+ | undefined;
+ return (
+
+ Path at {props.name}: {routeFunc?.(props.params) ?? ''}
+
+ );
+ } catch (ex) {
+ return (
+
+ Error at {props.name}, {String(ex)}
+
+ );
+ }
+ };
+
+ let ExtensionPage1: typeof MockComponent;
+ let ExtensionPage2: typeof MockComponent;
+ let ExtensionPage3: typeof MockComponent;
+ let ExtensionSource1: typeof MockRouteSource;
+ let ExtensionSource2: typeof MockRouteSource;
+
+ beforeAll(() => {
+ jest.doMock('react', () => React);
+ jest.doMock('react-router', () =>
+ rrVersion === 'beta'
+ ? jest.requireActual('react-router')
+ : jest.requireActual('react-router-stable'),
+ );
+ jest.doMock('react-router-dom', () =>
+ rrVersion === 'beta'
+ ? jest.requireActual('react-router-dom')
+ : jest.requireActual('react-router-dom-stable'),
+ );
+
+ const { createRoutableExtension } = requireDeps();
+
+ ExtensionPage1 = plugin.provide(
+ createRoutableExtension({
+ name: 'ExtensionPage1',
+ component: () => Promise.resolve(MockComponent),
+ mountPoint: refPage1,
+ }),
+ );
+ ExtensionPage2 = plugin.provide(
+ createRoutableExtension({
+ name: 'ExtensionPage2',
+ component: () => Promise.resolve(MockComponent),
+ mountPoint: refPage2,
+ }),
+ );
+ ExtensionPage3 = plugin.provide(
+ createRoutableExtension({
+ name: 'ExtensionPage3',
+ component: () => Promise.resolve(MockComponent),
+ mountPoint: refPage3,
+ }),
+ );
+ ExtensionSource1 = plugin.provide(
+ createRoutableExtension({
+ name: 'ExtensionSource1',
+ component: () => Promise.resolve(MockRouteSource),
+ mountPoint: refSource1,
+ }),
+ );
+ ExtensionSource2 = plugin.provide(
+ createRoutableExtension({
+ name: 'ExtensionSource2',
+ component: () => Promise.resolve(MockRouteSource),
+ mountPoint: refSource2,
+ }),
+ );
+ });
+
+ afterAll(() => {
+ jest.resetModules();
+ jest.resetAllMocks();
+ jest.restoreAllMocks();
+ jest.clearAllMocks();
+ });
+
+ function withRoutingProvider(
+ root: ReactElement,
+ routeBindings: [ExternalRouteRef, RouteRef][] = [],
+ ) {
+ const { routing } = traverseElementTree({
+ root,
+ discoverers: [childDiscoverer, routeElementDiscoverer],
+ collectors: {
+ routing: routingV2Collector,
+ },
+ });
+ const { RoutingProvider } = requireDeps();
+
+ return (
+
+ {root}
+
+ );
+ }
+
+ it('should handle simple routeRef path creation for routeRefs used in other parts of the app', async () => {
+ const { MemoryRouter, Routes, Route } = requireDeps();
+ const root = (
+
+
+
+
+
+
+ >
+ }
+ >
+
+ }
+ />
+
+ } />
+
+
+
+
+
+
+
+
+
+ );
+
+ const rendered = render(
+ withRoutingProvider(root, [
+ [eRefA, refPage2],
+ [eRefB, refPage1],
+ [eRefC, refSource1],
+ [eRefD, refPage1],
+ ]),
+ );
+
+ await new Promise(r => setTimeout(r, 500));
+
+ rendered.debug();
+ await expect(
+ rendered.findByText('Path at inside: /foo/bar'),
+ ).resolves.toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at insideExternal: /baz'),
+ ).toBeInTheDocument();
+ expect(rendered.getByText('Path at outside: /foo/bar')).toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at outsideExternal1: /foo'),
+ ).toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at outsideExternal2: /foo/bar'),
+ ).toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at outsideExternal3: /foo'),
+ ).toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at outsideExternal4: '),
+ ).toBeInTheDocument();
+ });
+
+ it('should handle routeRefs with parameters', async () => {
+ const { MemoryRouter, Routes, Route } = requireDeps();
+ const root = (
+
+
+
+ }>
+
+ }
+ />
+
+
+
+
+
+ );
+
+ const rendered = render(withRoutingProvider(root));
+
+ await expect(
+ rendered.findByText('Path at inside: /foo/bar/bleb'),
+ ).resolves.toBeInTheDocument();
+ expect(
+ rendered.getByText('Path at outside: /foo/bar/blob'),
+ ).toBeInTheDocument();
+ });
+
+ it('should handle relative routing within parameterized routePaths', async () => {
+ const { MemoryRouter, Routes, Route } = requireDeps();
+ const root = (
+
+
+
+
+ }>
+
+ }
+ />
+ } />
+
+
+
+
+
+
+
+ );
+
+ const rendered = render(withRoutingProvider(root));
+
+ await expect(
+ rendered.findByText('Path at inside: /foo/blob/baz'),
+ ).resolves.toBeInTheDocument();
+ rendered.debug();
+ });
+
+ it('should throw errors for routing to other routeRefs with unsupported parameters', () => {
+ const { MemoryRouter, Routes, Route } = requireDeps();
+ const root = (
+
+
+ }>
+ }
+ />
+ } />
+
+
+
+
+
+ );
+
+ const rendered = render(withRoutingProvider(root));
+
+ expect(
+ rendered.getByText(
+ `Error at outsideWithParams, Error: Cannot route to ${refPage2} with parent ${refPage3} as it has parameters`,
+ ),
+ ).toBeInTheDocument();
+ expect(
+ rendered.getByText(
+ `Error at outsideNoParams, Error: Cannot route to ${refPage2} with parent ${refPage3} as it has parameters`,
+ ),
+ ).toBeInTheDocument();
+ });
+
+ it('should handle relative routing of parameterized routePaths with duplicate param names', () => {
+ const { MemoryRouter, Routes, Route } = requireDeps();
+ const root = (
+
+
+ }>
+ }
+ />
+
+
+
+ );
+
+ const { routing } = traverseElementTree({
+ root,
+ discoverers: [childDiscoverer, routeElementDiscoverer],
+ collectors: {
+ routing: routingV2Collector,
+ },
+ });
+
+ expect(() =>
+ validateRouteParameters(routing.paths, routing.parents),
+ ).toThrow('Parameter :id is duplicated in path foo/:id/bar/:id');
+ });
+});