1// Async (non-Effect) Worker that drives a Browser Rendering binding the way
2// real users do — through `@cloudflare/puppeteer` (acquire a session, open a
3// page, inspect it). Used by Browser.local.test.ts both against the local
4// Chrome-backed simulator and (piped through `Alchemy.remote()`) against the real
5// Browser Rendering service via the remote-bindings proxy.
6import puppeteer from "@cloudflare/puppeteer";
7
8const PAGE_HTML =
9 "<html><head><title>Local Browser Test</title></head>" +
10 "<body><h1>Hello from the local browser</h1></body></html>";
11
12type Env = Record<string, unknown>;
13
14export default {
15 async fetch(request: Request, env: Env): Promise<Response> {
16 const url = new URL(request.url);
17 try {
18 if (url.pathname === "/title") {
19 const browser = await puppeteer.launch(env.BROWSER as any);
20 try {
21 const page = await browser.newPage();
22 await page.setContent(PAGE_HTML);
23 const title = await page.title();
24 const heading = await page.$eval("h1", (el) => el.textContent);
25 return Response.json({ title, heading });
26 } finally {
27 await browser.close();
28 }
29 }
30 if (url.pathname === "/screenshot") {
31 const browser = await puppeteer.launch(env.BROWSER as any);
32 try {
33 const page = await browser.newPage();
34 await page.setContent(PAGE_HTML);
35 const screenshot = await page.screenshot();
36 return new Response(screenshot as any, {
37 headers: { "content-type": "image/png" },
38 });
39 } finally {
40 await browser.close();
41 }
42 }
43 return new Response("ok");
44 } catch (e: any) {
45 return new Response(`browser fixture error: ${e?.stack ?? String(e)}`, {
46 status: 500,
47 });
48 }
49 },
50};