feat(steps): draw all arms of conditional navigations as separate edges
Adds multi-arm navigation support: when a destination is produced by a conditional, every arm is now drawn as its own edge. Introduces helpers (hrefArms, destinationsForHref) and updates framework resolvers and edge creation to emit multiple navigates edges (via alsoTargets) instead of a single one. Also introduces per-app rooted route tables to avoid cross-app crossings, and updates various resolvers (React Router, TanStack Router, Vue Router, SvelteKit, Vue, and SvelteKit’s linker) and the UI to reflect multiple possible destinations. Tests and docs updated to reflect the new behavior, ensuring the Screens tab shows all possible navigation paths from conditional destinations. This makes navigation visualization more accurate for forked destinations.
This commit is contained in:
@@ -263,7 +263,9 @@ describe('nextjs: end to end', () => {
|
||||
const link = screens.links.find((l) => l.from === home.id && l.to === users.id)!;
|
||||
expect(link.via).toEqual([]);
|
||||
expect(link.synthesized).toBe(true);
|
||||
expect(link.sites[0]).toMatchObject({ href: '/users', method: 'return' });
|
||||
// Markup, not a return value: the destination is written right there, so
|
||||
// the site keeps its own verb rather than reading as a helper's return.
|
||||
expect(link.sites[0]).toMatchObject({ href: '/users', method: 'link' });
|
||||
const push = screens.links.find((l) => l.from === users.id && l.to === user.id)!;
|
||||
expect(push).toBeDefined();
|
||||
expect(push.via.map((v) => v.name)).toEqual(['NewUserForm', 'handleSubmit']);
|
||||
@@ -274,6 +276,14 @@ describe('nextjs: end to end', () => {
|
||||
expect(screens.dropped).toBe(0);
|
||||
});
|
||||
|
||||
it('an endpoint is not a screen — the Screens tab is pages, Entry points is every route', async () => {
|
||||
const screens = await buildScreens(cg, tmpDir);
|
||||
// `GET /api/users` and `POST /api/users` are routes, and they are on the
|
||||
// Entry points list — but a request is not somewhere a user can be.
|
||||
expect(screens.screens.map((s) => s.path).sort()).toEqual(['/', '/login', '/users', '/users/:id']);
|
||||
expect(cg.getNodesByKind('route').some((r) => r.name === 'POST /api/users')).toBe(true);
|
||||
});
|
||||
|
||||
it('a page’s Steps picture fires from its load, crosses to the server action, and draws the pages it leads to as boundaries', async () => {
|
||||
const p = await buildSteps(cg, tmpDir, new URLSearchParams({ anchor: route('/users').id }));
|
||||
expect(p.project).toBe('web');
|
||||
|
||||
Reference in New Issue
Block a user