diff --git a/package.json b/package.json index 309ef93..e914b97 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "test:unit": "vitest --run --passWithNoTests", "test:unit:watch": "vitest --watch --passWithNoTests", "pretest:e2e": "bun scripts/other/confirm.js \"Are you sure you want to run e2e tests? This will reset your database (yes/no)\"", - "test:e2e": "bun run db:reset && bunx playwright test", + "test:e2e": "bun run db:reset && bunx playwright test && bun run db:reset", "test:e2e:results": "bunx playwright show-report", "coverage": "vitest --run --coverage --passWithNoTests", "db:migrate-dev": "prisma migrate dev --skip-seed", diff --git a/prisma/seed.ts b/prisma/seed.ts index adef7ab..e71fa60 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import { CamelCasePlugin, Kysely, PostgresDialect } from 'kysely'; import pg from 'pg'; -import type { DB } from '../src/lib/db/schema'; +import type { DB } from '$lib/db/schema'; const pool = new pg.Pool({ connectionString: process.env.DB_URL }); const dialect = new PostgresDialect({ pool }); diff --git a/prisma/seed/flight.ts b/prisma/seed/flight.ts new file mode 100644 index 0000000..95af19a --- /dev/null +++ b/prisma/seed/flight.ts @@ -0,0 +1,39 @@ +import { format } from 'date-fns'; +import { Kysely } from 'kysely'; + +import type { DB } from '../../src/lib/db/schema'; +import type { CreateFlight } from '../../src/lib/db/types'; + +export const seedFlight = async (db: Kysely, userId: string) => { + await createFlight(db, { + seats: [ + { userId, seat: 'window', seatNumber: '11F', seatClass: 'economy' }, + ], + from: 'EKCH', + to: 'ESSA', + date: format(new Date(), 'yyyy-MM-dd'), + duration: 70 * 60, + }); +}; + +const createFlight = async (db: Kysely, data: CreateFlight) => { + await db.transaction().execute(async (trx) => { + const { seats, ...flightData } = data; + const resp = await trx + .insertInto('flight') + .values(flightData) + .returning('id') + .executeTakeFirstOrThrow(); + + const seatData = seats.map((seat) => ({ + flightId: resp.id, + userId: seat.userId, + guestName: seat.guestName, + seat: seat.seat, + seatNumber: seat.seatNumber, + seatClass: seat.seatClass, + })); + + await trx.insertInto('seat').values(seatData).executeTakeFirstOrThrow(); + }); +}; diff --git a/prisma/seed/initial-seed.ts b/prisma/seed/initial-seed.ts index ba1eec5..4fa5524 100644 --- a/prisma/seed/initial-seed.ts +++ b/prisma/seed/initial-seed.ts @@ -2,8 +2,10 @@ import { Kysely } from 'kysely'; import type { DB } from '../../src/lib/db/schema'; +import { seedFlight } from './flight'; import { seedUser } from './user'; export const seedDatabase = async (db: Kysely) => { - await seedUser(db); + const user = await seedUser(db); + await seedFlight(db, user.id); }; diff --git a/prisma/seed/user.ts b/prisma/seed/user.ts index 8f138bb..866b331 100644 --- a/prisma/seed/user.ts +++ b/prisma/seed/user.ts @@ -13,12 +13,13 @@ export const SEED_USER = { } as const; export const seedUser = async (db: Kysely) => { - await db + return await db .insertInto('user') .values({ ...SEED_USER, id: generateId(15), password: await hashPassword(SEED_USER.password), }) - .execute(); + .returning('id') + .executeTakeFirstOrThrow(); }; diff --git a/tests/e2e/fixtures/url.ts b/tests/e2e/fixtures/url.ts new file mode 100644 index 0000000..915172d --- /dev/null +++ b/tests/e2e/fixtures/url.ts @@ -0,0 +1,3 @@ +export const isPathname = (pathname: string) => { + return (url: URL) => url.pathname === pathname; +}; diff --git a/tests/e2e/user/access.spec.ts b/tests/e2e/user/access.spec.ts index c03f447..ae249ba 100644 --- a/tests/e2e/user/access.spec.ts +++ b/tests/e2e/user/access.spec.ts @@ -1,11 +1,11 @@ import { expect, test } from '@playwright/test'; import { signin } from '../fixtures/authentication'; +import { isPathname } from '../fixtures/url'; test('no unauthorized access', async ({ page }) => { await page.goto('/'); - const url = new URL(page.url()); - expect(url.pathname).toBe('/login'); + await page.waitForURL(isPathname('/login')); }); test('can sign in', async ({ page }) => { diff --git a/tests/e2e/user/setup.spec.ts b/tests/e2e/user/setup.spec.ts index e191075..73367b6 100644 --- a/tests/e2e/user/setup.spec.ts +++ b/tests/e2e/user/setup.spec.ts @@ -1,5 +1,6 @@ import { SEED_USER } from '../../../prisma/seed/user'; import { test } from '../fixtures/db'; +import { isPathname } from '../fixtures/url'; test('can complete set up', async ({ page, db }) => { await db.deleteFrom('user').execute(); @@ -12,5 +13,10 @@ test('can complete set up', async ({ page, db }) => { await page.fill('input[name="displayName"]', SEED_USER.displayName); await page.click('button[type="submit"]'); - await page.waitForURL((url) => url.pathname === '/'); + await page.waitForURL(isPathname('/')); +}); + +test('cannot complete set up if user already exists', async ({ page }) => { + await page.goto('/setup'); + await page.waitForURL(isPathname('/login')); }); diff --git a/vite.config.ts b/vite.config.ts index 799bb3c..d8a000e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,6 @@ +import { o7Icon } from '@o7/icon/vite'; import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; -import { o7Icon } from '@o7/icon/vite'; export default defineConfig({ plugins: [o7Icon(), sveltekit()],