diff --git a/packages/remix-react/index.tsx b/packages/remix-react/index.tsx index 9ba8a629125..a571864c16f 100644 --- a/packages/remix-react/index.tsx +++ b/packages/remix-react/index.tsx @@ -49,7 +49,6 @@ export { useLoaderData, useMatches, useActionData, - RemixContext as UNSAFE_RemixContext, } from "./components"; export type { FormMethod, FormEncType } from "./data"; diff --git a/packages/remix-testing/create-remix-stub.tsx b/packages/remix-testing/create-remix-stub.tsx index 8189e2dbf3f..4d5fb9a4338 100644 --- a/packages/remix-testing/create-remix-stub.tsx +++ b/packages/remix-testing/create-remix-stub.tsx @@ -1,23 +1,9 @@ import * as React from "react"; -import type { - AssetsManifest, - EntryContext, - EntryRoute, - RouteData, - RouteManifest, - RouteModules, -} from "@remix-run/react"; -import { UNSAFE_RemixContext as RemixContext } from "@remix-run/react"; -import { StaticRouterProvider } from "react-router-dom/server"; +import type { RouteData } from "@remix-run/react"; import type { RouteObject } from "react-router-dom"; +import { RouterProvider } from "react-router-dom"; import { createMemoryRouter } from "react-router-dom"; -import { matchRoutes, json } from "react-router-dom"; -import type { - AgnosticDataRouteObject, - InitialEntry, - StaticHandler, - StaticHandlerContext, -} from "@remix-run/router"; +import type { InitialEntry } from "@remix-run/router"; import { createStaticHandler } from "@remix-run/router"; type RemixStubOptions = { @@ -35,28 +21,12 @@ type RemixStubOptions = { */ initialLoaderData?: RouteData; - /** - * Used to set the route's initial loader headers. - * e.g. initialLoaderHeaders={{ "/contact": { "Content-Type": "application/json" } }} - */ - initialLoaderHeaders?: Record; - /** * Used to set the route's initial action data. * e.g. initialActionData={{ "/login": { errors: { email: "invalid email" } }} */ initialActionData?: RouteData; - /** - * Used to set the route's initial action headers. - */ - initialActionHeaders?: Record; - - /** - * Used to set the route's initial status code. - */ - initialStatusCode?: number; - /** * The initial index in the history stack to render. This allows you to start a test at a specific entry. * It defaults to the last entry in initialEntries. @@ -67,154 +37,30 @@ type RemixStubOptions = { initialIndex?: number; }; -type RemixConfigFuture = Partial; - -export function createRemixStub( - routes: RouteObject[], - remixConfigFuture?: RemixConfigFuture -) { +export function createRemixStub(routes: RouteObject[]) { // Setup request handler to handle requests to the mock routes let staticHandler = createStaticHandler(routes); return function RemixStub({ initialEntries, initialIndex, - initialLoaderData = {}, initialActionData, - initialActionHeaders, - initialLoaderHeaders, - initialStatusCode: statusCode, + initialLoaderData, }: RemixStubOptions) { - let memoryRouter = createMemoryRouter(staticHandler.dataRoutes, { + let router = createMemoryRouter(staticHandler.dataRoutes, { initialEntries, initialIndex, + hydrationData: { + actionData: initialActionData, + loaderData: initialLoaderData, + }, }); - let manifest = createManifest(staticHandler.dataRoutes); - let matches = matchRoutes(routes, memoryRouter.state.location) || []; - let future: EntryContext["future"] = { - v2_meta: false, - ...remixConfigFuture, - }; - let routeModules = createRouteModules(staticHandler.dataRoutes); - - let staticHandlerContext: StaticHandlerContext = { - actionData: initialActionData || null, - actionHeaders: initialActionHeaders || {}, - loaderData: initialLoaderData || {}, - loaderHeaders: initialLoaderHeaders || {}, - basename: "", - errors: null, - location: memoryRouter.state.location, - // @ts-expect-error - matches, - statusCode: statusCode || 200, - }; - - // Patch fetch so that mock routes can handle action/loader requests - monkeyPatchFetch(staticHandler); - - return ( - - - - ); - }; -} - -function createManifest(routes: AgnosticDataRouteObject[]): AssetsManifest { - return { - routes: createRouteManifest(routes), - entry: { imports: [], module: "" }, - url: "", - version: "", - }; -} - -function createRouteManifest( - routes: AgnosticDataRouteObject[], - manifest?: RouteManifest, - parentId?: string -): RouteManifest { - return routes.reduce((manifest, route) => { - if (route.children) { - createRouteManifest(route.children, manifest, route.id); - } - manifest[route.id!] = convertToEntryRoute(route, parentId); - return manifest; - }, manifest || {}); -} - -function createRouteModules( - routes: AgnosticDataRouteObject[], - routeModules?: RouteModules -): RouteModules { - return routes.reduce((modules, route) => { - if (route.children) { - createRouteModules(route.children, modules); - } - - modules[route.id!] = { - CatchBoundary: undefined, - ErrorBoundary: undefined, - // @ts-expect-error - types are still `agnostic` here - default: () => route.element, - handle: route.handle, - links: undefined, - meta: undefined, - shouldRevalidate: undefined, - }; - return modules; - }, routeModules || {}); -} - -const originalFetch = - typeof global !== "undefined" ? global.fetch : window.fetch; - -function monkeyPatchFetch(staticHandler: StaticHandler) { - let fetchPatch = async ( - input: RequestInfo | URL, - init: RequestInit = {} - ): Promise => { - let request = new Request(input, init); - let url = new URL(request.url); - - // if we have matches, send the request to mock routes via @remix-run/router rather than the normal - // @remix-run/server-runtime so that stubs can also be used in browser environments. - let matches = matchRoutes(staticHandler.dataRoutes, url); - if (matches && matches.length > 0) { - let response = await staticHandler.queryRoute(request); - - if (response instanceof Response) { - return response; - } - - return json(response); - } - - // if no matches, passthrough to the original fetch as mock routes couldn't handle the request. - return originalFetch(request, init); - }; - - globalThis.fetch = fetchPatch; -} + React.useLayoutEffect(() => { + return router.subscribe((state) => { + console.log("state", state); + }); + }, []); -function convertToEntryRoute( - route: AgnosticDataRouteObject, - parentId?: string -): EntryRoute { - return { - id: route.id!, - index: route.index, - caseSensitive: route.caseSensitive, - path: route.path, - parentId, - hasAction: !!route.action, - hasLoader: !!route.loader, - module: "", - hasCatchBoundary: false, - hasErrorBoundary: false, + return ; }; }