1import * as Playwright from "@alchemy.run/cloudflare-test-tools/e2e/Playwright";
2import { expect, test } from "@playwright/test";
3
4const SECRET = "s3cret-from-binding";
5
6// Both modes run the shared contract. Live serves the adapter-emitted
7// `dist/server/worker.js` under miniflare (asset-first, SSR on miss); dev is
8// Octane's own Vite dev server (the plugin's in-process SSR middleware).
9for (const mode of Playwright.SERVER_METHODS) {
10 test.describe(mode, () => {
11 const it = Playwright.make(mode);
12
13 it("server-renders the home page", async ({ page, server }) => {
14 const response = await page.goto(server.url.toString());
15 expect(response?.status()).toBe(200);
16 await expect(page.getByTestId("page-marker")).toHaveText(
17 "OCTANE_FIXTURE",
18 );
19 });
20
21 it("hydrates the client-interactive counter", async ({ page, server }) => {
22 await page.goto(server.url.toString());
23 await expect(page.locator("#count")).toHaveText("count:0");
24 // wait for hydration before interacting (useEffect flips the marker)
25 await expect(page.locator("#increment")).toHaveAttribute(
26 "data-hydrated",
27 "true",
28 );
29 await page.click("#increment");
30 await expect(page.locator("#count")).toHaveText("count:1");
31 await page.click("#increment");
32 await expect(page.locator("#count")).toHaveText("count:2");
33 });
34
35 it("serves static assets asset-first", async ({ server }) => {
36 const response = await server.fetch("/robots.txt");
37 expect(response.status).toBe(200);
38 expect(await response.text()).toContain("User-agent: *");
39 });
40
41 it("runs the server route", async ({ server }) => {
42 const body = await server.fetchJson<{
43 marker: string;
44 secret: string | null;
45 hasWaitUntil: boolean;
46 }>("/api/hello");
47 expect(body.marker).toBe("api-route-ok");
48 if (mode === "live") {
49 // `context.platform` is the adapter-forwarded `{ env, ctx }`.
50 expect(body.secret).toBe(SECRET);
51 expect(body.hasWaitUntil).toBe(true);
52 } else {
53 // Octane's dev middleware supplies no platform (upstream
54 // limitation) — the handler degrades to null/false.
55 expect(body.secret).toBeNull();
56 expect(body.hasWaitUntil).toBe(false);
57 }
58 });
59 });
60}