diff options
| author | Adam Malczewski <[email protected]> | 2026-09-03 18:05:29 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-09-03 18:05:29 +0900 |
| commit | 3a4922a05930b0dc22740bf5621910803e8f275e (patch) | |
| tree | d5f831c3d3838cfff346e378f5370a9c58bc2ed3 /src/features/plugins/logic/highlight.test.ts | |
| parent | 33c7245f18346553f660434bc3ac589cff3e80c2 (diff) | |
| download | dispatch-web-3a4922a05930b0dc22740bf5621910803e8f275e.tar.gz dispatch-web-3a4922a05930b0dc22740bf5621910803e8f275e.zip | |
feat(plugin-system): plan 07 frontend plugin manager ui
Diffstat (limited to 'src/features/plugins/logic/highlight.test.ts')
| -rw-r--r-- | src/features/plugins/logic/highlight.test.ts | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/features/plugins/logic/highlight.test.ts b/src/features/plugins/logic/highlight.test.ts new file mode 100644 index 0000000..616f7ad --- /dev/null +++ b/src/features/plugins/logic/highlight.test.ts @@ -0,0 +1,60 @@ +import { describe, expect, it } from "vitest"; +import { dependencyHighlightSets } from "./highlight"; +import { node } from "./test-fixtures"; + +describe("dependencyHighlightSets", () => { + const nodes = [ + node({ id: "lib", loaded: false, section: "discovered" }), + node({ id: "mid", dependsOn: ["lib"] }), + node({ id: "app", dependsOn: ["mid", "lib"] }), + ]; + + it("returns empty sets for no hover", () => { + const sets = dependencyHighlightSets(null, nodes); + expect(sets.deps.size).toBe(0); + expect(sets.dependents.size).toBe(0); + }); + + it("hovering an item highlights its DIRECT dependencies (one hop)", () => { + const sets = dependencyHighlightSets("app", nodes); + expect(sets.deps).toEqual(new Set(["mid", "lib"])); + expect(sets.dependents.size).toBe(0); + }); + + it("hovering a dependency highlights its dependents (both directions work)", () => { + const sets = dependencyHighlightSets("lib", nodes); + expect(sets.deps.size).toBe(0); + expect(sets.dependents).toEqual(new Set(["mid", "app"])); + }); + + it("hovering a middle node highlights BOTH directions", () => { + const sets = dependencyHighlightSets("mid", nodes); + expect(sets.deps).toEqual(new Set(["lib"])); + expect(sets.dependents).toEqual(new Set(["app"])); + }); + + it("is one hop — not the transitive closure", () => { + // app → mid → lib: hovering app highlights mid + lib (both direct deps), + // but hovering lib highlights only DIRECT dependents (mid, app) — already + // one hop. The one-hop rule shows in: a plugin two hops away via an + // unrelated chain is not highlighted. + const chain = [ + node({ id: "a" }), + node({ id: "b", dependsOn: ["a"] }), + node({ id: "c", dependsOn: ["b"] }), + ]; + expect(dependencyHighlightSets("c", chain).deps).toEqual(new Set(["b"])); + }); + + it("returns empty sets for an unknown hovered id", () => { + const sets = dependencyHighlightSets("ghost", nodes); + expect(sets.deps.size).toBe(0); + expect(sets.dependents.size).toBe(0); + }); + + it("works across sections (a loaded row highlights an unloaded dependency)", () => { + // `app` loaded, `lib` discovered: hovering app still highlights lib. + const sets = dependencyHighlightSets("app", nodes); + expect(sets.deps.has("lib")).toBe(true); + }); +}); |
