Skip to content

Commit

Permalink
fix: wait for hydration via react effect
Browse files Browse the repository at this point in the history
  • Loading branch information
katywings committed Jun 30, 2024
1 parent 8600f15 commit edac055
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
24 changes: 18 additions & 6 deletions test/fs-router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ testDevAndProd("fs-router", ({ createFixture }) => {
});

test("ssr", async ({ page }) => {
let res = await fixture.requestDocument("/");
expect(res.status).toBe(200);
expect(res.headers.get("Content-Type")).toBe("text/html");
let app = new PlaywrightFixture(appFixture, page);
let res = await app.goto("/", true);

expect(res.status()).toBe(200);
let headers = await res.allHeaders();
console.log('headers', headers);
expect(headers["Content-Type"]).toBe("text/html");

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr

2) [chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr ──────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr

2) [chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr ──────────────────────────────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: ubuntu-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr

2) [chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr ──────────────────────────────────── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /home/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr

1) [chromium] › fs-router.test.ts:36:2 › fs-router-dev › ssr ───────────────────────────────────── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35

Check failure on line 43 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr

3) [chromium] › fs-router.test.ts:36:2 › fs-router-prod › ssr ──────────────────────────────────── Error: expect(received).toBe(expected) // Object.is equality Expected: "text/html" Received: undefined 41 | let headers = await res.allHeaders(); 42 | console.log('headers', headers); > 43 | expect(headers["Content-Type"]).toBe("text/html"); | ^ 44 | let html = await res.text(); 45 | expect(selectHtml(html, "[data-test-id=title]")).toBe( 46 | prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`), at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:43:35
let html = await res.text();
expect(selectHtml(html, "[data-test-id=title]")).toBe(
prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`),
Expand All @@ -45,9 +49,12 @@ testDevAndProd("fs-router", ({ createFixture }) => {
prettyHtml(`<button data-test-id="counter">0</button>`),
);

res = await fixture.requestDocument("/hello");
expect(res.status).toBe(200);
expect(res.headers.get("Content-Type")).toBe("text/html");
res = await app.goto("/hello", true);

expect(res.status()).toBe(200);
headers = await res.allHeaders();
console.log('headers', headers);
expect(headers["Content-Type"]).toBe("text/html");
html = await res.text();
expect(selectHtml(html, "[data-test-id=title]")).toBe(
prettyHtml(`<h1 data-test-id="title">Hello from Vinxi</h1>`),
Expand All @@ -57,9 +64,12 @@ testDevAndProd("fs-router", ({ createFixture }) => {
);
});

const ready = (app: PlaywrightFixture) => app.page.locator('[data-ready]').waitFor({ state: "attached" });;

Check failure on line 67 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates

2) [chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates ──────────────────────────────── Error: locator.waitFor: Page closed =========================== logs =========================== waiting for locator('[data-ready]') ============================================================ 65 | }); 66 | > 67 | const ready = (app: PlaywrightFixture) => app.page.locator('[data-ready]').waitFor({ state: "attached" });; | ^ 68 | 69 | test("hydrates", async ({ page }) => { 70 | let app = new PlaywrightFixture(appFixture, page); at ready (/Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:67:77) at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:72:9

Check failure on line 67 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates

2) [chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates ──────────────────────────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.waitFor: Page closed =========================== logs =========================== waiting for locator('[data-ready]') ============================================================ 65 | }); 66 | > 67 | const ready = (app: PlaywrightFixture) => app.page.locator('[data-ready]').waitFor({ state: "attached" });; | ^ 68 | 69 | test("hydrates", async ({ page }) => { 70 | let app = new PlaywrightFixture(appFixture, page); at ready (/Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:67:77) at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:72:9

Check failure on line 67 in test/fs-router.test.ts

View workflow job for this annotation

GitHub Actions / 👀 (os: macos-latest, node: 18)

[chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates

2) [chromium] › fs-router.test.ts:69:2 › fs-router-dev › hydrates ──────────────────────────────── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.waitFor: Page closed =========================== logs =========================== waiting for locator('[data-ready]') ============================================================ 65 | }); 66 | > 67 | const ready = (app: PlaywrightFixture) => app.page.locator('[data-ready]').waitFor({ state: "attached" });; | ^ 68 | 69 | test("hydrates", async ({ page }) => { 70 | let app = new PlaywrightFixture(appFixture, page); at ready (/Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:67:77) at /Users/runner/work/vinxi/vinxi/test/fs-router.test.ts:72:9

test("hydrates", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/", true);
await ready(app);

expect(await app.getHtml("[data-test-id=title]")).toBe(
prettyHtml(`<h1 data-test-id="title">Vinxi Home</h1>`),
Expand All @@ -76,6 +86,7 @@ testDevAndProd("fs-router", ({ createFixture }) => {

await app.clickElement("a[href='/hello']");
await app.waitForURL("/hello");
await ready(app);
await new Promise((r) => setTimeout(r, 1000));

expect(await app.getHtml("[data-test-id=title]")).toBe(
Expand All @@ -87,6 +98,7 @@ testDevAndProd("fs-router", ({ createFixture }) => {

await app.clickElement("a[href='/']");
await app.waitForURL("/");
await ready(app);
await new Promise((r) => setTimeout(r, 2000));

expect(await app.getHtml("[data-test-id=title]")).toBe(
Expand Down
2 changes: 1 addition & 1 deletion test/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const config: PlaywrightTestConfig = {
testDir: ".",
testMatch: ["**/*.test.ts"],
fullyParallel: false,
timeout: process.env.CI ? 120_000 : 30_000, // 2 minutes in CI, 30 seconds locally
timeout: process.env.CI ? 360_000 : 30_000, // 5 minutes in CI, 30 seconds locally
expect: {
timeout: 5_000, // 5 second retries for assertions
},
Expand Down
16 changes: 14 additions & 2 deletions test/templates/react-ssr-fs/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import React from "react";
import React, { useEffect, useRef } from "react";

import { Counter } from "./Counter";
import "./style.css";

const useReadyRef = <T extends HTMLElement,>() => {
const ref = useRef<T>();
useEffect(() => {
ref.current.dataset.ready = "";
return () => {
ref.current.dataset.ready = null;
}
}, []);
return ref;
}

export default function App({ assets, children }) {
const [count, setCount] = React.useState(0);
const ref = useReadyRef<HTMLHtmlElement>();
return (
<html lang="en">
<html lang="en" ref={ref}>
<head>
<link rel="icon" href="/favicon.ico" />
{assets}
Expand Down

0 comments on commit edac055

Please sign in to comment.