Skip to content

Commit e4285a7

Browse files
authored
test: import app-router e2e tests from aws (#289)
1 parent 3b20bc6 commit e4285a7

26 files changed

+734
-14
lines changed

examples/e2e/app-router/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,10 @@ yarn-error.log*
3434
# typescript
3535
*.tsbuildinfo
3636
next-env.d.ts
37+
38+
# playwright
39+
/test-results/
40+
/playwright-report/
41+
/blob-report/
42+
/playwright/.cache/
43+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("Next after", async ({ request }) => {
4+
const initialSSG = await request.get("/api/after/ssg");
5+
expect(initialSSG.status()).toEqual(200);
6+
const initialSSGJson = await initialSSG.json();
7+
8+
// We then fire a post request that will revalidate the SSG page 5 seconds after, but should respond immediately
9+
const dateNow = Date.now();
10+
const revalidateSSG = await request.post("/api/after/revalidate");
11+
expect(revalidateSSG.status()).toEqual(200);
12+
const revalidateSSGJson = await revalidateSSG.json();
13+
expect(revalidateSSGJson.success).toEqual(true);
14+
// This request should take less than 5 seconds to respond
15+
expect(Date.now() - dateNow).toBeLessThan(5000);
16+
17+
// We want to immediately check if the SSG page has been revalidated, it should not have been
18+
const notRevalidatedSSG = await request.get("/api/after/ssg");
19+
expect(notRevalidatedSSG.status()).toEqual(200);
20+
const notRevalidatedSSGJson = await notRevalidatedSSG.json();
21+
expect(notRevalidatedSSGJson.date).toEqual(initialSSGJson.date);
22+
23+
// We then wait for 5 seconds to ensure the SSG page has been revalidated
24+
await new Promise((resolve) => setTimeout(resolve, 5000));
25+
const revalidatedSSG = await request.get("/api/after/ssg");
26+
expect(revalidatedSSG.status()).toEqual(200);
27+
const revalidatedSSGJson = await revalidatedSSG.json();
28+
expect(revalidatedSSGJson.date).not.toEqual(initialSSGJson.date);
29+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("API call from client", async ({ page }) => {
4+
await page.goto("/");
5+
await page.getByRole("link", { name: "/API" }).click();
6+
7+
await page.waitForURL("/api");
8+
9+
let el = page.getByText("API: N/A");
10+
await expect(el).toBeVisible();
11+
12+
await page.getByRole("button", { name: "Call /api/client" }).click();
13+
el = page.getByText('API: { "hello": "client" }');
14+
await expect(el).toBeVisible();
15+
});
16+
17+
test("API call from middleware", async ({ page }) => {
18+
await page.goto("/");
19+
await page.getByRole("link", { name: "/API" }).click();
20+
21+
await page.waitForURL("/api");
22+
23+
let el = page.getByText("API: N/A");
24+
await expect(el).toBeVisible();
25+
26+
await page.getByRole("button", { name: "Call /api/middleware" }).click();
27+
el = page.getByText('API: { "hello": "middleware" }');
28+
await expect(el).toBeVisible();
29+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { expect, test } from "@playwright/test";
2+
/**
3+
* This tests that the "redirect" config in next.config.js works
4+
*
5+
* redirects: () => {
6+
return [
7+
{
8+
source: "/next-config-redirect",
9+
destination: "/config-redirect",
10+
permanent: true,
11+
missing: [{ type: "cookie", key: "missing-cookie" }],
12+
},
13+
];
14+
},
15+
*/
16+
test.describe("Next Config Redirect", () => {
17+
test("Missing cookies", async ({ page }) => {
18+
await page.goto("/");
19+
await page.goto("/next-config-redirect-missing");
20+
21+
await page.waitForURL("/config-redirect?missing=true");
22+
23+
const el = page.getByText("I was redirected from next.config.js", {
24+
exact: true,
25+
});
26+
await expect(el).toBeVisible();
27+
});
28+
test("Not missing cookies", async ({ page }) => {
29+
await page.goto("/");
30+
await page.goto("/next-config-redirect-not-missing");
31+
32+
// the cookie was not missing, so no redirects
33+
await page.waitForURL("/next-config-redirect-not-missing");
34+
35+
const el = page.getByText("This page could not be found.", {
36+
exact: true,
37+
});
38+
await expect(el).toBeVisible();
39+
});
40+
test("Has cookies", async ({ page }) => {
41+
await page.goto("/");
42+
await page.goto("/next-config-redirect-has");
43+
44+
await page.waitForURL("/config-redirect?has=true");
45+
46+
const el = page.getByText("I was redirected from next.config.js", {
47+
exact: true,
48+
});
49+
await expect(el).toBeVisible();
50+
});
51+
test("Has cookies with value", async ({ page }) => {
52+
await page.goto("/");
53+
await page.goto("/next-config-redirect-has-with-value");
54+
55+
await page.waitForURL("/config-redirect?hasWithValue=true");
56+
57+
const el = page.getByText("I was redirected from next.config.js", {
58+
exact: true,
59+
});
60+
await expect(el).toBeVisible();
61+
});
62+
test("Has cookies with bad value", async ({ page }) => {
63+
await page.goto("/");
64+
await page.goto("/next-config-redirect-has-with-bad-value");
65+
66+
// did not redirect
67+
await page.waitForURL("/next-config-redirect-has-with-bad-value");
68+
69+
// 404 not found
70+
const el = page.getByText("This page could not be found.", {
71+
exact: true,
72+
});
73+
await expect(el).toBeVisible();
74+
});
75+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
/**
4+
* Tests that the headers are available in RSC and response headers
5+
*/
6+
test("Headers", async ({ page }) => {
7+
const responsePromise = page.waitForResponse((response) => {
8+
return response.status() === 200;
9+
});
10+
await page.goto("/headers");
11+
12+
const response = await responsePromise;
13+
// Response header should be set
14+
const headers = response.headers();
15+
expect(headers["response-header"]).toEqual("response-header");
16+
17+
// The next.config.js headers should be also set in response
18+
expect(headers["e2e-headers"]).toEqual("next.config.js");
19+
20+
// Request header should be available in RSC
21+
const el = page.getByText("request-header");
22+
await expect(el).toBeVisible();
23+
24+
// Both these headers should not be present cause poweredByHeader is false in appRouter
25+
expect(headers["x-powered-by"]).toBeFalsy();
26+
expect(headers["x-opennext"]).toBeFalsy();
27+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
/**
4+
* Tests that the request.url is the deployed host and not localhost
5+
*/
6+
test("Request.url is host", async ({ baseURL, page }) => {
7+
await page.goto("/api/host");
8+
9+
const el = page.getByText(`{"url":"${baseURL}/api/host"}`);
10+
await expect(el).toBeVisible();
11+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("Image Optimization", async ({ page }) => {
4+
await page.goto("/");
5+
6+
const imageResponsePromise = page.waitForResponse(/https%3A%2F%2Fopennext.js.org%2Farchitecture.png/);
7+
await page.locator('[href="/image-optimization"]').click();
8+
const imageResponse = await imageResponsePromise;
9+
10+
await page.waitForURL("/image-optimization");
11+
12+
const imageContentType = imageResponse.headers()["content-type"];
13+
expect(imageContentType).toBe("image/webp");
14+
15+
const el = page.locator("img");
16+
await expect(el).toHaveJSProperty("complete", true);
17+
await expect(el).not.toHaveJSProperty("naturalWidth", 0);
18+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("Test revalidate", async ({ request }) => {
4+
const result = await request.get("/api/isr");
5+
6+
expect(result.status()).toEqual(200);
7+
const json = await result.json();
8+
const body = json.body;
9+
10+
expect(json.status).toEqual(200);
11+
expect(body.result).toEqual(true);
12+
expect(body.cacheControl).toEqual("private, no-cache, no-store, max-age=0, must-revalidate");
13+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("Incremental Static Regeneration", async ({ page }) => {
4+
test.setTimeout(45000);
5+
await page.goto("/");
6+
await page.locator("[href='/isr']").click();
7+
// Load the page a couple times to regenerate ISR
8+
9+
let el = page.getByText("Time:");
10+
// Track the static time
11+
let time = await el.textContent();
12+
let newTime: typeof time;
13+
let tempTime = time;
14+
do {
15+
await page.waitForTimeout(1000);
16+
await page.reload();
17+
time = tempTime;
18+
el = page.getByText("Time:");
19+
newTime = await el.textContent();
20+
tempTime = newTime;
21+
} while (time !== newTime);
22+
await page.reload();
23+
24+
await page.waitForTimeout(1000);
25+
el = page.getByText("Time:");
26+
const midTime = await el.textContent();
27+
// Expect that the time is still stale
28+
expect(midTime).toEqual(newTime);
29+
30+
// Wait 10 + 1 seconds for ISR to regenerate time
31+
await page.waitForTimeout(11000);
32+
let finalTime = newTime;
33+
do {
34+
await page.waitForTimeout(2000);
35+
el = page.getByText("Time:");
36+
finalTime = await el.textContent();
37+
await page.reload();
38+
} while (newTime === finalTime);
39+
40+
expect(newTime).not.toEqual(finalTime);
41+
});
42+
43+
test("headers", async ({ page }) => {
44+
let responsePromise = page.waitForResponse((response) => {
45+
return response.status() === 200;
46+
});
47+
await page.goto("/isr");
48+
49+
while (true) {
50+
const response = await responsePromise;
51+
const headers = response.headers();
52+
53+
// this was set in middleware
54+
if (headers["cache-control"] === "max-age=10, stale-while-revalidate=999") {
55+
break;
56+
}
57+
await page.waitForTimeout(1000);
58+
responsePromise = page.waitForResponse((response) => {
59+
return response.status() === 200;
60+
});
61+
await page.reload();
62+
}
63+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test("Cookies", async ({ page, context }) => {
4+
await page.goto("/");
5+
6+
const cookies = await context.cookies();
7+
const from = cookies.find(({ name }) => name === "from");
8+
expect(from?.value).toEqual("middleware");
9+
10+
const love = cookies.find(({ name }) => name === "with");
11+
expect(love?.value).toEqual("love");
12+
});

0 commit comments

Comments
 (0)