diff --git a/.changeset/appcontent-route-test-headers-3749.md b/.changeset/appcontent-route-test-headers-3749.md new file mode 100644 index 000000000..a799d3beb --- /dev/null +++ b/.changeset/appcontent-route-test-headers-3749.md @@ -0,0 +1,30 @@ +--- +--- + +Comment-only change, no behaviour and no authoring-surface change (objectui#3749). + +Three docblock passages in the zero-app console routing tests enumerated +`sys-datasources` / `sys-objects` in the present tense as the producers of +`…/component/metadata/resource?type=datasource` and `…/system/metadata/object`. +Both entries were re-pointed at the metadata-admin engine's canonical +`…/metadata/:type` routes — `sys-datasources` by objectui#3660, +`sys-objects` (and the home QuickActions "Manage Objects" card) by +objectui#3739 — so the narration described a producer surface that no longer +exists, while the assertions underneath it stayed correct and green. + +Rewritten as "history + current state" per objectui#3666: what was true at +objectui#3610, then what is true now, with the current-state half stating +positively what the two spellings are today (arrivals for bookmarks, external +links and the host's own alias route) rather than denying where they used to +point. The two `it` titles move off the producer names onto what they actually +measure — each alias still resolving out of the zero-app branch in exactly one +hop, named by its rewriter (`shell alias` / `host alias`). + +No package is declared because nothing published changed: `AppContent.tsx` is a +JSX-comment edit with both `LegacyMetadataRedirect` route declarations and every +other line of code untouched, and the two test files keep their assertions and +case count byte for byte (43 passed before, 43 passed after). The reason this is +worth a commit at all is that the same comment family has gone stale once before +at a measured cost — objectui#3661 / #3669, where a transcription that had +drifted left two cases silently measuring a redirect chain production had +stopped emitting. diff --git a/packages/app-shell/src/console/AppContent.tsx b/packages/app-shell/src/console/AppContent.tsx index 8a958ada0..ef1bdaedb 100644 --- a/packages/app-shell/src/console/AppContent.tsx +++ b/packages/app-shell/src/console/AppContent.tsx @@ -655,9 +655,12 @@ export function AppContent({ extraRoutes, extraRoutesNoApp }: AppContentProps = every one of them rendered a blank screen. #3610 mirrored the routes rather than re-point that navigation, because inventing a zero-app-only spelling would have given the alias a second - canonical destination. #3660 re-pointed it anyway — at the shared - `metadata/:type` routes above, so no second spelling was created — - which leaves these two serving bookmarks and external links, the + canonical destination. #3660 re-pointed `sys-datasources` anyway — + at the shared `metadata/:type` routes above, so no second spelling + was created — and #3739 did the same for `sys-objects` and the + home "Manage Objects" card, whose chain had already left these two + routes at #3658, when the host stopped rewriting onto the alias. + What is left for these two is bookmarks and external links: the arrivals that can never be re-pointed. */} } /> } /> diff --git a/packages/app-shell/src/console/__tests__/AppContent.noAppComponentRoutes.test.tsx b/packages/app-shell/src/console/__tests__/AppContent.noAppComponentRoutes.test.tsx index f8e0eebf7..f722a90db 100644 --- a/packages/app-shell/src/console/__tests__/AppContent.noAppComponentRoutes.test.tsx +++ b/packages/app-shell/src/console/__tests__/AppContent.noAppComponentRoutes.test.tsx @@ -4,20 +4,38 @@ * Zero-app console: the `component/metadata/*` destinations must resolve, and * anything unmatched must say so (objectui#3610). * - * ## The defect + * ## The defect, as it stood at objectui#3610 * - * With zero published apps, the system fallback sidebar offers two entries that - * both land inside `AppContent`'s no-`activeApp` branch: + * With zero published apps, the system fallback sidebar offered two entries + * that both landed inside `AppContent`'s no-`activeApp` branch: * * sys-datasources -> /apps/setup/component/metadata/resource?type=datasource * sys-objects -> /apps/setup/system/metadata/object * - * `isMetadataRoute` is a substring test (`pathname.includes('/metadata')`), so - * both URLs pass the "no apps configured" guard and enter the no-`activeApp` - * ``. That branch declared `create-app`, `system/marketplace*` and - * `metadata*` only — no `component/…` at all — and, unlike the with-`activeApp` - * branch, no trailing `path="*"`. A `` with no match renders `null`: - * a fully blank screen, no 404, no error, no empty state. + * `isMetadataRoute` was a substring test (`pathname.includes('/metadata')`) at + * the time, so both URLs passed the "no apps configured" guard and entered the + * no-`activeApp` ``. That branch declared `create-app`, + * `system/marketplace*` and `metadata*` only — no `component/…` at all — and, + * unlike the with-`activeApp` branch, no trailing `path="*"`. A `` with + * no match renders `null`: a fully blank screen, no 404, no error, no empty + * state. + * + * ## What those two URLs are NOW (objectui#3660, #3739) + * + * Neither is anybody's navigation target any more. Both sidebar entries name + * the metadata-admin engine's canonical routes directly — `sys-datasources` -> + * `/apps/setup/metadata/datasource` (#3660), `sys-objects` -> + * `/apps/setup/metadata/object` (#3739) — as does the home QuickActions + * "Manage Objects" card. The two spellings above are ARRIVALS: bookmarks, + * external links, and, for the `system/metadata/:type` one, the host + * fragment's own alias route, which stays declared for exactly those. + * + * That is why this file still measures them, and why the `it` titles below name + * the alias URL and its rewriter rather than the sidebar entry that used to + * emit it: what is under test is that each alias still RESOLVES out of the + * zero-app branch, and still costs exactly one hop. `isMetadataRoute` is a + * segment test since #3638 (`pathSegments.includes('metadata')`), under which + * every URL here stays true. * * ## Which spelling is canonical — MEASURED, and the opposite of the guess * @@ -49,17 +67,18 @@ * `apps/console/src/AppContent.tsx` (`systemRoutes` + its `MetadataRedirect`). * app-shell cannot import from `apps/` — a different Vitest project — so the * rewrite is copied verbatim, including its `prefix` regex, and this comment is - * the pointer back to the original. It is the `sys-objects` leg of the chain: - * without it that URL's route into this branch is invisible here. + * the pointer back to the original. It is the `system/metadata/:type` leg of + * the chain: without it that URL's route into this branch is invisible here. * * ## Why the chain, not just the endpoint (objectui#3661) * * A transcription can go stale, and this one did. objectui#3658 re-pointed the * host straight at the canonical routes; the copy here kept emitting the - * deprecated alias, so the `sys-objects` case went on measuring a two-hop chain - * that production had stopped producing. Nothing went red — the assertions - * pinned only the final pathname, and that is identical either way. Green, for - * a reason that no longer had anything to do with the code under test. + * deprecated alias, so the `system/metadata/object` case went on measuring a + * two-hop chain that production had stopped producing. Nothing went red — the + * assertions pinned only the final pathname, and that is identical either way. + * Green, for a reason that no longer had anything to do with the code under + * test. * * So `renderConsoleAt` now returns every location the router settles on, and * all four redirect cases assert that list exactly. A stub that drifts back @@ -265,15 +284,18 @@ describe('AppContent — zero-app component/metadata destinations (objectui#3610 vi.clearAllMocks(); }); - it('sys-datasources: /apps/setup/component/metadata/resource?type=datasource renders the resource page', async () => { + it('shell alias: /apps/setup/component/metadata/resource?type=datasource resolves in the zero-app branch and hops ONCE to the canonical page', async () => { // The white screen this issue is about. The URL passes `isMetadataRoute` - // (substring `/metadata`) and so enters the no-`activeApp` branch, which - // used to declare nothing matching `component/…` and had no catch-all. + // (a `metadata` path segment; a substring test until #3638) and so enters + // the no-`activeApp` branch, which used to declare nothing matching + // `component/…` and had no catch-all. // // Unlike the two host-rewrite cases below, the alias here is the ENTRY, not - // an intermediate stop — the zero-app fallback sidebar's `sys-datasources` - // item still points straight at this spelling, so this chain is one this - // deployment really produces. + // an intermediate stop: nothing rewrites it on the way in, so this branch's + // own route table is the whole story. The `sys-datasources` sidebar item is + // what emitted it at #3610; since #3660 that item names the canonical route + // and this spelling arrives from bookmarks and external links instead — + // which is precisely why the redirect has to keep working. const chain = renderConsoleAt('/apps/setup/component/metadata/resource?type=datasource'); const page = await screen.findByTestId('metadata-resource-list-page'); @@ -294,17 +316,20 @@ describe('AppContent — zero-app component/metadata destinations (objectui#3610 expect(screen.queryByTestId('root-landing')).not.toBeInTheDocument(); }); - it('sys-objects: /apps/setup/system/metadata/object reaches this branch\'s metadata/:type in ONE hop', async () => { + it('host alias: /apps/setup/system/metadata/object reaches this branch\'s metadata/:type in ONE hop', async () => { // The non-obvious half, pinned on its own because it would regress // silently: this URL is rewritten by the HOST (`MetadataRedirect`) onto the // canonical route, which the zero-app branch declares itself. Two route // tables, one redirect, zero apps. // // It used to be two redirects — the host aimed at the legacy alias and the - // shell forwarded that on. objectui#3658 removed the middle stop; this case - // now measures what production actually does, and objectui#3661 is what it - // cost to notice that it had stopped doing so (the endpoint never moved, so - // nothing failed). + // shell forwarded that on. objectui#3658 removed the middle stop, and + // objectui#3661 is what it cost to notice that the transcribed stub had not + // followed (the endpoint never moved, so nothing failed). Since #3739 no + // click in this repo emits this URL either — `sys-objects` and the home + // "Manage Objects" card name the canonical route — so what is pinned here + // is the arrival path the host still declares for bookmarks and external + // links. const chain = renderConsoleAt('/apps/setup/system/metadata/object'); const page = await screen.findByTestId('metadata-resource-list-page'); diff --git a/packages/app-shell/src/console/__tests__/AppContent.pseudoRouteSegments.test.tsx b/packages/app-shell/src/console/__tests__/AppContent.pseudoRouteSegments.test.tsx index 45072c277..5df9143fc 100644 --- a/packages/app-shell/src/console/__tests__/AppContent.pseudoRouteSegments.test.tsx +++ b/packages/app-shell/src/console/__tests__/AppContent.pseudoRouteSegments.test.tsx @@ -38,14 +38,27 @@ * metadata,metadata/:type,metadata/:type/:name}` * (`developer/*` and `docs/*` are in the same * fragment but flip NO flag — pinned below) - * navigation AppSidebar / UnifiedSidebar `/apps/setup/system{,/apps,/marketplace, - * /metadata/object,/users,/organizations, - * /roles,/settings}` - * `/apps/setup/component/metadata/resource?type=` - * QuickActions / HomePage / `/apps/setup/system/{metadata/object,marketplace, - * InboxPopover approvals}` + * navigation AppSidebar / UnifiedSidebar `/apps/setup/system{,/apps,/marketplace,/users, + * /organizations,/roles,/settings}` + * `/apps/setup/metadata/{object,datasource}` + * QuickActions `/apps/setup/metadata/object`, `/apps/setup/system` + * HomePage / InboxPopover `/apps/setup/system/{marketplace,approvals}` * SystemRedirect (#3637) bare `/system` -> `/apps/setup/system` * + * The metadata-admin entries moved after #3638 landed: the sidebars' + * `sys-objects` / `sys-datasources` items and the QuickActions "Manage Objects" + * card once spelled `…/system/metadata/object` and + * `…/component/metadata/resource?type=datasource`; #3739 and #3660 re-pointed + * all three at the engine's canonical `…/metadata/:type` routes. Those two + * older spellings are still in this input surface, as ARRIVALS rather than + * emissions — declared in the two rows above + * (`component/metadata/{directory,resource/*}` in the shell, + * `system/metadata{,/:type}` in the host) and reached from bookmarks and + * external links. `metadata` is a whole path segment either way, so the claim + * below is indifferent to the move; the `navigation` row is re-read here + * because a producer list naming URLs nothing emits any more is the stale + * pointer objectui#3661 was paid for. + * * In EVERY one of them `system` / `metadata` is a whole path segment, so a * segment test keeps all of them true. That is the claim this file's first two * describes exist to falsify.