diff --git a/.changeset/pink-apricots-fix.md b/.changeset/pink-apricots-fix.md new file mode 100644 index 000000000000..b9ba87d41c49 --- /dev/null +++ b/.changeset/pink-apricots-fix.md @@ -0,0 +1,5 @@ +--- +"pages-functions-example": patch +--- + +Added a Pages Functions example project for tests diff --git a/packages/example-pages-functions-app/functions/blog/[slug].ts b/packages/example-pages-functions-app/functions/blog/[slug].ts new file mode 100644 index 000000000000..0872ef621020 --- /dev/null +++ b/packages/example-pages-functions-app/functions/blog/[slug].ts @@ -0,0 +1,6 @@ +export const onRequestGet: PagesFunction = ({ params }) => { + const { slug } = params; + return new Response(`

A blog with a slug: ${slug}

`, { + headers: { "content-type": "text/html" }, + }); +}; diff --git a/packages/example-pages-functions-app/functions/date.ts b/packages/example-pages-functions-app/functions/date.ts new file mode 100644 index 000000000000..9fd0f03a2702 --- /dev/null +++ b/packages/example-pages-functions-app/functions/date.ts @@ -0,0 +1,3 @@ +export const onRequest = () => { + return new Response(new Date().toISOString()); +}; diff --git a/packages/example-pages-functions-app/functions/intercept.ts b/packages/example-pages-functions-app/functions/intercept.ts new file mode 100644 index 000000000000..94330049b6c7 --- /dev/null +++ b/packages/example-pages-functions-app/functions/intercept.ts @@ -0,0 +1,10 @@ +export const onRequest: PagesFunction = async ({ next }) => { + const response = await next(); + return new Response(response.body, { + status: response.status, + headers: { + ...Object.fromEntries(response.headers.entries()), + "x-set-from-functions": "true", + }, + }); +}; diff --git a/packages/example-pages-functions-app/package.json b/packages/example-pages-functions-app/package.json new file mode 100644 index 000000000000..5813b53851d0 --- /dev/null +++ b/packages/example-pages-functions-app/package.json @@ -0,0 +1,34 @@ +{ + "private": true, + "name": "pages-functions-example", + "scripts": { + "dev": "npx wrangler pages dev public --port 8789", + "test": "npx jest --forceExit" + }, + "devDependencies": { + "@cloudflare/workers-types": "^3.2.0", + "typescript": "^4.1.2", + "undici": "^4.13.0" + }, + "engines": { + "node": ">=14" + }, + "sideEffects": false, + "main": "dist/worker.js", + "jest": { + "restoreMocks": true, + "testTimeout": 30000, + "testRegex": ".*.(test|spec)\\.[jt]sx?$", + "transformIgnorePatterns": [ + "node_modules/(?!find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream)" + ], + "transform": { + "^.+\\.c?(t|j)sx?$": [ + "esbuild-jest", + { + "sourcemap": true + } + ] + } + } +} diff --git a/packages/example-pages-functions-app/public/index.html b/packages/example-pages-functions-app/public/index.html new file mode 100644 index 000000000000..9f735a6307ae --- /dev/null +++ b/packages/example-pages-functions-app/public/index.html @@ -0,0 +1 @@ +

Hello, world!

diff --git a/packages/example-pages-functions-app/tests/index.test.ts b/packages/example-pages-functions-app/tests/index.test.ts new file mode 100644 index 000000000000..7ad11e499a41 --- /dev/null +++ b/packages/example-pages-functions-app/tests/index.test.ts @@ -0,0 +1,63 @@ +import { spawn } from "child_process"; +import { resolve } from "path"; +import { fetch } from "undici"; +import type { Response } from "undici"; + +const waitUntilReady = async (url: string): Promise => { + let response: Response | undefined = undefined; + + while (response === undefined) { + await new Promise((resolvePromise) => setTimeout(resolvePromise, 500)); + + try { + response = await fetch(url); + } catch {} + } + + return response as Response; +}; + +const isWindows = process.platform === "win32"; + +describe("Remix", () => { + beforeAll(async () => { + const wranglerProcess = spawn("npm", ["run", "dev"], { + shell: isWindows, + cwd: resolve(__dirname, "../"), + env: { BROWSER: "none", ...process.env }, + }); + wranglerProcess.stdout.on("data", (chunk) => { + console.log(chunk.toString()); + }); + wranglerProcess.stderr.on("data", (chunk) => { + console.log(chunk.toString()); + }); + }); + + it("renders static pages", async () => { + const response = await waitUntilReady("http://localhost:8789/"); + const text = await response.text(); + expect(text).toContain("Hello, world!"); + }); + + it("intercepts static requests with next()", async () => { + const response = await waitUntilReady("http://localhost:8789/intercept"); + const text = await response.text(); + expect(text).toContain("Hello, world!"); + expect(response.headers.get("x-set-from-functions")).toBe("true"); + }); + + it("can make SSR responses", async () => { + const response = await waitUntilReady("http://localhost:8789/date"); + const text = await response.text(); + expect(text).toMatch(/\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d/); + }); + + it("can use parameters", async () => { + const response = await waitUntilReady( + "http://localhost:8789/blog/hello-world" + ); + const text = await response.text(); + expect(text).toContain("

A blog with a slug: hello-world

"); + }); +}); diff --git a/packages/example-pages-functions-app/tsconfig.json b/packages/example-pages-functions-app/tsconfig.json new file mode 100644 index 000000000000..554bd93e6b0a --- /dev/null +++ b/packages/example-pages-functions-app/tsconfig.json @@ -0,0 +1,9 @@ +{ + "include": ["functions"], + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "lib": ["ES2020"], + "types": ["@cloudflare/workers-types"] + } +}