From 474feb7793fa9f9e9c6f75d957dcafb22550b534 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 14 Mar 2023 09:18:40 -0400 Subject: [PATCH] Remove wrapper API from data browser router tests (#10196) --- .../__tests__/data-browser-router-test.tsx | 1479 +++++++++-------- 1 file changed, 821 insertions(+), 658 deletions(-) diff --git a/packages/react-router-dom/__tests__/data-browser-router-test.tsx b/packages/react-router-dom/__tests__/data-browser-router-test.tsx index 5ec90eaa6f..5c73c8f3e2 100644 --- a/packages/react-router-dom/__tests__/data-browser-router-test.tsx +++ b/packages/react-router-dom/__tests__/data-browser-router-test.tsx @@ -9,8 +9,8 @@ import { prettyDOM, } from "@testing-library/react"; import "@testing-library/jest-dom"; - -import type { Router, RouterInit } from "@remix-run/router"; +import type { ErrorResponse } from "@remix-run/router"; +import type { RouteObject } from "react-router-dom"; import { Form, Link, @@ -43,8 +43,6 @@ testDomRouter("", createHashRouter, (url) => getWindowImpl(url, true) ); -let router: Router | null = null; - function testDomRouter( name: string, createTestRouter: typeof createBrowserRouter | typeof createHashRouter, @@ -68,60 +66,26 @@ function testDomRouter( } } - // Abstraction to avoid re-writing all tests for the time being - function TestDataRouter({ - basename, - children, - fallbackElement, - hydrationData, - window, - }: { - basename?: RouterInit["basename"]; - children: React.ReactNode | React.ReactNode[]; - fallbackElement?: React.ReactNode; - hydrationData?: RouterInit["hydrationData"]; - window?: Window; - }) { - router = createTestRouter(createRoutesFromElements(children), { - basename, - hydrationData, - window, - }); - return ; - } - - async function waitForRouterInitialize(router) { - return await new Promise((resolve) => { - let unsubscribe = router.subscribe((updatedState) => { - if (updatedState.initialized) { - unsubscribe(); - resolve(router); - } - }); - }); - } - describe(`Router: ${name}`, () => { let consoleWarn: jest.SpyInstance; let consoleError: jest.SpyInstance; + beforeEach(() => { consoleWarn = jest.spyOn(console, "warn").mockImplementation(() => {}); consoleError = jest.spyOn(console, "error").mockImplementation(() => {}); }); afterEach(() => { - router = null; window.__staticRouterHydrationData = undefined; consoleWarn.mockRestore(); consoleError.mockRestore(); }); it("renders the first route that matches the URL", () => { - let { container } = render( - - Home} /> - + let router = createTestRouter( + createRoutesFromElements(Home} />) ); + let { container } = render(); expect(getHtml(container)).toMatchInlineSnapshot(` "
@@ -133,18 +97,19 @@ function testDomRouter( }); it("renders the first route that matches the URL when wrapped in a root Route", () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> Heyooo} /> - + ), + { + window: getWindow("/my/base/path/thing"), + } ); + let { container } = render(); expect(getHtml(container)).toMatchInlineSnapshot(` "
@@ -156,15 +121,16 @@ function testDomRouter( }); it("supports a basename prop", () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( Heyooo} /> - + ), + { + basename: "/my/base/path", + window: getWindow("/my/base/path/thing"), + } ); + let { container } = render(); expect(getHtml(container)).toMatchInlineSnapshot(` "
@@ -176,10 +142,15 @@ function testDomRouter( }); it("renders with hydration data", async () => { - let { container } = render( - }> + } /> + + ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": "parent data", "0-0": "child data", @@ -187,13 +158,10 @@ function testDomRouter( actionData: { "0-0": "child action", }, - }} - > - }> - } /> - - + }, + } ); + let { container } = render(); function Comp() { let data = useLoaderData(); @@ -201,9 +169,9 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); @@ -235,13 +203,17 @@ function testDomRouter( "0-0": "child action", }, }; - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/child"), + } ); + let { container } = render(); function Comp() { let data = useLoaderData(); @@ -249,9 +221,9 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); @@ -287,14 +259,15 @@ function testDomRouter( }, }, }; - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( Nope} errorElement={} /> - + ) ); + let { container } = render(); function Boundary() { - let error = useRouteError(); + let error = useRouteError() as unknown; return isRouteErrorResponse(error) ? (
{JSON.stringify(error)}
) : ( @@ -322,14 +295,15 @@ function testDomRouter( }, }, }; - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( Nope} errorElement={} /> - + ) ); + let { container } = render(); function Boundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return error instanceof Error ? ( <>
{error.toString()}
@@ -354,11 +328,8 @@ function testDomRouter( it("renders fallbackElement while first data fetch happens", async () => { let fooDefer = createDeferred(); - let { container } = render( - } - > + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/foo"), + } + ); + let { container } = render( + } /> ); function FallbackElement() { @@ -375,8 +352,8 @@ function testDomRouter( } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } function Bar() { @@ -405,11 +382,8 @@ function testDomRouter( it("renders fallbackElement while first data fetch and lazy route load happens", async () => { let fooDefer = createDeferred(); - let { container } = render( - } - > + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/foo"), + } + ); + let { container } = render( + } /> ); function FallbackElement() { @@ -430,8 +410,8 @@ function testDomRouter( } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } function Bar() { @@ -460,11 +440,8 @@ function testDomRouter( it("does not render fallbackElement if no data fetch or lazy loading is required", async () => { let fooDefer = createDeferred(); - let { container } = render( - } - > + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/bar"), + } + ); + let { container } = render( + } /> ); function FallbackElement() { @@ -481,8 +464,8 @@ function testDomRouter( } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } function Bar() { @@ -500,11 +483,8 @@ function testDomRouter( it("renders fallbackElement within router contexts", async () => { let fooDefer = createDeferred(); - let { container } = render( - } - > + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { window: getWindow("/foo") } + ); + let { container } = render( + } /> ); function FallbackElement() { @@ -521,8 +505,8 @@ function testDomRouter( } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } expect(getHtml(container)).toMatchInlineSnapshot(` @@ -547,14 +531,16 @@ function testDomRouter( }); it("handles link navigations", async () => { - render( - + let router = createTestRouter( + createRoutesFromElements( }> Foo Heading} /> Bar Heading} /> - + ), + { window: getWindow("/foo") } ); + render(); function Layout() { return ( @@ -576,18 +562,19 @@ function testDomRouter( it("handles link navigations when using a basename", async () => { let testWindow = getWindow("/base/name/foo"); - render( - + let router = createTestRouter( + createRoutesFromElements( }> Foo Heading} /> Bar Heading} /> - + ), + { + window: testWindow, + basename: "/base/name", + } ); + render(); function Layout() { return ( @@ -616,8 +603,8 @@ function testDomRouter( it("executes route loaders on navigation", async () => { let barDefer = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> } /> } /> - + ), + { window: getWindow("/foo") } ); + let { container } = render(); function Layout() { let navigation = useNavigation(); @@ -646,11 +635,11 @@ function testDomRouter( return

Foo

; } function Bar() { - let data = useLoaderData(); - return

{data?.message}

; + let data = useLoaderData() as { message: string }; + return

{data.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
{ let barDefer = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/foo"), + } ); + let { container } = render(); function Layout() { let navigation = useNavigation(); @@ -731,11 +724,11 @@ function testDomRouter( return

Foo

; } function Bar() { - let data = useLoaderData(); - return

{data?.message}

; + let data = useLoaderData() as { message: string }; + return

{data.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> Foo Heading} /> Bar Heading} /> - + ), + { window: getWindow("/foo") } ); + let { container } = render(); function Layout() { let state = React.useContext(DataRouterStateContext); @@ -807,7 +802,7 @@ function testDomRouter( fireEvent.click(screen.getByText("Link to Bar")); await waitFor(() => screen.getByText("Bar Heading")); - expect(getHtml(container.querySelector("#preventScrollReset"))) + expect(getHtml(container.querySelector("#preventScrollReset")!)) .toMatchInlineSnapshot(` "

screen.getByText("Foo Heading")); - expect(getHtml(container.querySelector("#preventScrollReset"))) + expect(getHtml(container.querySelector("#preventScrollReset")!)) .toMatchInlineSnapshot(` "

{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> Foo Heading} /> Bar Heading} /> - + ), + { window: getWindow("/foo") } ); + let { container } = render(); function Layout() { let state = React.useContext(DataRouterStateContext); @@ -854,7 +851,7 @@ function testDomRouter( fireEvent.click(screen.getByText("Link to Bar")); await waitFor(() => screen.getByText("Bar Heading")); - expect(getHtml(container.querySelector("#preventScrollReset"))) + expect(getHtml(container.querySelector("#preventScrollReset")!)) .toMatchInlineSnapshot(` "

screen.getByText("Foo Heading")); - expect(getHtml(container.querySelector("#preventScrollReset"))) + expect(getHtml(container.querySelector("#preventScrollReset")!)) .toMatchInlineSnapshot(` "

+ let router = createTestRouter( + createRoutesFromElements( actionDefer.promise} loader={() => loaderDefer.promise} element={} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); let submit = useSubmit(); - let formRef = React.useRef(); + let formRef = React.useRef(null); return (

- +

{navigation.state}

{data}

@@ -912,7 +916,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("submitting")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( ({ @@ -991,15 +995,20 @@ function testDomRouter( element: , })} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); let submit = useSubmit(); - let formRef = React.useRef(); + let formRef = React.useRef(null); return (
@@ -1017,7 +1026,7 @@ function testDomRouter( } await waitFor(() => screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("submitting")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( actionDefer.promise} @@ -1100,12 +1109,17 @@ function testDomRouter( }} element={} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1123,7 +1137,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( ({ @@ -1189,12 +1203,17 @@ function testDomRouter( element: , })} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1213,7 +1232,7 @@ function testDomRouter( } await waitFor(() => screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( { @@ -1275,12 +1294,17 @@ function testDomRouter( loader={() => loaderDefer.promise} element={} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1298,7 +1322,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("submitting")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( ({ @@ -1381,12 +1405,17 @@ function testDomRouter( element: , })} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
@@ -1405,7 +1434,7 @@ function testDomRouter( } await waitFor(() => screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("submitting")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ) ); + render(); let handlerCalled; let defaultPrevented; @@ -1504,15 +1534,19 @@ function testDomRouter( }); it('defaults to be a PUSH navigation', async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

index

} /> "1"} element={

Page 1

} /> "2"} element={

Page 2

} />
-
+ ), + { + hydrationData: {}, + } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); @@ -1530,7 +1564,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 1")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("index")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
to be a REPLACE navigation', async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

Index Page

} /> Result Page} /> -
+ ), + { + hydrationData: {}, + } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); @@ -1597,7 +1635,7 @@ function testDomRouter( } function FormPage() { - let data = useActionData(); + let data = useActionData() as string | undefined; return (

Form Page

@@ -1608,7 +1646,7 @@ function testDomRouter( ); } - let html = () => getHtml(container.querySelector(".output")); + let html = () => getHtml(container.querySelector(".output")!); // Start on index page expect(html()).toMatch("Index Page"); @@ -1630,8 +1668,8 @@ function testDomRouter( }); it('Uses a PUSH navigation on if it redirects', async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

Index Page

} /> Result Page} /> -
+ ), + { hydrationData: {} } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); @@ -1663,7 +1703,7 @@ function testDomRouter( } function FormPage() { - let data = useActionData(); + let data = useActionData() as string | undefined; return (

Form Page

@@ -1674,7 +1714,7 @@ function testDomRouter( ); } - let html = () => getHtml(container.querySelector(".output")); + let html = () => getHtml(container.querySelector(".output")!); // Start on index page expect(html()).toMatch("Index Page"); @@ -1693,15 +1733,20 @@ function testDomRouter( }); it('defaults useSubmit({ method: "get" }) to be a PUSH navigation', async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

index

} /> "1"} element={

Page 1

} /> "2"} element={

Page 2

} />
-
+ ), + { + hydrationData: {}, + window: getWindow("/"), + } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); @@ -1723,7 +1768,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 1")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("index")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

index

} /> "1"} element={

Page 1

} /> @@ -1774,8 +1819,13 @@ function testDomRouter( element={

Page 2

} />
-
+ ), + { + hydrationData: {}, + window: getWindow("/"), + } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); @@ -1800,7 +1850,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 1")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 2")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 1")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> "index"} element={

index

} /> Page 1} /> -
+ ), + { + hydrationData: {}, + window: getWindow("/"), + } ); + let { container } = render(); function Layout() { let navigate = useNavigate(); let submit = useSubmit(); - let actionData = useActionData(); + let actionData = useActionData() as string | undefined; let formData = new FormData(); formData.append("test", "value"); return ( @@ -1891,7 +1946,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("Page 1")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("action")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
screen.getByText("index")); - expect(getHtml(container.querySelector(".output"))) + expect(getHtml(container.querySelector(".output")!)) .toMatchInlineSnapshot(` "
', async () => { let testWindow = getWindow("/base/path"); - let { container } = render( - - } /> - + let router = createTestRouter( + createRoutesFromElements(} />), + { basename: "/base", hydrationData: {}, window: testWindow } ); + let { container } = render(); function Comp() { let location = useLocation(); @@ -2020,11 +2075,17 @@ function testDomRouter( it('supports a basename on ', async () => { let testWindow = getWindow("/base/path"); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( "action data"} element={} /> - + ), + { + basename: "/base", + hydrationData: {}, + window: testWindow, + } ); + let { container } = render(); function Comp() { let location = useLocation(); @@ -2100,8 +2161,8 @@ function testDomRouter( it("allows a button to override the ", async () => { let loaderDefer = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( { @@ -2110,11 +2171,16 @@ function testDomRouter( loader={() => loaderDefer.promise} element={} /> - + ), + { + hydrationData: {}, + window: getWindow("/"), + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); + let data = useLoaderData() as string; let navigation = useNavigation(); return (
@@ -2133,7 +2199,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("loading")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( { @@ -2192,16 +2258,21 @@ function testDomRouter( loader={() => loaderDefer.promise} element={} /> - + ), + { + hydrationData: {}, + window: getWindow("/"), + } ); + let { container } = render(); function Home() { - let data = useLoaderData(); - let actionData = useActionData(); + let data = useLoaderData() as string; + let actionData = useActionData() as string | undefined; let navigation = useNavigation(); return (
- + @@ -2221,7 +2292,7 @@ function testDomRouter( await waitFor(() => screen.getByText("loading")); loaderDefer.resolve("Loader Data"); await waitFor(() => screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
{ it("includes search params + hash when no action is specified", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?a=1#hash" @@ -2288,18 +2360,17 @@ function testDomRouter( }); it("does not include search params + hash when action='.'", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/foo/bar?a=1#hash") } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2307,18 +2378,17 @@ function testDomRouter( }); it("does not include search params + hash when action=''", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/foo/bar?a=1#hash") } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2328,11 +2398,8 @@ function testDomRouter( describe("layout routes", () => { it("includes search params + hash when no action is specified", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> @@ -2340,8 +2407,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?a=1#hash" @@ -2349,11 +2420,8 @@ function testDomRouter( }); it("does not include search params + hash when action='.'", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> @@ -2361,8 +2429,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2370,11 +2442,8 @@ function testDomRouter( }); it("does not include search params + hash when action=''", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> @@ -2382,8 +2451,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2393,11 +2466,8 @@ function testDomRouter( describe("index routes", () => { it("includes search params + hash when no action is specified", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( @@ -2405,8 +2475,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?index&a=1#hash" @@ -2414,11 +2488,8 @@ function testDomRouter( }); it("does not include search params + hash action='.'", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( @@ -2426,8 +2497,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?index" @@ -2435,11 +2510,8 @@ function testDomRouter( }); it("does not include search params + hash action=''", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( @@ -2447,8 +2519,12 @@ function testDomRouter( - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?index" @@ -2458,8 +2534,8 @@ function testDomRouter( // eslint-disable-next-line jest/expect-expect it("does not repeatedly add ?index params on submissions", async () => { let testWindow = getWindow("/form"); - render( - + let router = createTestRouter( + createRoutesFromElements( - + ), + { + window: testWindow, + } ); + render(); assertLocation(testWindow, "/form", ""); @@ -2490,11 +2570,8 @@ function testDomRouter( }); it("handles index routes with a path", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( - + ), + { window: getWindow("/foo/bar?a=1#hash") } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?index&a=1#hash" @@ -2515,18 +2594,19 @@ function testDomRouter( describe("dynamic routes", () => { it("includes search params + hash when no action is specified", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar?a=1#hash" @@ -2534,18 +2614,19 @@ function testDomRouter( }); it("does not include search params + hash action='.'", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2553,18 +2634,19 @@ function testDomRouter( }); it("does not include search params + hash when action=''", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo/bar" @@ -2574,18 +2656,19 @@ function testDomRouter( describe("splat routes", () => { it("includes search params + hash when no action is specified", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo?a=1#hash" @@ -2593,18 +2676,19 @@ function testDomRouter( }); it("does not include search params + hash when action='.'", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo" @@ -2612,18 +2696,19 @@ function testDomRouter( }); it("does not include search params + hash when action=''", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/foo/bar?a=1#hash"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/foo" @@ -2634,11 +2719,8 @@ function testDomRouter( describe('
', () => { it("navigates relative to the URL for static routes", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/inbox/messages/edit"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/inbox/messages" @@ -2655,11 +2741,8 @@ function testDomRouter( }); it("navigates relative to the URL for dynamic routes", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/inbox/messages/1"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/inbox/messages" @@ -2676,11 +2763,8 @@ function testDomRouter( }); it("navigates relative to the URL for layout routes", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( Form} /> - + ), + { + window: getWindow("/inbox/messages/1"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/inbox/messages" @@ -2704,19 +2792,20 @@ function testDomRouter( }); it("navigates relative to the URL for index routes", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/inbox/messages/1"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/inbox/messages" @@ -2724,11 +2813,8 @@ function testDomRouter( }); it("navigates relative to the URL for splat routes", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { + window: getWindow("/inbox/messages/1/2/3"), + } ); + let { container } = render(); expect(container.querySelector("form")?.getAttribute("action")).toBe( "/inbox/messages/1/2" @@ -2748,11 +2838,13 @@ function testDomRouter( describe("useSubmit/Form FormData", () => { it("gathers form data on submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { return ( @@ -2772,11 +2864,13 @@ function testDomRouter( it("gathers form data on submit(form) submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2800,11 +2894,13 @@ function testDomRouter( it("gathers form data on submit(button) submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2834,11 +2930,13 @@ function testDomRouter( it("gathers form data on submit(input[type=submit]) submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2868,11 +2966,13 @@ function testDomRouter( it("gathers form data on submit(FormData) submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2894,11 +2994,13 @@ function testDomRouter( it("gathers form data on submit(object) submissions", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2919,11 +3021,13 @@ function testDomRouter( it("includes submit button name/value on form submission", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { return ( @@ -2946,11 +3050,13 @@ function testDomRouter( it("includes submit button name/value on button submission", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -2981,11 +3087,13 @@ function testDomRouter( it("appends button name/value and doesn't overwrite inputs with same name (form)", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { return ( @@ -3007,11 +3115,13 @@ function testDomRouter( it("appends button name/value and doesn't overwrite inputs with same name (button)", async () => { let actionSpy = jest.fn(); - render( - + let router = createTestRouter( + createRoutesFromElements( } /> - + ), + { window: getWindow("/") } ); + render(); function FormPage() { let submit = useSubmit(); @@ -3043,11 +3153,8 @@ function testDomRouter( describe("useFetcher(s)", () => { it("handles fetcher.load and fetcher.submit", async () => { let count = 0; - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3068,8 +3175,13 @@ function testDomRouter( return { count }; }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3092,7 +3204,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3186,8 +3295,13 @@ function testDomRouter( loader={() => "INDEX LOADER"} /> - + ), + { + window: getWindow("/parent"), + hydrationData: { loaderData: { parent: null, index: null } }, + } ); + let { container } = render(); function Index() { let fetcher = useFetcher(); @@ -3240,7 +3354,7 @@ function testDomRouter( async function clickAndAssert(btnText: string, expectedOutput: string) { fireEvent.click(screen.getByText(btnText)); await waitFor(() => screen.getByText(new RegExp(expectedOutput))); - expect(getHtml(container.querySelector("#output"))).toContain( + expect(getHtml(container.querySelector("#output")!)).toContain( expectedOutput ); } @@ -3255,11 +3369,8 @@ function testDomRouter( }); it("handles fetcher.load errors", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3268,8 +3379,13 @@ function testDomRouter( throw new Error("Kaboom!"); }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3285,7 +3401,7 @@ function testDomRouter( } function ErrorElement() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -3324,19 +3440,21 @@ function testDomRouter( it("handles fetcher.load errors (defer)", async () => { let dfd = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } errorElement={} loader={() => defer({ value: dfd.promise })} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3352,7 +3470,7 @@ function testDomRouter( } function ErrorElement() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -3391,11 +3509,8 @@ function testDomRouter( }); it("handles fetcher.submit errors", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3404,8 +3519,13 @@ function testDomRouter( throw new Error("Kaboom!"); }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3427,7 +3547,7 @@ function testDomRouter( } function ErrorElement() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -3466,11 +3586,8 @@ function testDomRouter( it("handles fetcher.Form", async () => { let count = 0; - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3491,8 +3608,13 @@ function testDomRouter( return { count }; }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3514,7 +3636,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3581,8 +3700,13 @@ function testDomRouter( throw new Error("Kaboom!"); }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3600,11 +3724,11 @@ function testDomRouter( } function ErrorElement() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } @@ -3647,8 +3768,13 @@ function testDomRouter( throw new Error("Kaboom!"); }} /> - + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3666,11 +3792,11 @@ function testDomRouter( } function ErrorElement() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

{ let dfd1 = createDeferred(); let dfd2 = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/1"), + hydrationData: { loaderData: { "0": null, "0-0": null } }, + } ); + let { container } = render(); function Parent() { let fetchers = useFetchers(); @@ -3763,7 +3891,7 @@ function testDomRouter( } // Initial state - no useFetchers reflected yet - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/data 1/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText(/2.*idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText(/2.*idle/)); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
{ let count = 0; let fetchCount = 0; - let { container } = render( - - } - action={async ({ request }) => { - let formData = await request.formData(); - count = count + parseInt(String(formData.get("increment")), 10); - return { count }; - }} - loader={async () => ({ count: ++count })} - /> - ({ fetchCount: ++fetchCount })} - /> - + let router = createTestRouter( + createRoutesFromElements( + <> + } + action={async ({ request }) => { + let formData = await request.formData(); + count = + count + parseInt(String(formData.get("increment")), 10); + return { count }; + }} + loader={async () => ({ count: ++count })} + /> + ({ fetchCount: ++fetchCount })} + /> + + ), + { + window: getWindow("/"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -3959,7 +4092,7 @@ function testDomRouter( ); } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); }); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

screen.getByText(/idle/)); }); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "

{ - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } errorElement={

Not I!

}> } /> - + ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -4021,7 +4156,7 @@ function testDomRouter( } function ErrorElement() { - let { status, statusText } = useRouteError(); + let { status, statusText } = useRouteError() as ErrorResponse; return

contextual error:{`${status} ${statusText}`}

; } @@ -4046,11 +4181,8 @@ function testDomRouter( }); it("handles fetcher.load errors at the correct spot in the route hierarchy", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } errorElement={

Not I!

}> Not I!

} />
-
+ ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -4074,7 +4211,8 @@ function testDomRouter( } function ErrorElement() { - return

contextual error:{useRouteError().message}

; + let error = useRouteError() as Error; + return

contextual error:{error.message}

; } expect(getHtml(container)).toMatchInlineSnapshot(` @@ -4098,11 +4236,8 @@ function testDomRouter( }); it("handles fetcher.submit errors at the correct spot in the route hierarchy", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } errorElement={

Not I!

}> Not I!

} />
-
+ ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -4137,7 +4277,8 @@ function testDomRouter( } function ErrorElement() { - return

contextual error:{useRouteError().message}

; + let error = useRouteError() as Error; + return

contextual error:{error.message}

; } expect(getHtml(container)).toMatchInlineSnapshot(` @@ -4161,11 +4302,8 @@ function testDomRouter( }); it("handles fetcher.Form errors at the correct spot in the route hierarchy", async () => { - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( } errorElement={

Not I!

}> Not I!

} />
-
+ ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": null } }, + } ); + let { container } = render(); function Comp() { let fetcher = useFetcher(); @@ -4195,7 +4338,8 @@ function testDomRouter( } function ErrorElement() { - return

contextual error:{useRouteError().message}

; + let error = useRouteError() as Error; + return

contextual error:{error.message}

; } expect(getHtml(container)).toMatchInlineSnapshot(` @@ -4230,10 +4374,19 @@ function testDomRouter( describe("errors", () => { it("renders hydration errors on leaf elements", async () => { - let { container } = render( - }> + } + errorElement={} + /> + + ), + { + window: getWindow("/child"), + hydrationData: { loaderData: { "0": "parent data", }, @@ -4243,17 +4396,10 @@ function testDomRouter( errors: { "0-0": new Error("Kaboom 💥"), }, - }} - > - }> - } - errorElement={} - /> - - + }, + } ); + let { container } = render(); function Comp() { let data = useLoaderData(); @@ -4261,16 +4407,16 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); } function ErrorBoundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -4327,16 +4473,16 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); } function ErrorBoundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -4403,16 +4549,16 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); } function ErrorBoundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -4431,22 +4577,24 @@ function testDomRouter( }); it("renders hydration errors on parent elements", async () => { - let { container } = render( - } errorElement={}> + } /> + + ), + { + window: getWindow("/child"), + hydrationData: { loaderData: {}, actionData: null, errors: { "0": new Error("Kaboom 💥"), }, - }} - > - } errorElement={}> - } /> - - + }, + } ); + let { container } = render(); function Comp() { let data = useLoaderData(); @@ -4454,16 +4602,16 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); } function ErrorBoundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -4519,16 +4667,16 @@ function testDomRouter( let navigation = useNavigation(); return (
- {data} - {actionData} - {navigation.state} + <>{data} + <>{actionData} + <>{navigation.state}
); } function ErrorBoundary() { - let error = useRouteError(); + let error = useRouteError() as Error; return

{error.message}

; } @@ -4545,17 +4693,8 @@ function testDomRouter( let fooDefer = createDeferred(); let barDefer = createDeferred(); - let { container } = render( - + let router = createTestRouter( + createRoutesFromElements( }> } /> - + ), + { + window: getWindow("/foo"), + hydrationData: { + loaderData: { + "0-0": { + message: "hydrated from foo", + }, + }, + }, + } ); + let { container } = render(); function Layout() { let navigation = useNavigation(); @@ -4588,23 +4738,23 @@ function testDomRouter( } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } function FooError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Foo Error:{error.message}

; } function Bar() { - let data = useLoaderData(); - return

Bar:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Bar:{data.message}

; } function BarError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Bar Error:{error.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
+ let router = createTestRouter( + createRoutesFromElements( } errorElement={}> } /> - + ), + { + window: getWindow("/foo"), + hydrationData: { + loaderData: { + "0-0": { + message: "hydrated from foo", + }, + }, + }, + } ); + let { container } = render(); function Layout() { let navigation = useNavigation(); @@ -4701,23 +4853,23 @@ function testDomRouter( ); } function LayoutError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Layout Error:{error.message}

; } function Foo() { - let data = useLoaderData(); - return

Foo:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Foo:{data.message}

; } function FooError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Foo Error:{error.message}

; } function Bar() { - let data = useLoaderData(); - return

Bar:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Bar:{data.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
); function Layout() { @@ -4785,15 +4937,15 @@ function testDomRouter( } function Bar() { - let data = useLoaderData(); - return

Bar:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Bar:{data.message}

; } function BarError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Bar Error:{error.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
, @@ -4842,13 +4994,13 @@ function testDomRouter( }, { path: "bar", - lazy: async () => lazyDefer.promise, + lazy: async () => lazyDefer.promise as Promise, }, ], }, ]; - router = createTestRouter(routes, { window: getWindow("/foo") }); + let router = createTestRouter(routes, { window: getWindow("/foo") }); let { container } = render(); function Layout() { @@ -4865,15 +5017,15 @@ function testDomRouter( } function Bar() { - let data = useLoaderData(); - return

Bar:{data?.message}

; + let data = useLoaderData() as { message: string }; + return

Bar:{data.message}

; } function BarError() { - let error = useRouteError(); + let error = useRouteError() as Error; return

Bar Error:{error.message}

; } - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
screen.getByText("idle")); - expect(getHtml(container.querySelector("#output"))) + expect(getHtml(container.querySelector("#output")!)) .toMatchInlineSnapshot(` "
{ + let unsubscribe = router.subscribe((updatedState) => { + if (updatedState.initialized) { + unsubscribe(); + resolve(router); + } + }); + }); +}