diff --git a/examples/e2e/app-router/sst-env.d.ts b/examples/e2e/app-router/sst-env.d.ts deleted file mode 100644 index 59d33569..00000000 --- a/examples/e2e/app-router/sst-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/e2e/pages-router/.env.production b/examples/e2e/pages-router/.env.production new file mode 100644 index 00000000..82e6f9e7 --- /dev/null +++ b/examples/e2e/pages-router/.env.production @@ -0,0 +1 @@ +SOME_PROD_VAR=bar \ No newline at end of file diff --git a/examples/e2e/pages-router/.gitignore b/examples/e2e/pages-router/.gitignore new file mode 100644 index 00000000..93e8ff69 --- /dev/null +++ b/examples/e2e/pages-router/.gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +.open-next +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/examples/e2e/pages-router/README.md b/examples/e2e/pages-router/README.md new file mode 100644 index 00000000..ecdf4f78 --- /dev/null +++ b/examples/e2e/pages-router/README.md @@ -0,0 +1,3 @@ +# Pages Router + +This project uses the Pages Router exclusively. diff --git a/examples/e2e/pages-router/e2e/404.test.ts b/examples/e2e/pages-router/e2e/404.test.ts new file mode 100644 index 00000000..31605e83 --- /dev/null +++ b/examples/e2e/pages-router/e2e/404.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from "@playwright/test"; + +test("should return 404 on a route not corresponding to any route", async ({ page }) => { + const result = await page.goto("/not-existing/route"); + expect(result).toBeDefined(); + expect(result?.status()).toBe(404); + const headers = result?.headers(); + expect(headers?.["cache-control"]).toBe("private, no-cache, no-store, max-age=0, must-revalidate"); +}); diff --git a/examples/e2e/pages-router/e2e/data.test.ts b/examples/e2e/pages-router/e2e/data.test.ts new file mode 100644 index 00000000..919fcc6c --- /dev/null +++ b/examples/e2e/pages-router/e2e/data.test.ts @@ -0,0 +1,21 @@ +import { expect, test } from "@playwright/test"; + +test("fix _next/data", async ({ page }) => { + await page.goto("/"); + + const isrJson = page.waitForResponse("/_next/data/*/en/isr.json"); + await page.locator('[href="/isr/"]').click(); + const response = await isrJson; + expect(response.ok()).toBe(true); + expect(response.request().url()).toMatch(/\/_next\/data\/.*\/en\/isr\.json$/); + await page.waitForURL("/isr/"); + + const homeJson = page.waitForResponse("/_next/data/*/en.json"); + await page.locator('[href="/"]').click(); + const response2 = await homeJson; + expect(response2.ok()).toBe(true); + expect(response2.request().url()).toMatch(/\/_next\/data\/.*\/en\.json$/); + await page.waitForURL("/"); + const body = await response2.json(); + expect(body).toEqual({ pageProps: { hello: "world" }, __N_SSG: true }); +}); diff --git a/examples/e2e/pages-router/e2e/header.test.ts b/examples/e2e/pages-router/e2e/header.test.ts new file mode 100644 index 00000000..7811be1b --- /dev/null +++ b/examples/e2e/pages-router/e2e/header.test.ts @@ -0,0 +1,12 @@ +import { expect, test } from "@playwright/test"; + +test("should test if poweredByHeader adds the correct headers ", async ({ page }) => { + const result = await page.goto("/"); + expect(result).toBeDefined(); + expect(result?.status()).toBe(200); + const headers = result?.headers(); + + // Both these headers should be present cause poweredByHeader is true in pagesRouter + expect(headers?.["x-powered-by"]).toBe("Next.js"); + expect(headers?.["x-opennext"]).toBe("1"); +}); diff --git a/examples/e2e/pages-router/e2e/i18n.test.ts b/examples/e2e/pages-router/e2e/i18n.test.ts new file mode 100644 index 00000000..4271f93d --- /dev/null +++ b/examples/e2e/pages-router/e2e/i18n.test.ts @@ -0,0 +1,17 @@ +import { expect, test } from "@playwright/test"; + +test("Next config headers with i18n", async ({ page }) => { + const responsePromise = page.waitForResponse((response) => { + return response.status() === 200; + }); + await page.goto("/"); + + const response = await responsePromise; + // Response header should be set + const headers = response.headers(); + // Headers from next.config.js should be set + expect(headers["x-custom-header"]).toEqual("my custom header value"); + + // Headers from middleware should be set + expect(headers["x-from-middleware"]).toEqual("true"); +}); diff --git a/examples/e2e/pages-router/e2e/isr.test.ts b/examples/e2e/pages-router/e2e/isr.test.ts new file mode 100644 index 00000000..aac897d2 --- /dev/null +++ b/examples/e2e/pages-router/e2e/isr.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from "@playwright/test"; + +test("Incremental Static Regeneration", async ({ page }) => { + test.setTimeout(45000); + await page.goto("/"); + await page.locator("[href='/isr/']").click(); + await page.waitForURL("/isr/"); + // Load the page a couple times to regenerate ISR + + let el = page.getByText("Time:"); + // Track the static time + let time = await el.textContent(); + let newTime: typeof time; + let tempTime = time; + do { + await page.waitForTimeout(1000); + await page.reload(); + time = tempTime; + el = page.getByText("Time:"); + newTime = await el.textContent(); + tempTime = newTime; + } while (time !== newTime); + await page.reload(); + await page.waitForTimeout(1000); + el = page.getByText("Time:"); + const midTime = await el.textContent(); + // Expect that the time is still stale + expect(midTime).toEqual(newTime); + + // Wait 10 + 1 seconds for ISR to regenerate time + await page.waitForTimeout(11000); + let finalTime = newTime; + do { + await page.waitForTimeout(2000); + el = page.getByText("Time:"); + finalTime = await el.textContent(); + await page.reload(); + } while (newTime === finalTime); + + expect(newTime).not.toEqual(finalTime); +}); diff --git a/examples/e2e/pages-router/e2e/playwright.config.ts b/examples/e2e/pages-router/e2e/playwright.config.ts new file mode 100644 index 00000000..602e4861 --- /dev/null +++ b/examples/e2e/pages-router/e2e/playwright.config.ts @@ -0,0 +1,54 @@ +import { defineConfig, devices } from "@playwright/test"; +import type nodeProcess from "node:process"; + +declare const process: typeof nodeProcess; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./", + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: "http://localhost:8791", + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + // TODO(vicb): enable all browsers + // { + // name: "firefox", + // use: { ...devices["Desktop Firefox"] }, + // }, + // { + // name: "webkit", + // use: { ...devices["Desktop Safari"] }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: "pnpm preview", + url: "http://localhost:8791", + reuseExistingServer: !process.env.CI, + timeout: 70_000, + }, +}); diff --git a/examples/e2e/pages-router/e2e/redirect.test.ts b/examples/e2e/pages-router/e2e/redirect.test.ts new file mode 100644 index 00000000..3a8b290a --- /dev/null +++ b/examples/e2e/pages-router/e2e/redirect.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "@playwright/test"; + +test("Single redirect", async ({ page }) => { + await page.goto("/next-config-redirect-without-locale-support/"); + + await page.waitForURL("https://opennext.js.org/"); + const el = page.getByRole("heading", { name: "OpenNext" }); + await expect(el).toBeVisible(); +}); + +test("Redirect with default locale support", async ({ page }) => { + await page.goto("/redirect-with-locale/"); + + await page.waitForURL("/ssr/"); + const el = page.getByText("SSR"); + await expect(el).toBeVisible(); +}); + +test("Redirect with locale support", async ({ page }) => { + await page.goto("/nl/redirect-with-locale/"); + + await page.waitForURL("/nl/ssr/"); + const el = page.getByText("SSR"); + await expect(el).toBeVisible(); +}); diff --git a/examples/e2e/pages-router/e2e/rewrite.test.ts b/examples/e2e/pages-router/e2e/rewrite.test.ts new file mode 100644 index 00000000..668668d5 --- /dev/null +++ b/examples/e2e/pages-router/e2e/rewrite.test.ts @@ -0,0 +1,25 @@ +import { expect, test } from "@playwright/test"; +import { validateMd5 } from "../../utils"; + +const EXT_PNG_MD5 = "405f45cc3397b09717a13ebd6f1e027b"; + +test("Single Rewrite", async ({ page }) => { + await page.goto("/rewrite"); + + const el = page.getByText("Nextjs Pages Router"); + await expect(el).toBeVisible(); +}); + +test("Rewrite with query", async ({ page }) => { + await page.goto("/rewriteUsingQuery?d=ssr"); + + const el = page.getByText("SSR"); + await expect(el).toBeVisible(); +}); + +test("Rewrite to external image", async ({ request }) => { + const response = await request.get("/external-on-image"); + expect(response.status()).toBe(200); + expect(response.headers()["content-type"]).toBe("image/png"); + expect(validateMd5(await response.body(), EXT_PNG_MD5)).toBe(true); +}); diff --git a/examples/e2e/pages-router/e2e/ssr.test.ts b/examples/e2e/pages-router/e2e/ssr.test.ts new file mode 100644 index 00000000..93c88f2c --- /dev/null +++ b/examples/e2e/pages-router/e2e/ssr.test.ts @@ -0,0 +1,33 @@ +import { expect, test } from "@playwright/test"; + +test("Server Side Render", async ({ page }) => { + await page.goto("/"); + await page.locator('[href="/ssr/"]').click(); + + await page.waitForURL("/ssr/"); + let el = page.getByText("Time:"); + await expect(el).toBeVisible(); + let time = await el.textContent(); + + await page.reload(); + + el = page.getByText("Time:"); + let newTime = await el.textContent(); + await expect(el).toBeVisible(); + + for (let i = 0; i < 5; i++) { + await page.reload(); + el = page.getByText("Time:"); + newTime = await el.textContent(); + await expect(el).toBeVisible(); + expect(time).not.toEqual(newTime); + time = newTime; + await page.waitForTimeout(250); + } +}); + +test("Server Side Render with env", async ({ page }) => { + await page.goto("/ssr/"); + const el = page.getByText("Env:"); + expect(await el.textContent()).toEqual("Env: bar"); +}); diff --git a/examples/e2e/pages-router/e2e/trailing.test.ts b/examples/e2e/pages-router/e2e/trailing.test.ts new file mode 100644 index 00000000..4a9179e2 --- /dev/null +++ b/examples/e2e/pages-router/e2e/trailing.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from "@playwright/test"; + +test("trailingSlash redirect", async ({ page }) => { + const response = await page.goto("/ssr"); + + expect(response?.request().redirectedFrom()?.url()).toMatch(/\/ssr$/); + expect(response?.request().url()).toMatch(/\/ssr\/$/); +}); + +test("trailingSlash redirect with search parameters", async ({ page }) => { + const response = await page.goto("/ssr?happy=true"); + + expect(response?.request().redirectedFrom()?.url()).toMatch(/\/ssr\?happy=true$/); + expect(response?.request().url()).toMatch(/\/ssr\/\?happy=true$/); +}); diff --git a/examples/e2e/pages-router/next.config.ts b/examples/e2e/pages-router/next.config.ts new file mode 100644 index 00000000..ea3e7858 --- /dev/null +++ b/examples/e2e/pages-router/next.config.ts @@ -0,0 +1,67 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + transpilePackages: ["@example/shared", "react", "react-dom"], + i18n: { + locales: ["en", "nl"], + defaultLocale: "en", + }, + cleanDistDir: true, + reactStrictMode: true, + output: "standalone", + // outputFileTracingRoot: "../sst", + typescript: { + ignoreBuildErrors: true, + }, + eslint: { + ignoreDuringBuilds: true, + }, + headers: async () => [ + { + source: "/", + headers: [ + { + key: "x-custom-header", + value: "my custom header value", + }, + ], + }, + ], + rewrites: async () => [ + { source: "/rewrite", destination: "/", locale: false }, + { + source: "/rewriteUsingQuery", + destination: "/:destination/", + locale: false, + has: [ + { + type: "query", + key: "d", + value: "(?\\w+)", + }, + ], + }, + { + source: "/external-on-image", + destination: "https://opennext.js.org/share.png", + }, + ], + redirects: async () => [ + { + source: "/next-config-redirect-without-locale-support/", + destination: "https://opennext.js.org/", + permanent: false, + basePath: false, + locale: false, + }, + { + source: "/redirect-with-locale/", + destination: "/ssr/", + permanent: false, + }, + ], + trailingSlash: true, + poweredByHeader: true, +}; + +export default nextConfig; diff --git a/examples/e2e/pages-router/open-next.config.ts b/examples/e2e/pages-router/open-next.config.ts new file mode 100644 index 00000000..0f7794ff --- /dev/null +++ b/examples/e2e/pages-router/open-next.config.ts @@ -0,0 +1,25 @@ +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next"; + +const config: OpenNextConfig = { + default: { + override: { + wrapper: "cloudflare-node", + converter: "edge", + // Unused implementation + incrementalCache: "dummy", + tagCache: "dummy", + queue: "dummy", + }, + }, + + middleware: { + external: true, + override: { + wrapper: "cloudflare-edge", + converter: "edge", + proxyExternalRequest: "fetch", + }, + }, +}; + +export default config; diff --git a/examples/e2e/pages-router/package.json b/examples/e2e/pages-router/package.json new file mode 100644 index 00000000..933cdc4c --- /dev/null +++ b/examples/e2e/pages-router/package.json @@ -0,0 +1,34 @@ +{ + "name": "pages-router", + "version": "0.1.0", + "private": true, + "scripts": { + "openbuild": "node ../../packages/open-next/dist/index.js build --build-command \"npx turbo build\"", + "dev": "next dev --turbopack --port 3002", + "build": "next build", + "start": "next start --port 3002", + "lint": "next lint", + "clean": "rm -rf .turbo node_modules .next .open-next", + "build:worker": "pnpm opennextjs-cloudflare", + "dev:worker": "wrangler dev --port 8791 --inspector-port 9351", + "preview": "pnpm build:worker && pnpm dev:worker", + "e2e-fix": "playwright test -c e2e/playwright.config.ts" + }, + "dependencies": { + "@opennextjs/cloudflare": "workspace:*", + "@example/shared": "workspace:*", + "next": "catalog:e2e", + "react": "catalog:e2e", + "react-dom": "catalog:e2e" + }, + "devDependencies": { + "@playwright/test": "catalog:", + "@types/node": "catalog:e2e", + "@types/react": "catalog:e2e", + "@types/react-dom": "catalog:e2e", + "autoprefixer": "catalog:e2e", + "postcss": "catalog:e2e", + "tailwindcss": "catalog:e2e", + "typescript": "catalog:default" + } +} diff --git a/examples/e2e/pages-router/postcss.config.js b/examples/e2e/pages-router/postcss.config.js new file mode 100644 index 00000000..aae516f5 --- /dev/null +++ b/examples/e2e/pages-router/postcss.config.js @@ -0,0 +1,8 @@ +module.exports = { + plugins: { + tailwindcss: { + content: ["./src/**/*.{js,ts,jsx,tsx,mdx}", "../../examples/shared/**/*.{jsx,tsx}"], + }, + autoprefixer: {}, + }, +}; diff --git a/examples/e2e/pages-router/public/favicon.ico b/examples/e2e/pages-router/public/favicon.ico new file mode 100644 index 00000000..4ba005f2 Binary files /dev/null and b/examples/e2e/pages-router/public/favicon.ico differ diff --git a/examples/e2e/pages-router/public/static/frank.webp b/examples/e2e/pages-router/public/static/frank.webp new file mode 100644 index 00000000..b2cc67f0 Binary files /dev/null and b/examples/e2e/pages-router/public/static/frank.webp differ diff --git a/examples/e2e/pages-router/src/middleware.ts b/examples/e2e/pages-router/src/middleware.ts new file mode 100644 index 00000000..682614fd --- /dev/null +++ b/examples/e2e/pages-router/src/middleware.ts @@ -0,0 +1,14 @@ +import type { NextRequest } from "next/server"; +import { NextResponse } from "next/server"; + +export function middleware(request: NextRequest) { + return NextResponse.next({ + headers: { + "x-from-middleware": "true", + }, + }); +} + +export const config = { + matcher: ["/"], +}; diff --git a/examples/e2e/pages-router/src/pages/_app.tsx b/examples/e2e/pages-router/src/pages/_app.tsx new file mode 100644 index 00000000..a9d6fd8d --- /dev/null +++ b/examples/e2e/pages-router/src/pages/_app.tsx @@ -0,0 +1,7 @@ +import "@/styles/globals.css"; + +import type { AppProps } from "next/app"; + +export default function App({ Component, pageProps }: AppProps) { + return ; +} diff --git a/examples/e2e/pages-router/src/pages/_document.tsx b/examples/e2e/pages-router/src/pages/_document.tsx new file mode 100644 index 00000000..ffc3f3cc --- /dev/null +++ b/examples/e2e/pages-router/src/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Head, Html, Main, NextScript } from "next/document"; + +export default function Document() { + return ( + + + +
+ + + + ); +} diff --git a/examples/e2e/pages-router/src/pages/api/hello.ts b/examples/e2e/pages-router/src/pages/api/hello.ts new file mode 100644 index 00000000..41b59cbc --- /dev/null +++ b/examples/e2e/pages-router/src/pages/api/hello.ts @@ -0,0 +1,10 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import type { NextApiRequest, NextApiResponse } from "next"; + +type Data = { + hello: string; +}; + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + res.status(200).json({ hello: "world" }); +} diff --git a/examples/e2e/pages-router/src/pages/index.tsx b/examples/e2e/pages-router/src/pages/index.tsx new file mode 100644 index 00000000..d72ee99e --- /dev/null +++ b/examples/e2e/pages-router/src/pages/index.tsx @@ -0,0 +1,34 @@ +import Nav from "@example/shared/components/Nav"; +import Head from "next/head"; + +// Not used, but necessary to get prefetching to work +export function getStaticProps() { + return { + props: { + hello: "world", + }, + }; +} + +export default function Home() { + return ( + <> + + Nextjs Pages Router + + + +
+

Nextjs Pages Router

+
+ + +
+
+ + ); +} diff --git a/examples/e2e/pages-router/src/pages/isr/index.tsx b/examples/e2e/pages-router/src/pages/isr/index.tsx new file mode 100644 index 00000000..5980b914 --- /dev/null +++ b/examples/e2e/pages-router/src/pages/isr/index.tsx @@ -0,0 +1,20 @@ +import type { InferGetStaticPropsType } from "next"; +import Link from "next/link"; + +export async function getStaticProps() { + return { + props: { + time: new Date().toISOString(), + }, + revalidate: 10, + }; +} + +export default function Page({ time }: InferGetStaticPropsType) { + return ( +
+
Time: {time}
+ Home +
+ ); +} diff --git a/examples/e2e/pages-router/src/pages/ssr/index.tsx b/examples/e2e/pages-router/src/pages/ssr/index.tsx new file mode 100644 index 00000000..86eb0e42 --- /dev/null +++ b/examples/e2e/pages-router/src/pages/ssr/index.tsx @@ -0,0 +1,20 @@ +import type { InferGetServerSidePropsType } from "next"; + +export async function getServerSideProps() { + return { + props: { + time: new Date().toISOString(), + envVar: process.env.SOME_PROD_VAR, + }, + }; +} + +export default function Page({ time, envVar }: InferGetServerSidePropsType) { + return ( + <> +

SSR

+
Time: {time}
+
Env: {envVar}
+ + ); +} diff --git a/examples/e2e/pages-router/src/styles/globals.css b/examples/e2e/pages-router/src/styles/globals.css new file mode 100644 index 00000000..cb7c88f8 --- /dev/null +++ b/examples/e2e/pages-router/src/styles/globals.css @@ -0,0 +1,95 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", + "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace; + + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; + + --primary-glow: conic-gradient( + from 180deg at 50% 50%, + #16abff33 0deg, + #0885ff33 55deg, + #54d6ff33 120deg, + #0071ff33 160deg, + transparent 360deg + ); + --secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); + + --tile-start-rgb: 239, 245, 249; + --tile-end-rgb: 228, 232, 233; + --tile-border: conic-gradient(#00000080, #00000040, #00000030, #00000020, #00000010, #00000010, #00000080); + + --callout-rgb: 238, 240, 241; + --callout-border-rgb: 172, 175, 176; + --card-rgb: 180, 185, 188; + --card-border-rgb: 131, 134, 135; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + + --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); + --secondary-glow: linear-gradient( + to bottom right, + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0.3) + ); + + --tile-start-rgb: 2, 13, 46; + --tile-end-rgb: 2, 5, 19; + --tile-border: conic-gradient( + #ffffff80, + #ffffff40, + #ffffff30, + #ffffff20, + #ffffff10, + #ffffff10, + #ffffff80 + ); + + --callout-rgb: 20, 20, 20; + --callout-border-rgb: 108, 108, 108; + --card-rgb: 100, 100, 100; + --card-border-rgb: 200, 200, 200; + } +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) + rgb(var(--background-start-rgb)); +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} diff --git a/examples/e2e/pages-router/tsconfig.json b/examples/e2e/pages-router/tsconfig.json new file mode 100644 index 00000000..7c3c0ed0 --- /dev/null +++ b/examples/e2e/pages-router/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + "@example/shared": ["../shared"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "../utils.ts"], + "exclude": ["node_modules", "open-next.config.ts"] +} diff --git a/examples/e2e/pages-router/wrangler.json b/examples/e2e/pages-router/wrangler.json new file mode 100644 index 00000000..57ad53ee --- /dev/null +++ b/examples/e2e/pages-router/wrangler.json @@ -0,0 +1,11 @@ +{ + "$schema": "node_modules/wrangler/config-schema.json", + "main": ".open-next/worker.js", + "name": "pages-router", + "compatibility_date": "2024-12-30", + "compatibility_flags": ["nodejs_compat"], + "assets": { + "directory": ".open-next/assets", + "binding": "ASSETS" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 556549f1..1a712c40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,6 +219,49 @@ importers: specifier: 'catalog:' version: 3.105.0(@cloudflare/workers-types@4.20250109.0) + examples/e2e/app-pages-router: + dependencies: + '@example/shared': + specifier: workspace:* + version: link:../shared + '@opennextjs/cloudflare': + specifier: workspace:* + version: link:../../../packages/cloudflare + next: + specifier: catalog:e2e + version: 15.1.0(@playwright/test@1.47.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: + specifier: catalog:e2e + version: 19.0.0 + react-dom: + specifier: catalog:e2e + version: 19.0.0(react@19.0.0) + devDependencies: + '@playwright/test': + specifier: 'catalog:' + version: 1.47.0 + '@types/node': + specifier: catalog:e2e + version: 20.17.6 + '@types/react': + specifier: catalog:e2e + version: 19.0.0 + '@types/react-dom': + specifier: catalog:e2e + version: 19.0.0 + autoprefixer: + specifier: catalog:e2e + version: 10.4.15(postcss@8.4.27) + postcss: + specifier: catalog:e2e + version: 8.4.27 + tailwindcss: + specifier: catalog:e2e + version: 3.3.3 + typescript: + specifier: catalog:default + version: 5.7.3 + examples/e2e/app-router: dependencies: '@example/shared': @@ -259,6 +302,49 @@ importers: specifier: catalog:default version: 5.7.3 + examples/e2e/pages-router: + dependencies: + '@example/shared': + specifier: workspace:* + version: link:../shared + '@opennextjs/cloudflare': + specifier: workspace:* + version: link:../../../packages/cloudflare + next: + specifier: catalog:e2e + version: 15.1.0(@playwright/test@1.47.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: + specifier: catalog:e2e + version: 19.0.0 + react-dom: + specifier: catalog:e2e + version: 19.0.0(react@19.0.0) + devDependencies: + '@playwright/test': + specifier: 'catalog:' + version: 1.47.0 + '@types/node': + specifier: catalog:e2e + version: 20.17.6 + '@types/react': + specifier: catalog:e2e + version: 19.0.0 + '@types/react-dom': + specifier: catalog:e2e + version: 19.0.0 + autoprefixer: + specifier: catalog:e2e + version: 10.4.15(postcss@8.4.27) + postcss: + specifier: catalog:e2e + version: 8.4.27 + tailwindcss: + specifier: catalog:e2e + version: 3.3.3 + typescript: + specifier: catalog:default + version: 5.7.3 + examples/e2e/shared: dependencies: next: