| 1 | import assert from "node:assert/strict"; |
| 2 | import { DockNavigation, requestKeys, type DockRequests } from "../app-shell/dockNavigation"; |
| 3 | |
| 4 | for (const key of requestKeys) { |
| 5 | const navigation = new DockNavigation(); |
| 6 | const request = { id: 1, path: "a", paths: ["a"], changes: [], tabId: "session", summary: {} }; |
| 7 | const incoming = { [key]: request } as DockRequests; |
| 8 | navigation.commit("project/session", "one", incoming, ["one", "two"]); |
| 9 | const snapshot = navigation.getSnapshot(); |
| 10 | assert.equal(snapshot[key]?.acceptNavigation?.(), true); |
| 11 | navigation.commit("project/session", "one", { [key]: { ...request } } as DockRequests, ["one", "two"]); |
| 12 | assert.equal(navigation.getSnapshot(), snapshot, `${key}: equivalent input must preserve snapshot`); |
| 13 | assert.equal(snapshot[key]?.acceptNavigation?.(), false); |
| 14 | navigation.commit("project/session", "one", { [key]: { ...request, navigationSource: "another-producer" } } as DockRequests, ["one", "two"]); |
| 15 | assert.equal(navigation.getSnapshot()[key]?.acceptNavigation?.(), true, "producer identities cannot collide"); |
| 16 | navigation.commit("project/session", "one", incoming, ["one", "two"]); |
| 17 | navigation.commit("project/session", "two", incoming, ["one", "two"]); |
| 18 | assert.equal(navigation.getSnapshot()[key], null); |
| 19 | navigation.commit("project/session", "one", incoming, ["one", "two"]); |
| 20 | assert.equal(navigation.getSnapshot()[key], null); |
| 21 | navigation.commit("project/session", "one", { [key]: { ...request, id: 2 } } as DockRequests, ["one"]); |
| 22 | const pending = navigation.getSnapshot()[key]; |
| 23 | navigation.commit("project/session", null, {}, []); |
| 24 | assert.equal(pending?.acceptNavigation?.(), false, "closed occurrence cannot accept a late request"); |
| 25 | navigation.commit("project/session", "one", { [key]: { ...request, id: 2 } } as DockRequests, ["one"]); |
| 26 | assert.equal(navigation.getSnapshot()[key], null, "reopening same ID does not replay"); |
| 27 | const cancellation = new AbortController(); |
| 28 | navigation.commit("project/session", "one", { [key]: { ...request, id: 3, navigationCancellation: cancellation.signal } } as DockRequests, ["one"]); |
| 29 | cancellation.abort(); |
| 30 | assert.equal(navigation.getSnapshot()[key]?.acceptNavigation?.(), false, "cancelled navigation cannot be accepted before reconciliation"); |
| 31 | const lifetime = navigation.getSnapshot().navigationSignal!; |
| 32 | navigation.dispose(); |
| 33 | assert(lifetime.aborted); |
| 34 | } |
| 35 | console.log("PASS five Dock request kinds: stable revision, once-only acceptance, view isolation and close/reopen"); |
| 36 | |
| 37 | const navigation = new DockNavigation(); |
| 38 | navigation.commit("project/session", "one", { changeRevealRequest: { id: 1, path: "report.md" } }, ["one", "two"]); |
| 39 | const original = navigation.getSnapshot(); |
| 40 | navigation.commit("project/session", "two", {}, ["one", "two"]); |
| 41 | const restored = navigation.restoredView("project/session", "one"); |
| 42 | assert.equal(restored.navigationSignal, original.navigationSignal, "a restored view keeps its own lifetime signal"); |
| 43 | for (const key of requestKeys) assert.equal(restored[key], null, "restoration never replays an old command"); |
| 44 | assert.equal(navigation.getSnapshot().changeRevealRequest, null, "reading a restoration does not activate the view"); |
| 45 | assert.equal(navigation.restoredView("project/other-session", "one").navigationSignal, undefined, "a restoration cannot cross scopes"); |
| 46 | navigation.reconcile(["two"]); |
| 47 | assert.equal(navigation.restoredView("project/session", "one").navigationSignal, undefined); |
| 48 | assert(original.navigationSignal?.aborted); |
| 49 | navigation.dispose(); |
| 50 | console.log("PASS a closed view's lifetime ends without activating, replaying or crossing scope boundaries"); |
| 51 |