summaryrefslogtreecommitdiffhomepage
path: root/src/features/layout/logic/panel-keys.test.ts
blob: b45671af3446174a16db6eda6a9f7b9e42bd36bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { describe, expect, it } from "vitest";
import { initialPanelKeys, reconcilePanelKeys, swappedPanels } from "./panel-keys";

describe("initialPanelKeys", () => {
  it("numbers the panels in order and seeds past them", () => {
    expect(initialPanelKeys(["tabs", "model"])).toEqual({
      views: ["tabs", "model"],
      keys: [0, 1],
      seed: 2,
    });
  });
});

describe("reconcilePanelKeys", () => {
  const start = initialPanelKeys(["tabs", "model", "usage"]); // keys 0 1 2

  it("closing the MIDDLE panel drops the middle key (not the last)", () => {
    const next = reconcilePanelKeys(start, ["tabs", "usage"]);
    expect(next.keys).toEqual([0, 2]);
    expect(next.seed).toBe(3);
  });

  it("adding a panel gives only the new one a fresh key", () => {
    const next = reconcilePanelKeys(start, ["tabs", "model", "usage", "lsp"]);
    expect(next.keys).toEqual([0, 1, 2, 3]);
    expect(next.seed).toBe(4);
  });

  it("a dropdown swap keeps every key positional", () => {
    const next = reconcilePanelKeys(start, ["tabs", "lsp", "usage"]);
    expect(next.keys).toEqual([0, 1, 2]);
  });

  it("handles duplicate views and never reuses a key", () => {
    const dup = initialPanelKeys(["a", "b", "a"]); // 0 1 2
    const removed = reconcilePanelKeys(dup, ["a", "a"]);
    expect(removed.keys).toEqual([0, 2]);
    const added = reconcilePanelKeys(removed, ["a", "a", "a"]);
    expect(added.keys).toEqual([0, 2, 3]);
    expect(new Set(added.keys).size).toBe(3);
  });

  it("a ✕ hint picks the exact panel when identical views make it ambiguous", () => {
    const twins = initialPanelKeys(["model", "usage", "usage"]); // 0 1 2
    expect(reconcilePanelKeys(twins, ["model", "usage"]).keys).toEqual([0, 1]); // no hint
    expect(reconcilePanelKeys(twins, ["model", "usage"], 1).keys).toEqual([0, 2]);
  });

  it("ignores a stale hint that does not describe the change", () => {
    // The tree changed some other way (e.g. a remote edit) — fall back to LCS.
    expect(reconcilePanelKeys(start, ["tabs", "model"], 0).keys).toEqual([0, 1]);
    expect(reconcilePanelKeys(start, ["tabs", "model", "usage"], 1).keys).toEqual([0, 1, 2]);
  });

  it("an unrelated replacement of different length gets all-fresh keys", () => {
    const next = reconcilePanelKeys(start, ["x"]);
    expect(next.keys).toEqual([3]);
  });
});

describe("swappedPanels", () => {
  it("reports a surviving panel whose view changed", () => {
    const prev = initialPanelKeys(["tabs", "model"]);
    const next = reconcilePanelKeys(prev, ["tabs", "usage"]);
    expect([...swappedPanels(prev, next)]).toEqual([[1, { from: "model", to: "usage" }]]);
  });

  it("does not report adds or removes", () => {
    const prev = initialPanelKeys(["tabs", "model", "usage"]);
    expect(swappedPanels(prev, reconcilePanelKeys(prev, ["tabs", "usage"])).size).toBe(0);
    expect(swappedPanels(prev, reconcilePanelKeys(prev, [...prev.views, "lsp"])).size).toBe(0);
  });
});