@khanacademy/wonder-blocks-testing-core 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @khanacademy/wonder-blocks-testing-core
2
2
 
3
+ ## 5.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b5618a5: The `router` test harness adapter now supports a data-routes mode for exercising React Router v6 data routers. Passing a `routes` config renders `createMemoryRouter` + `RouterProvider` so that route `loader`s run and `errorElement`s render (`useRouteError`/`useLoaderData`, redirects, deferred data) — unlike context mode, which only provides routing context via `MemoryRouter`/`StaticRouter`.
8
+
9
+ The mode is selected purely by config shape: pass `routes` (plus optional `initialEntries`/`initialIndex`/`hydrationData`) for data-routes mode, or a location for the existing context mode. Provide `routes` as a function `(harnessedComponent) => RouteObject[]` for full control over where the harnessed component is mounted (e.g. as an `errorElement`), or as an array to mount it as the matched leaf route's `element` (the leaf must not define its own `element`, `Component`, or `lazy`). Pass `hydrationData` to pre-resolve loaders and render synchronously. Context mode is unchanged and backward-compatible, and combining the two modes is a type error.
10
+
11
+ The router adapter's config type is now exported as `RouterAdapterConfig`.
12
+
3
13
  ## 5.0.0
4
14
 
5
15
  ### Major Changes
package/dist/es/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { StaticRouter, MemoryRouter, Switch, Route } from 'react-router-dom';
4
- import { CompatRouter, useLocation } from 'react-router-dom-v5-compat';
4
+ import { CompatRouter, useLocation, matchRoutes, createMemoryRouter, RouterProvider } from 'react-router-dom-v5-compat';
5
5
  import * as ReactDOMServer from 'react-dom/server';
6
6
 
7
7
  const getHref=input=>{if(typeof input==="string"){return input}else if(typeof input.url==="string"){return input.url}else if(typeof input.href==="string"){return input.href}else {throw new Error(`Unsupported input type`)}};const fetchRequestMatchesMock=(mock,input,init)=>{const href=getHref(input);if(typeof mock==="string"){return href===mock}else if(mock instanceof RegExp){return mock.test(href)}else {throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`)}};
@@ -26,7 +26,7 @@ const defaultConfig$2=null;class ErrorBoundary extends React.Component{static ge
26
26
 
27
27
  const defaultConfig$1=null;const adapter$1=(children,config)=>jsxs(Fragment,{children:[jsx("div",{id:config,"data-testid":config}),children]});
28
28
 
29
- const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsx(Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxs(Switch,{children:[jsx(Route,{path:path,render:()=>jsx(Fragment,{children:children})}),jsx(Route,{path:"*",component:ErrorElement})]})};const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsx(StaticRouter,{location:config.location,context:{},children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsx(StaticRouter,{location:config.location,context:{},children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsx(MemoryRouter,{initialEntries:[config.location],children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsx(MemoryRouter,{...routerProps,children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
29
+ const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsx(Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxs(Switch,{children:[jsx(Route,{path:path,render:()=>jsx(Fragment,{children:children})}),jsx(Route,{path:"*",component:ErrorElement})]})};const describeLocation=location=>typeof location==="string"?location:location.pathname??"";const injectChildrenIntoRoutes=(routes,harnessedElement,location)=>{const matches=matchRoutes(routes,location);if(matches==null||matches.length===0){throw new Error(`No route in \`routes\` matches the location `+`'${describeLocation(location)}'. In array \`routes\` mode the `+`harnessed component is mounted as the matched leaf route's `+`\`element\`, so a route must match the location. Use the `+`function form \`routes: (harnessedComponent) => [...]\` to `+`place the component yourself.`)}const leafRoute=matches[matches.length-1].route;const cloneWithChildren=routeList=>routeList.map(route=>{if(route===leafRoute){if(route.element!=null||route.Component!=null||route.lazy!=null){throw new Error(`The route matching the location already defines an `+`\`element\`, \`Component\`, or \`lazy\`. In array `+`\`routes\` mode the harnessed component is mounted `+`as the matched leaf's \`element\`, so that leaf must `+`not define its own \`element\`, \`Component\`, or `+`\`lazy\`. Use the function form `+`\`routes: (harnessedComponent) => [...]\` for full `+`control.`)}return {...route,element:harnessedElement}}if(route.children!=null){return {...route,children:cloneWithChildren(route.children)}}return {...route}});return cloneWithChildren(routes)};const HarnessedChildrenContext=React.createContext(null);const ChildrenSlot=()=>jsx(Fragment,{children:React.useContext(HarnessedChildrenContext)});const CachedDataRouter=({routes,options})=>{const routerRef=React.useRef(null);if(routerRef.current==null){routerRef.current=createMemoryRouter(routes,options);}return jsx(RouterProvider,{router:routerRef.current})};const renderDataRoutes=(children,config)=>{const initialEntries=config.initialEntries==null||config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const harnessedSlot=jsx(ChildrenSlot,{});const routes=typeof config.routes==="function"?[...config.routes(harnessedSlot)]:injectChildrenIntoRoutes(config.routes,harnessedSlot,initialEntries[config.initialIndex??initialEntries.length-1]);if(config.hydrationData==null&&typeof Request==="undefined"){throw new Error("Data-routes mode runs route `loader`s, which require the Fetch "+"API `Request` global. Polyfill `Request`/`Response` in your "+"test environment, or pass `hydrationData` to pre-resolve "+"loaders without running them.")}const options={initialEntries,...config.initialIndex!=null?{initialIndex:config.initialIndex}:{},...config.hydrationData!=null?{hydrationData:config.hydrationData}:{}};return jsx(HarnessedChildrenContext.Provider,{value:children,children:jsx(CachedDataRouter,{routes:routes,options:options})})};const isDataRoutesConfig=config=>"routes"in config&&config.routes!=null;const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if(isDataRoutesConfig(config)){return renderDataRoutes(children,config)}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsx(StaticRouter,{location:config.location,context:{},children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsx(StaticRouter,{location:config.location,context:{},children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsx(MemoryRouter,{initialEntries:[config.location],children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsx(MemoryRouter,{...routerProps,children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
30
30
 
31
31
  const DefaultAdapters={boundary:adapter$2,css:adapter$3,portal:adapter$1,router:adapter};const DefaultConfigs={boundary:defaultConfig$2,css:defaultConfig$3,portal:defaultConfig$1,router:defaultConfig};
32
32
 
@@ -1,3 +1,4 @@
1
+ import * as router from "./router";
1
2
  import type { TestHarnessConfigs } from "../types";
2
3
  /**
3
4
  * NOTE: We do not type `DefaultAdapters` with `Adapters` here because we want
@@ -16,19 +17,7 @@ export declare const DefaultAdapters: {
16
17
  style: import("aphrodite").CSSProperties;
17
18
  }>;
18
19
  readonly portal: import("../types").TestHarnessAdapter<string>;
19
- readonly router: import("../types").TestHarnessAdapter<string | Readonly<{
20
- initialEntries: import("history").LocationDescriptor<unknown>[] | undefined;
21
- initialIndex?: number | undefined;
22
- path?: string;
23
- } | {
24
- location: import("history").LocationDescriptor;
25
- forceStatic: true;
26
- disableCompatRouter?: boolean;
27
- path?: string;
28
- } | {
29
- location: import("history").LocationDescriptor;
30
- path?: string;
31
- }>>;
20
+ readonly router: import("../types").TestHarnessAdapter<router.Config>;
32
21
  };
33
22
  /**
34
23
  * The default configurations to use with the `DefaultAdapters`.
@@ -1,12 +1,105 @@
1
1
  import * as React from "react";
2
2
  import { MemoryRouter } from "react-router-dom";
3
+ import { createMemoryRouter } from "react-router-dom-v5-compat";
3
4
  import type { LocationDescriptor } from "history";
5
+ import type { RouteObject } from "react-router-dom-v5-compat";
4
6
  import type { TestHarnessAdapter } from "../types";
5
7
  type MemoryRouterProps = JSX.LibraryManagedAttributes<typeof MemoryRouter, React.ComponentProps<typeof MemoryRouter>>;
6
8
  /**
7
- * Configuration for the withLocation test harness adapter.
9
+ * The options accepted by `createMemoryRouter` (RR v6 data router).
8
10
  */
9
- type Config = Readonly<{
11
+ type DataRouterOptions = NonNullable<Parameters<typeof createMemoryRouter>[1]>;
12
+ /**
13
+ * A tree of RR v6 route objects for the data-routes mode.
14
+ */
15
+ type DataRoutes = ReadonlyArray<RouteObject>;
16
+ /**
17
+ * Keys that only exist in data-routes mode.
18
+ *
19
+ * They are forbidden (typed as `never`) in context mode so the two modes can
20
+ * never be combined: passing a context-mode `location` alongside `routes` is a
21
+ * type error.
22
+ */
23
+ type NotDataRoutes = {
24
+ routes?: never;
25
+ hydrationData?: never;
26
+ };
27
+ /**
28
+ * Configuration for the data-routes mode of the `router` adapter.
29
+ *
30
+ * Selected by the presence of `routes`. Renders a RR v6 data router
31
+ * (`createMemoryRouter` + `RouterProvider`) so that route `loader`s run and
32
+ * `errorElement`s render — unlike context mode, which only provides routing
33
+ * context.
34
+ */
35
+ type DataRoutesConfig = {
36
+ /**
37
+ * The RR v6 route tree to render.
38
+ *
39
+ * Provide either:
40
+ *
41
+ * - A function `(harnessedComponent) => routes` for full control over
42
+ * where the harnessed component is mounted (e.g. as a route's
43
+ * `errorElement`). The `harnessedComponent` argument is a stable
44
+ * placeholder element: mount it wherever you like and it will always
45
+ * render the current harnessed component, even across rerenders.
46
+ * - An array of route objects, in which case the harnessed component is
47
+ * mounted as the `element` of the route that matches the initial
48
+ * location. In this form the matched leaf route must not define its own
49
+ * `element`, `Component`, or `lazy`.
50
+ */
51
+ routes: DataRoutes | ((harnessedComponent: React.ReactNode) => DataRoutes);
52
+ /**
53
+ * The initial history entries for the data router.
54
+ *
55
+ * Defaults to the adapter's default location when absent or empty.
56
+ */
57
+ initialEntries?: DataRouterOptions["initialEntries"];
58
+ /**
59
+ * The index of `initialEntries` to render first.
60
+ */
61
+ initialIndex?: DataRouterOptions["initialIndex"];
62
+ /**
63
+ * Pre-resolved loader data and errors.
64
+ *
65
+ * When provided, the data router starts already initialized: route
66
+ * `loader`s do not run and the tree renders synchronously. This is the
67
+ * robust choice for asserting on loader-resolved or error states, as it
68
+ * avoids running loaders (which require the Fetch API in the test
69
+ * environment) and the associated render loop.
70
+ *
71
+ * NOTE: This is the data-routes analog of context mode's `forceStatic`.
72
+ * The server data-router APIs (`createStaticHandler`/`createStaticRouter`/
73
+ * `StaticRouterProvider`) aren't reachable through `react-router-dom-v5-compat`,
74
+ * so `hydrationData` provides the same "pre-resolved, synchronous, no
75
+ * loaders run" guarantee that `forceStatic` provides in context mode.
76
+ */
77
+ hydrationData?: DataRouterOptions["hydrationData"];
78
+ /**
79
+ * Context-mode-only keys, forbidden here so the two modes can't mix.
80
+ *
81
+ * `forceStatic`/`disableCompatRouter` are context-router concepts;
82
+ * data-routes mode uses `hydrationData` for pre-resolved rendering instead.
83
+ */
84
+ location?: never;
85
+ path?: never;
86
+ forceStatic?: never;
87
+ disableCompatRouter?: never;
88
+ };
89
+ /**
90
+ * Configuration for the router test harness adapter.
91
+ *
92
+ * There are two modes, selected purely by the shape of the config:
93
+ *
94
+ * - Context mode (a location string / `{location}` / `{initialEntries}`)
95
+ * renders a `MemoryRouter` or `StaticRouter` around the harnessed component.
96
+ * Use it for components that consume routing (`useNavigate`, `useParams`,
97
+ * `<Link>`). This is the common case.
98
+ * - Data-routes mode (a config including `routes`) renders a RR v6 data router
99
+ * (`createMemoryRouter` + `RouterProvider`). Use it when a route `loader` or
100
+ * `errorElement` needs to run for the test.
101
+ */
102
+ export type Config = Readonly<(NotDataRoutes & {
10
103
  /**
11
104
  * See MemoryRouter prop for initialEntries.
12
105
  */
@@ -28,7 +121,7 @@ type Config = Readonly<{
28
121
  * will not render the component.
29
122
  */
30
123
  path?: string;
31
- } | {
124
+ }) | (NotDataRoutes & {
32
125
  /**
33
126
  * The location to use.
34
127
  */
@@ -59,7 +152,7 @@ type Config = Readonly<{
59
152
  * will not render the component.
60
153
  */
61
154
  path?: string;
62
- } | {
155
+ }) | (NotDataRoutes & {
63
156
  /**
64
157
  * The initial location to use.
65
158
  */
@@ -77,7 +170,7 @@ type Config = Readonly<{
77
170
  * will not render the component.
78
171
  */
79
172
  path?: string;
80
- }> | string;
173
+ }) | DataRoutesConfig> | string;
81
174
  /**
82
175
  * The default configuration for this adapter.
83
176
  */
@@ -16,17 +16,5 @@ export declare const testHarness: <TProps extends object>(Component: import("rea
16
16
  style: import("aphrodite").CSSProperties;
17
17
  }>;
18
18
  readonly portal: import("./types").TestHarnessAdapter<string>;
19
- readonly router: import("./types").TestHarnessAdapter<string | Readonly<{
20
- initialEntries: import("history").LocationDescriptor<unknown>[] | undefined;
21
- initialIndex?: number | undefined;
22
- path?: string;
23
- } | {
24
- location: import("history").LocationDescriptor;
25
- forceStatic: true;
26
- disableCompatRouter?: boolean;
27
- path?: string;
28
- } | {
29
- location: import("history").LocationDescriptor;
30
- path?: string;
31
- }>>;
19
+ readonly router: import("./types").TestHarnessAdapter<import("..").RouterAdapterConfig>;
32
20
  }>> | undefined) => import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<TProps> & import("react").RefAttributes<unknown>>;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export type { FetchMockFn, FetchMockOperation } from "./fetch/types";
7
7
  export type { GraphQLJson, MockFn, OperationMock, OperationMatcher, MockOperationFn, MockConfiguration, ConfigureFn, } from "./types";
8
8
  export * from "./harness/types";
9
9
  export * as harnessAdapters from "./harness/adapters/adapters";
10
+ export type { Config as RouterAdapterConfig } from "./harness/adapters/router";
10
11
  export { makeHookHarness } from "./harness/make-hook-harness";
11
12
  export { makeTestHarness } from "./harness/make-test-harness";
12
13
  export { hookHarness } from "./harness/hook-harness";
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ const defaultConfig$2=null;class ErrorBoundary extends React__namespace.Componen
51
51
 
52
52
  const defaultConfig$1=null;const adapter$1=(children,config)=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{id:config,"data-testid":config}),children]});
53
53
 
54
- const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=reactRouterDomV5Compat.useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxRuntime.jsxs(reactRouterDom.Switch,{children:[jsxRuntime.jsx(reactRouterDom.Route,{path:path,render:()=>jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}),jsxRuntime.jsx(reactRouterDom.Route,{path:"*",component:ErrorElement})]})};const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{initialEntries:[config.location],children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{...routerProps,children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
54
+ const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=reactRouterDomV5Compat.useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxRuntime.jsxs(reactRouterDom.Switch,{children:[jsxRuntime.jsx(reactRouterDom.Route,{path:path,render:()=>jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}),jsxRuntime.jsx(reactRouterDom.Route,{path:"*",component:ErrorElement})]})};const describeLocation=location=>typeof location==="string"?location:location.pathname??"";const injectChildrenIntoRoutes=(routes,harnessedElement,location)=>{const matches=reactRouterDomV5Compat.matchRoutes(routes,location);if(matches==null||matches.length===0){throw new Error(`No route in \`routes\` matches the location `+`'${describeLocation(location)}'. In array \`routes\` mode the `+`harnessed component is mounted as the matched leaf route's `+`\`element\`, so a route must match the location. Use the `+`function form \`routes: (harnessedComponent) => [...]\` to `+`place the component yourself.`)}const leafRoute=matches[matches.length-1].route;const cloneWithChildren=routeList=>routeList.map(route=>{if(route===leafRoute){if(route.element!=null||route.Component!=null||route.lazy!=null){throw new Error(`The route matching the location already defines an `+`\`element\`, \`Component\`, or \`lazy\`. In array `+`\`routes\` mode the harnessed component is mounted `+`as the matched leaf's \`element\`, so that leaf must `+`not define its own \`element\`, \`Component\`, or `+`\`lazy\`. Use the function form `+`\`routes: (harnessedComponent) => [...]\` for full `+`control.`)}return {...route,element:harnessedElement}}if(route.children!=null){return {...route,children:cloneWithChildren(route.children)}}return {...route}});return cloneWithChildren(routes)};const HarnessedChildrenContext=React__namespace.createContext(null);const ChildrenSlot=()=>jsxRuntime.jsx(jsxRuntime.Fragment,{children:React__namespace.useContext(HarnessedChildrenContext)});const CachedDataRouter=({routes,options})=>{const routerRef=React__namespace.useRef(null);if(routerRef.current==null){routerRef.current=reactRouterDomV5Compat.createMemoryRouter(routes,options);}return jsxRuntime.jsx(reactRouterDomV5Compat.RouterProvider,{router:routerRef.current})};const renderDataRoutes=(children,config)=>{const initialEntries=config.initialEntries==null||config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const harnessedSlot=jsxRuntime.jsx(ChildrenSlot,{});const routes=typeof config.routes==="function"?[...config.routes(harnessedSlot)]:injectChildrenIntoRoutes(config.routes,harnessedSlot,initialEntries[config.initialIndex??initialEntries.length-1]);if(config.hydrationData==null&&typeof Request==="undefined"){throw new Error("Data-routes mode runs route `loader`s, which require the Fetch "+"API `Request` global. Polyfill `Request`/`Response` in your "+"test environment, or pass `hydrationData` to pre-resolve "+"loaders without running them.")}const options={initialEntries,...config.initialIndex!=null?{initialIndex:config.initialIndex}:{},...config.hydrationData!=null?{hydrationData:config.hydrationData}:{}};return jsxRuntime.jsx(HarnessedChildrenContext.Provider,{value:children,children:jsxRuntime.jsx(CachedDataRouter,{routes:routes,options:options})})};const isDataRoutesConfig=config=>"routes"in config&&config.routes!=null;const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if(isDataRoutesConfig(config)){return renderDataRoutes(children,config)}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{initialEntries:[config.location],children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{...routerProps,children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
55
55
 
56
56
  const DefaultAdapters={boundary:adapter$2,css:adapter$3,portal:adapter$1,router:adapter};const DefaultConfigs={boundary:defaultConfig$2,css:defaultConfig$3,portal:defaultConfig$1,router:defaultConfig};
57
57
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "",
4
4
  "author": "Khan Academy",
5
5
  "license": "MIT",
6
- "version": "5.0.0",
6
+ "version": "5.1.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "devDependencies": {
33
33
  "@khanacademy/wonder-stuff-testing": "^4.0.3",
34
- "@khanacademy/wb-dev-build-settings": "3.2.0"
34
+ "@khanacademy/wb-dev-build-settings": "3.3.0"
35
35
  },
36
36
  "scripts": {
37
37
  "test": "echo \"Error: no test specified\" && exit 1"