- 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
148 lines
3.3 KiB
TypeScript
148 lines
3.3 KiB
TypeScript
import type { Prisma, UserRole } from '#shared/generated/prisma/client';
|
|
import { hash } from 'argon2';
|
|
import { randomBytes, randomInt } from 'node:crypto';
|
|
import { prisma } from '../integration/setup';
|
|
|
|
/** Default plaintext password used by createUser(); login tests rely on it. */
|
|
export const TEST_PASSWORD = 'super-secret-123';
|
|
|
|
let seq = 0;
|
|
|
|
// argon2 hashing is comparatively slow, so cache one hash per password.
|
|
const passwordHashes = new Map<string, Promise<string>>();
|
|
function hashPassword(password: string) {
|
|
if (!passwordHashes.has(password)) {
|
|
passwordHashes.set(password, hash(password));
|
|
}
|
|
return passwordHashes.get(password)!;
|
|
}
|
|
|
|
export async function createUser(
|
|
overrides: {
|
|
email?: string;
|
|
name?: string;
|
|
password?: string;
|
|
role?: UserRole;
|
|
} = {}
|
|
) {
|
|
seq += 1;
|
|
return prisma.user.create({
|
|
data: {
|
|
email: overrides.email ?? `user-${seq}-${randomInt(100_000)}@test.dev`,
|
|
name: overrides.name ?? `User ${seq}`,
|
|
password: await hashPassword(overrides.password ?? TEST_PASSWORD),
|
|
role: overrides.role
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createHunt(
|
|
creatorId: number,
|
|
overrides: Partial<Prisma.HuntUncheckedCreateInput> = {}
|
|
) {
|
|
seq += 1;
|
|
return prisma.hunt.create({
|
|
data: {
|
|
name_en: `Hunt ${seq}`,
|
|
name_de: `Jagd ${seq}`,
|
|
description_en: `Description ${seq}`,
|
|
description_de: `Beschreibung ${seq}`,
|
|
creatorId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createHuntMember(huntId: number, memberId: number) {
|
|
return prisma.huntMember.create({
|
|
data: { huntId, memberId }
|
|
});
|
|
}
|
|
|
|
export async function createQuest(
|
|
huntId: number,
|
|
overrides: Partial<Prisma.HuntQuestUncheckedCreateInput> = {}
|
|
) {
|
|
seq += 1;
|
|
return prisma.huntQuest.create({
|
|
data: {
|
|
title_en: `Quest ${seq}`,
|
|
title_de: `Aufgabe ${seq}`,
|
|
huntId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createTeam(
|
|
huntId: number,
|
|
ownerId: number,
|
|
overrides: Partial<Prisma.HuntTeamUncheckedCreateInput> = {}
|
|
) {
|
|
seq += 1;
|
|
return prisma.huntTeam.create({
|
|
data: {
|
|
name: `Team ${seq}`,
|
|
// same format as the production endpoint: 6 hex chars
|
|
password: randomBytes(3).toString('hex'),
|
|
huntId,
|
|
ownerId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createTeamMember(teamId: number, memberId: number) {
|
|
return prisma.teamMember.create({
|
|
data: { teamId, memberId }
|
|
});
|
|
}
|
|
|
|
export async function createAnswer(
|
|
{
|
|
teamId,
|
|
questId,
|
|
memberId
|
|
}: { teamId: number; questId: number; memberId: number },
|
|
overrides: Partial<Prisma.QuestAnswerUncheckedCreateInput> = {}
|
|
) {
|
|
return prisma.questAnswer.create({
|
|
data: {
|
|
teamId,
|
|
questId,
|
|
memberId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createFile(
|
|
creatorId: number,
|
|
overrides: Partial<Prisma.FileUncheckedCreateInput> = {}
|
|
) {
|
|
seq += 1;
|
|
const uuid = `file-${seq}-${randomInt(100_000)}`;
|
|
return prisma.file.create({
|
|
data: {
|
|
uuid,
|
|
url: `https://bucket.test/${uuid}`,
|
|
creatorId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function createReview(
|
|
answerId: number,
|
|
reviewerId: number,
|
|
overrides: Partial<Prisma.ReviewUncheckedCreateInput> = {}
|
|
) {
|
|
return prisma.review.create({
|
|
data: {
|
|
answerId,
|
|
reviewerId,
|
|
...overrides
|
|
}
|
|
});
|
|
}
|