- PGlite (in-memory WASM Postgres) hosted in a child process, exposed via TCP socket; real migrations applied with prisma migrate deploy - Vitest harness (vitest.integration.config.ts, global-setup spawns PGlite + built Nuxt server, per-test TRUNCATE, factories, cookie-jar API client); no mocks, zero production code changes - 50 tests across auth, hunt, team, submit, review, showcase, diashow incl. SuperJSON envelope check; *.itest.ts keeps bun test untouched - CI: parallel unit + integration jobs in .github/workflows/test.yml - tests/ covered by nuxt typecheck via tests/tsconfig.json reference
138 lines
4.0 KiB
TypeScript
138 lines
4.0 KiB
TypeScript
import { beforeEach, describe, expect, it } from 'vitest';
|
|
import { newClient } from '../helpers/api';
|
|
import { resetDatabase } from '../helpers/database';
|
|
import {
|
|
createAnswer,
|
|
createFile,
|
|
createHunt,
|
|
createQuest,
|
|
createTeam,
|
|
createUser,
|
|
TEST_PASSWORD
|
|
} from '../helpers/factories';
|
|
import { prisma } from './setup';
|
|
|
|
beforeEach(resetDatabase);
|
|
|
|
/**
|
|
* Hunt with one quest and three finalized answers:
|
|
* - a public picture (shown)
|
|
* - a private picture (hidden)
|
|
* - no picture at all (hidden)
|
|
*/
|
|
async function seedDiashow(reveal: boolean) {
|
|
const creator = await createUser();
|
|
const hunt = await createHunt(creator.id, {
|
|
revealAnswers: reveal,
|
|
revealQuests: reveal
|
|
});
|
|
const quest = await createQuest(hunt.id);
|
|
const owner = await createUser();
|
|
const team = await createTeam(hunt.id, owner.id);
|
|
|
|
const answerPublic = await createAnswer({
|
|
teamId: team.id,
|
|
questId: quest.id,
|
|
memberId: owner.id
|
|
});
|
|
const publicFile = await createFile(owner.id, { answerId: answerPublic.id });
|
|
await prisma.questAnswer.update({
|
|
where: { id: answerPublic.id },
|
|
data: { pictureId: publicFile.id, final: true }
|
|
});
|
|
|
|
const answerPrivate = await createAnswer({
|
|
teamId: team.id,
|
|
questId: quest.id,
|
|
memberId: owner.id
|
|
});
|
|
const privateFile = await createFile(owner.id, {
|
|
answerId: answerPrivate.id,
|
|
private: true
|
|
});
|
|
await prisma.questAnswer.update({
|
|
where: { id: answerPrivate.id },
|
|
data: { pictureId: privateFile.id, final: true }
|
|
});
|
|
|
|
await createAnswer(
|
|
{ teamId: team.id, questId: quest.id, memberId: owner.id },
|
|
{ final: true, text: 'no picture' }
|
|
);
|
|
|
|
return { hunt, quest, team, publicFile };
|
|
}
|
|
|
|
describe('diashow (GET /api/hunt/[huntId]/diashow)', () => {
|
|
it('returns 404 for unknown hunts', async () => {
|
|
const res = await newClient().get('/api/hunt/999999/diashow');
|
|
expect(res.status).toBe(404);
|
|
});
|
|
|
|
it('blocks anonymous users before answers are revealed', async () => {
|
|
const { hunt } = await seedDiashow(false);
|
|
const res = await newClient().get(`/api/hunt/${hunt.id}/diashow`);
|
|
expect(res.status).toBe(403);
|
|
});
|
|
|
|
it('lets the hunt creator peek before reveal', async () => {
|
|
const { hunt } = await seedDiashow(false);
|
|
const creator = await prisma.user.findFirstOrThrow({
|
|
where: { huntsCreated: { some: { id: hunt.id } } }
|
|
});
|
|
|
|
const client = newClient();
|
|
await client.login(creator.email, TEST_PASSWORD);
|
|
const res = await client.get(`/api/hunt/${hunt.id}/diashow`);
|
|
expect(res.status).toBe(200);
|
|
});
|
|
|
|
it('only shows finalized answers with public pictures', async () => {
|
|
const { hunt, quest, team, publicFile } = await seedDiashow(true);
|
|
|
|
const res = await newClient().get(`/api/hunt/${hunt.id}/diashow`);
|
|
expect(res.status).toBe(200);
|
|
const body = await res.json();
|
|
|
|
expect(body.id).toBe(hunt.id);
|
|
expect(body.quests).toHaveLength(1);
|
|
expect(body.quests[0].id).toBe(quest.id);
|
|
expect(body.quests[0].answers).toHaveLength(1);
|
|
expect(body.quests[0].answers[0].picture.url).toBe(publicFile.url);
|
|
expect(body.quests[0].answers[0].team).toMatchObject({
|
|
id: team.id,
|
|
name: team.name
|
|
});
|
|
});
|
|
|
|
it('omits quests whose final answers are all private', async () => {
|
|
const creator = await createUser();
|
|
const hunt = await createHunt(creator.id, {
|
|
revealAnswers: true,
|
|
revealQuests: true
|
|
});
|
|
const quest = await createQuest(hunt.id);
|
|
const owner = await createUser();
|
|
const team = await createTeam(hunt.id, owner.id);
|
|
|
|
const answer = await createAnswer({
|
|
teamId: team.id,
|
|
questId: quest.id,
|
|
memberId: owner.id
|
|
});
|
|
const privateFile = await createFile(owner.id, {
|
|
answerId: answer.id,
|
|
private: true
|
|
});
|
|
await prisma.questAnswer.update({
|
|
where: { id: answer.id },
|
|
data: { pictureId: privateFile.id, final: true }
|
|
});
|
|
|
|
const res = await newClient().get(`/api/hunt/${hunt.id}/diashow`);
|
|
expect(res.status).toBe(200);
|
|
const body = await res.json();
|
|
expect(body.quests).toEqual([]);
|
|
});
|
|
});
|