import { expect, test } from "bun:test"; import { mkdtemp, writeFile, rm } from "node:fs/promises"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { astroComponent } from "../modules/astro/index.ts"; import { TemplateContext } from "../core/context.ts"; import { createViews } from "../views/api.ts"; import { authFromRequest, authGuard, authIntegration } from "../integrations/auth.ts"; import { App } from "../core/app.ts"; import { resolveConfig } from "../core/config.ts"; import { renderMdx } from "../modules/mdx/index.ts"; import { compileCss } from "../views/css/index.ts"; test("Astro imports compose with typed props and SPUG slots", async () => { const root = await mkdtemp(join(tmpdir(), "astro-compose-")); try { await writeFile(join(root, "Title.astro"), '---\nconst { title } = Astro.props;\n---\n

{title}

'); await writeFile(join(root, "Card.astro"), '---\nimport Title from "./Title.astro";\nconst { title } = Astro.props;\n---\n
<slot /></article>'); await writeFile(join(root, "index.spug"), 'component Card\n title: "Composed"\n render content\n p Slot body'); const context = new TemplateContext().import("Card", astroComponent(join(root, "Card.astro"))); const views = createViews({ viewsDir: root, context }); const html = await views.renderFile("index"); expect(html).toContain("<h2>Composed</h2>"); expect(html).toContain("<p>Slot body</p>"); } finally { await rm(root, { recursive: true, force: true }); } }); test("form authentication issues an opaque session and rejects forged identity cookies", async () => { const app = await App.create({ config: resolveConfig(), integrations: [authIntegration({ login: (email, password) => password === "secret" ? { id: email } : undefined })] }); const response = await app.fetch(new Request("https://example.test/auth/login", { method: "POST", headers: { origin: "https://example.test" }, body: new URLSearchParams({ email: "ada", password: "secret" }) })); expect(response.status).toBe(302); const cookie = response.headers.get("set-cookie")!; expect((await authFromRequest(new Request("https://example.test", { headers: { cookie } })))?.id).toBe("ada"); expect(await authFromRequest(new Request("https://example.test", { headers: { cookie: 'muddle_auth=%7B%22id%22%3A%22admin%22%7D' } }))).toBeUndefined(); }); test("OAuth callback validates browser-bound state and exchanges a PKCE code", async () => { const original = globalThis.fetch; let exchanged = false; globalThis.fetch = (async (input: string | URL | Request, init?: RequestInit) => { if (String(input).endsWith("/token")) { const body = init?.body as URLSearchParams; expect(body.get("code_verifier")?.length).toBeGreaterThan(40); exchanged = true; return Response.json({ access_token: "test-token" }); } return Response.json({ sub: "oauth-user" }); }) as typeof fetch; try { const app = await App.create({ config: resolveConfig(), integrations: [authIntegration({ providers: [{ name: "test", authorizationUrl: "https://provider.test/authorize", tokenUrl: "https://provider.test/token", userInfoUrl: "https://provider.test/user", clientId: "test", redirectUri: "https://app.test/auth/test/callback", identity: (profile) => ({ id: String(profile.sub) }) }] })] }); const start = await app.fetch(new Request("https://app.test/auth/test")); const authorization = new URL(start.headers.get("location")!); expect(authorization.searchParams.get("code_challenge_method")).toBe("S256"); const callback = `https://app.test/auth/test/callback?code=test-code&state=${authorization.searchParams.get("state")}`; expect((await app.fetch(new Request(callback))).status).toBe(400); const response = await app.fetch(new Request(callback, { headers: { cookie: start.headers.get("set-cookie")! } })); expect(response.status).toBe(302); expect(exchanged).toBe(true); expect((await app.fetch(new Request(callback, { headers: { cookie: start.headers.get("set-cookie")! } }))).status).toBe(400); } finally { globalThis.fetch = original; } });