A page used to be listed three times (lib/modules for its label, icon and gate; shell/moduleRegistry for its page and rail; lib/pageMeta for its title), and App held every rail's layout and collapse flag. Now each module's `module.ts` says it all — label, icon, gate, its lazy page and rail, its width — handed out through its index.ts, and features/navigation/moduleRegistry lists them in nav order for the rail, the palette, the tab title, the reachable set and the shell's render. A contract test holds the registry to the page ids and each definition to its own folder, with no static import of a page. Every rail is lazy now, loaded together with its page so a pinned rail never arrives after it and shoves the content aside; the feed's and the playlists' rails took @dnd-kit off the boot path (boot 428.5 → 393.9 KiB gzip, the App chunk 122 → 32 KiB). A rail reads its own layout and collapse flag (lib/useRail) and writes a layout change to the `me` cache too, since it now mounts anew on each visit. App's session effects, its one-shot entry-URL handlers and the admin nudge move into shell hooks; App is layout. The registry's three layer suppressions are gone: none is left.
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
// A page whose rail sits in its flow must not be ready before the rail: the rail would then appear a
|
|
// moment after the page and shove its content sideways.
|
|
import { describe, expect, it } from "vitest";
|
|
import type { ComponentType } from "react";
|
|
import { lazyWithPreload, lazyWithPreloadAlongside } from "./lazyWithPreload";
|
|
|
|
const component = (() => null) as ComponentType<object>;
|
|
|
|
describe("lazyWithPreloadAlongside", () => {
|
|
it("is ready only once its rail has loaded too", async () => {
|
|
let releaseRail = () => {};
|
|
const rail = lazyWithPreload(
|
|
() =>
|
|
new Promise<{ default: ComponentType<object> }>((resolve) => {
|
|
releaseRail = () => resolve({ default: component });
|
|
}),
|
|
);
|
|
const page = lazyWithPreloadAlongside(async () => ({ default: component }), rail);
|
|
let pageReady = false;
|
|
const loading = page.preload().then(() => {
|
|
pageReady = true;
|
|
});
|
|
await new Promise((r) => setTimeout(r, 0));
|
|
expect(pageReady).toBe(false); // its own code is in, its rail's is not
|
|
releaseRail();
|
|
await loading;
|
|
expect(pageReady).toBe(true);
|
|
});
|
|
});
|