// `outline.js`: folding a branch of an outline. // // The fixture is the shape `Row::depth` describes and `node.rs` emits: a flat // list of `[data-row]` siblings, each carrying `data-depth`, each branch // holding a `[data-disclose]` chevron. Nothing here builds a nested list, // because the renderer does not emit one -- the hierarchy is the numbers. // // r0 depth 0 // r1 depth 1 <- a branch // r2 depth 2 // r3 depth 2 // r4 depth 1 <- r1's sibling, not its descendant /** The outline above, in the fixture. */ const outline = () => fixture( ``, ); /** A row's chevron. */ const chevron = (id) => document.getElementById(id).querySelector("[data-disclose]"); /** Whether a row is out of the outline the reader is looking at. */ const gone = (id) => document.getElementById(id).hidden; describe("outline.js, as shipped", () => { beforeEach(outline); it("hides a branch's descendants and leaves its siblings alone", () => { chevron("r1").click(); expect(gone("r2"), "r2 is under r1").to.equal(true); expect(gone("r3"), "r3 is under r1").to.equal(true); expect(gone("r4"), "r4 is a sibling, not a descendant").to.equal(false); }); it("keeps an inner shut branch shut when the outer one reopens", () => { // The property `settle` is a walk rather than a row-by-row toggle for: // a reader who left an inner branch shut expects to come back to it // shut. `quasi_router::folded` makes the same reading on the server, so // a reload has to agree with this. chevron("r1").click(); chevron("r0").click(); expect(gone("r1"), "r1 is under r0").to.equal(true); chevron("r0").click(); expect(gone("r1"), "r1 comes back").to.equal(false); expect(gone("r2"), "r2 stays shut: r1 is still collapsed").to.equal(true); expect(gone("r3"), "r3 stays shut").to.equal(true); }); it("says which way the chevron points, in the two places a reader reads", () => { const shut = chevron("r1"); shut.click(); expect(shut.getAttribute("aria-expanded")).to.equal("false"); expect(shut.getAttribute("aria-label")).to.equal("Expand"); shut.click(); expect(shut.getAttribute("aria-expanded")).to.equal("true"); expect(shut.getAttribute("aria-label")).to.equal("Collapse"); }); it("does not let the fold reach the row's own act", () => { // A chevron is a separate hit target from the label precisely so that // pressing it is not pressing the row. A row that activates on click // would otherwise navigate out from under the fold. let reached = 0; const row = document.getElementById("r1"); row.addEventListener("click", () => { reached += 1; }); chevron("r1").click(); expect(reached, "the click stopped at the chevron").to.equal(0); }); });