Skip to content

Commit 2d287ee

Browse files
authored
Add the experimental e2e app (#614)
* add experimental e2e app * ignore typescript errors for now * lint fix * review fix
1 parent 2d82fad commit 2d287ee

28 files changed

+922
-29
lines changed

examples/common/apps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const apps = [
1111
"app-pages-router",
1212
"app-router",
1313
"pages-router",
14+
"experimental",
1415
// overrides
1516
"d1-tag-next",
1617
"memory-queue",

examples/e2e/experimental/.gitignore

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files (can opt-in for committing if needed)
34+
.env*
35+
36+
# vercel
37+
.vercel
38+
39+
# typescript
40+
*.tsbuildinfo
41+
next-env.d.ts

examples/e2e/experimental/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Experimental
2+
3+
This project is meant to test experimental features that are only available on canary builds of Next.js.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
// See https://github.com/opennextjs/opennextjs-cloudflare/issues/617
4+
test.describe("Node Middleware", () => {
5+
test.skip("Node middleware should add headers", async ({ request }) => {
6+
const resp = await request.get("/");
7+
expect(resp.status()).toEqual(200);
8+
const headers = resp.headers();
9+
expect(headers["x-middleware-test"]).toEqual("1");
10+
expect(headers["x-random-node"]).toBeDefined();
11+
});
12+
13+
test.skip("Node middleware should return json", async ({ request }) => {
14+
const resp = await request.get("/api/hello");
15+
expect(resp.status()).toEqual(200);
16+
const json = await resp.json();
17+
expect(json).toEqual({ name: "World" });
18+
});
19+
20+
test.skip("Node middleware should redirect", async ({ page }) => {
21+
await page.goto("/redirect");
22+
await page.waitForURL("/");
23+
const el = page.getByText("Incremental PPR");
24+
await expect(el).toBeVisible();
25+
});
26+
27+
test.skip("Node middleware should rewrite", async ({ page }) => {
28+
await page.goto("/rewrite");
29+
const el = page.getByText("Incremental PPR");
30+
await expect(el).toBeVisible();
31+
});
32+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { configurePlaywright } from "../../../common/config-e2e";
2+
3+
// We need to disable parallel execution for the experimental app, otherwise it breaks the SSR test
4+
export default configurePlaywright("experimental", { parallel: false });
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test.describe("PPR", () => {
4+
test("PPR should show loading first", async ({ page }) => {
5+
await page.goto("/");
6+
await page.getByRole("link", { name: "Incremental PPR" }).click();
7+
await page.waitForURL("/ppr");
8+
const loading = page.getByText("Loading...");
9+
await expect(loading).toBeVisible();
10+
const el = page.getByText("Dynamic Component");
11+
await expect(el).toBeVisible();
12+
});
13+
14+
test("PPR rsc prefetch request should be cached", async ({ request }) => {
15+
const resp = await request.get("/ppr", {
16+
headers: { rsc: "1", "next-router-prefetch": "1" },
17+
});
18+
expect(resp.status()).toEqual(200);
19+
const headers = resp.headers();
20+
expect(headers["x-nextjs-postponed"]).toEqual("1");
21+
expect(headers["x-nextjs-cache"]).toEqual("HIT");
22+
expect(headers["cache-control"]).toEqual("s-maxage=31536000");
23+
});
24+
});
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test.describe("Composable Cache", () => {
4+
test("cached component should work in ssr", async ({ page }) => {
5+
await page.goto("/use-cache/ssr");
6+
let fullyCachedElt = page.getByTestId("fullyCached");
7+
let isrElt = page.getByTestId("isr");
8+
await expect(fullyCachedElt).toBeVisible();
9+
await expect(isrElt).toBeVisible();
10+
11+
const initialFullyCachedText = await fullyCachedElt.textContent();
12+
const initialIsrText = await isrElt.textContent();
13+
14+
let isrText = initialIsrText;
15+
do {
16+
await page.reload();
17+
fullyCachedElt = page.getByTestId("fullyCached");
18+
isrElt = page.getByTestId("isr");
19+
await expect(fullyCachedElt).toBeVisible();
20+
await expect(isrElt).toBeVisible();
21+
isrText = await isrElt.textContent();
22+
await page.waitForTimeout(1000);
23+
} while (isrText === initialIsrText);
24+
const fullyCachedText = await fullyCachedElt.textContent();
25+
expect(fullyCachedText).toEqual(initialFullyCachedText);
26+
});
27+
28+
test("revalidateTag should work for fullyCached component", async ({ page, request }) => {
29+
await page.goto("/use-cache/ssr");
30+
const fullyCachedElt = page.getByTestId("fullyCached");
31+
await expect(fullyCachedElt).toBeVisible();
32+
33+
const initialFullyCachedText = await fullyCachedElt.textContent();
34+
35+
const resp = await request.get("/api/revalidate");
36+
expect(resp.status()).toEqual(200);
37+
expect(await resp.text()).toEqual("DONE");
38+
39+
await page.reload();
40+
await expect(fullyCachedElt).toBeVisible();
41+
const newFullyCachedText = await fullyCachedElt.textContent();
42+
expect(newFullyCachedText).not.toEqual(initialFullyCachedText);
43+
});
44+
45+
test("cached component should work in isr", async ({ page }) => {
46+
await page.goto("/use-cache/isr");
47+
48+
let fullyCachedElt = page.getByTestId("fullyCached");
49+
let isrElt = page.getByTestId("isr");
50+
51+
await expect(fullyCachedElt).toBeVisible();
52+
await expect(isrElt).toBeVisible();
53+
54+
let initialFullyCachedText = await fullyCachedElt.textContent();
55+
let initialIsrText = await isrElt.textContent();
56+
57+
// We have to force reload until ISR has triggered at least once, otherwise the test will be flakey
58+
59+
let isrText = initialIsrText;
60+
61+
while (isrText === initialIsrText) {
62+
await page.reload();
63+
isrElt = page.getByTestId("isr");
64+
fullyCachedElt = page.getByTestId("fullyCached");
65+
await expect(isrElt).toBeVisible();
66+
isrText = await isrElt.textContent();
67+
await expect(fullyCachedElt).toBeVisible();
68+
initialFullyCachedText = await fullyCachedElt.textContent();
69+
await page.waitForTimeout(1000);
70+
}
71+
initialIsrText = isrText;
72+
73+
do {
74+
await page.reload();
75+
fullyCachedElt = page.getByTestId("fullyCached");
76+
isrElt = page.getByTestId("isr");
77+
await expect(fullyCachedElt).toBeVisible();
78+
await expect(isrElt).toBeVisible();
79+
isrText = await isrElt.textContent();
80+
await page.waitForTimeout(1000);
81+
} while (isrText === initialIsrText);
82+
const fullyCachedText = await fullyCachedElt.textContent();
83+
expect(fullyCachedText).toEqual(initialFullyCachedText);
84+
});
85+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { NextConfig } from "next";
2+
3+
const nextConfig: NextConfig = {
4+
/* config options here */
5+
cleanDistDir: true,
6+
output: "standalone",
7+
eslint: {
8+
ignoreDuringBuilds: true,
9+
},
10+
typescript: {
11+
// Ignore type errors during build for now, we'll need to figure this out later
12+
ignoreBuildErrors: true,
13+
},
14+
experimental: {
15+
ppr: "incremental",
16+
// Node middleware is not supported yet in cloudflare
17+
// See https://github.com/opennextjs/opennextjs-cloudflare/issues/617
18+
// nodeMiddleware: true,
19+
dynamicIO: true,
20+
},
21+
};
22+
23+
export default nextConfig;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
2+
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";
3+
import shardedTagCache from "@opennextjs/cloudflare/overrides/tag-cache/do-sharded-tag-cache";
4+
import doQueue from "@opennextjs/cloudflare/overrides/queue/do-queue";
5+
6+
export default defineCloudflareConfig({
7+
incrementalCache: r2IncrementalCache,
8+
// With such a configuration, we could have up to 12 * (8 + 2) = 120 Durable Objects instances
9+
tagCache: shardedTagCache({
10+
baseShardSize: 12,
11+
shardReplication: {
12+
numberOfSoftReplicas: 8,
13+
numberOfHardReplicas: 2,
14+
},
15+
}),
16+
queue: doQueue,
17+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "experimental",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "next dev --turbopack --port 3004",
7+
"build": "next build",
8+
"start": "next start --port 3004",
9+
"lint": "next lint",
10+
"clean": "rm -rf .turbo node_modules .next .open-next",
11+
"build:worker": "pnpm opennextjs-cloudflare build",
12+
"preview:worker": "pnpm opennextjs-cloudflare preview",
13+
"preview": "pnpm build:worker && pnpm preview:worker",
14+
"e2e": "playwright test -c e2e/playwright.config.ts"
15+
},
16+
"dependencies": {
17+
"@opennextjs/cloudflare": "workspace:*",
18+
"next": "15.4.0-canary.14",
19+
"react": "catalog:e2e",
20+
"react-dom": "catalog:e2e"
21+
},
22+
"devDependencies": {
23+
"@playwright/test": "catalog:",
24+
"@types/node": "catalog:e2e",
25+
"@types/react": "catalog:e2e",
26+
"@types/react-dom": "catalog:e2e",
27+
"typescript": "catalog:default",
28+
"wrangler": "catalog:"
29+
}
30+
}

0 commit comments

Comments
 (0)