import { createId } from "@paralleldrive/cuid2"; import { expect, test, type BrowserContext, type Page } from "@playwright/test"; import { Lucia, type Cookie } from "lucia"; import createClient from "openapi-fetch"; import * as schema from "~/drizzle/schema"; import { paths } from "~/types/discord"; import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle"; import "dotenv/config"; import { drizzle } from "drizzle-orm/postgres-js"; import postgres from "postgres"; const queryClient = postgres(process.env.DATABASE_URL!); const db = drizzle(queryClient, { schema, }); const adapter = new DrizzlePostgreSQLAdapter(db, schema.sessions, schema.users); export const lucia = new Lucia(adapter, { getUserAttributes: (attributes) => attributes, }); let context: BrowserContext; let page: Page; let sessionCookie: Cookie | undefined; test.describe.serial("User auth process", () => { test.beforeAll(async ({ browser }) => { context = await browser.newContext(); page = await context.newPage(); }); test.beforeEach(async () => { if (!sessionCookie) return; const sameSiteProps = { lax: "Lax", strict: "Strict", none: "None", } as const; const expires = sessionCookie.attributes.expires ? sessionCookie.attributes.expires.getTime() / 1000 : undefined; const sameSite = sessionCookie.attributes.sameSite ? sameSiteProps[sessionCookie.attributes.sameSite] : undefined; await context.addCookies([ { name: sessionCookie.name, value: sessionCookie.value, ...sessionCookie.attributes, sameSite, expires, secure: false, domain: "localhost", path: "/", }, ]); }); test.afterAll(async () => { await context.close(); }); test("Landing page", async () => { await page.goto("/"); await page.waitForLoadState("load"); expect(await page.screenshot()).toMatchSnapshot("landing_page.png"); }); test("Unauthorized Access Redirect Test", async () => { await page.goto("/config"); await page.waitForURL("/"); }); test("Generate auth session for further tests", async () => { const { GET } = createClient({ baseUrl: "https://discord.com/api/v10", }); const discordUserResponse = await GET("/users/@me", { headers: { Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN}`, }, }); if (discordUserResponse.error) throw discordUserResponse.error; const discordUser = discordUserResponse.data; const userId = createId(); await db.insert(schema.users).values({ id: userId, discord_id: discordUser.id, name: discordUser.global_name, image: discordUser.avatar, }); const session = await lucia.createSession( userId, {}, { sessionId: createId() }, ); sessionCookie = lucia.createSessionCookie(session.id); await db .insert(schema.discordTokens) .values({ userId, accessToken: "tokens.accessToken", expiresAt: sessionCookie.attributes.expires ?? new Date(), refreshToken: "tokens.refreshToken", }) .returning() .execute(); }); test("Landing page when logged in", async () => { await page.goto("/"); await page.waitForLoadState("load"); expect(await page.screenshot()).toMatchSnapshot( "landing_page_logged_in.png", ); }); });