Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: App crash on fast browser navigation or shows wrong url #5166

Closed
wants to merge 7 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 93 additions & 20 deletions integration/bug-report-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,24 @@ test.beforeAll(async () => {
////////////////////////////////////////////////////////////////////////////
files: {
"app/routes/index.jsx": js`
import { json } from "@remix-run/node";
import { useLoaderData, Link } from "@remix-run/react";

export function loader() {
return json("pizza");
}
import { Link } from "@remix-run/react";

export default function Index() {
let data = useLoaderData();
return (
<div>
{data}
<Link to="/burgers">Other Route</Link>
<div>pizza</div>
<Link to="/burgers">burger link</Link>
</div>
)
}
`,

"app/routes/burgers.jsx": js`

export default function Index() {
return <div>cheeseburger</div>;
return (
<div>cheeseburger</div>
);
}
`,
},
Expand All @@ -85,22 +82,98 @@ test.afterAll(() => appFixture.close());
// add a good description for what you expect Remix to do 👇🏽
////////////////////////////////////////////////////////////////////////////////

test("[description of what you expect it to do]", async ({ page }) => {
test(`expect to be able to browse backward out of a remix app,
then forward in history and have pages render correctly`, async ({
page,
}) => {
let app = new PlaywrightFixture(appFixture, page);
// You can test any request your app might get using `fixture`.
let response = await fixture.requestDocument("/");
expect(await response.text()).toMatch("pizza");

// If you need to test interactivity use the `app`
// This sets up the Remix modules cache in memory, priming the error case.
await app.goto("/");
await app.clickLink("/burgers");
expect(await app.getHtml()).toMatch("cheeseburger");
expect(await page.content()).toMatch("cheeseburger");

let retry = 4;
for (let i = 0; i < retry; i++) {
// Back to /
await page.goBack();
expect(await app.getHtml()).toContain("pizza");
// Takes the browser to an empty state. This doesn't seem to work in headless Firefox
await page.goBack();

// Forward to /
await page.goForward();
// This passes
expect(await app.getHtml()).toContain("pizza");

// Forward to /burgers
await page.goForward();
// Here's an error: the path should be `/burgers`
// (this validates correctly and passes)
expect(page.url()).toContain("/burgers");
// but now the content won't contain the string "cheeseburger"
expect(await app.getHtml()).toMatch("cheeseburger");
expect(await app.getHtml()).not.toMatch("pizza");
}
});

test("expect to be able to go forward and backward in browser history without triggering a TypeError", async ({
page,
}) => {
let app = new PlaywrightFixture(appFixture, page);

// This fails locally in chromium, edge or Firefox but all intermittently on an M1 MacPro.
// Increasing the retries will ensure more of the browsers fail.
// Failure message look like:
//
// TypeError: Cannot destructure property 'default' of 'n[e]' as it is undefined.
// at hr (http://localhost:60918/build/_shared/chunk-2QBB563C.js:14:85)
// at mu (http://localhost:60918/build/entry.client-RIRIZEHM.js:6:19484)
// at Xa (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:44019)
// at $a (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:39724)
// at Zf (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:39655)
// at br (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:39515)
// at Ui (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:35905)
// at Ha (http://localhost:60918/build/entry.client-RIRIZEHM.js:8:34858)
// at Cl (http://localhost:60918/build/entry.client-RIRIZEHM.js:1:1741)
// at MessagePort.gl (http://localhost:60918/build/entry.client-RIRIZEHM.js:1:2131)</pre
// >

// First create some history in the browser and validate that Remix
// is rendering the content expected.
await app.goto("/");
await app.clickLink("/burgers");
expect(await page.content()).toMatch("cheeseburger");

// For chromium, this usually triggers the error.
// It requires fast navigation between a page that is not the remix app,
// for example Chromium's 'no url' page, or remix.run, and a page
// 2 deep in history that's part of a remix app (eg click forward twice).
let appErrorStr = "Application Error!";

// Increase `retry` to something large, like 40, to view the
// TyepError failures if you're not seeing them after a couple of tries.
let retry = 10;

for (let i = 0; i < retry; i++) {
// Back to /
await page.goBack();
expect(await app.getHtml()).toContain("pizza");
// Back to empty page
await page.goBack();

// If you're not sure what's going on, you can "poke" the app, it'll
// automatically open up in your browser for 20 seconds, so be quick!
// await app.poke(20);
// Forward to /
await page.goForward();
let appHtml1 = await app.getHtml();
expect(appHtml1).toContain("pizza");
expect(appHtml1).not.toContain(appErrorStr);

// Go check out the other tests to see what else you can do.
// Forward to /burgers
await page.goForward();
// But now the content won't contain the string "cheeseburger"
let appHtml2 = await app.getHtml();
expect(appHtml2).not.toContain(appErrorStr);
}
});

////////////////////////////////////////////////////////////////////////////////
Expand Down