// ── NatusWheelSpec.js ───────────────────────────────────────────────────────── // // Unit specs for natus-wheel.js — planet hover tooltips. // // DOM contract assumed: // — target for NatusWheel.draw() //
— tooltip portal (position:fixed on page) // // Public API under test: // NatusWheel.draw(svgEl, data) — renders wheel; attaches hover listeners // NatusWheel.clear() — empties the SVG (used in afterEach) // // Hover contract: // mouseover on [data-planet] group → adds .nw-planet--hover class // shows #id_natus_tooltip with // planet name, in-sign degree, sign name // and ℞ if retrograde // mouseout on [data-planet] group → removes .nw-planet--hover // hides #id_natus_tooltip // // In-sign degree: ecliptic_longitude % 30 (e.g. 338.4° → 8.4° Pisces) // // ───────────────────────────────────────────────────────────────────────────── describe("NatusWheel — planet tooltips", () => { const SYNTHETIC_CHART = { planets: { Sun: { sign: "Pisces", degree: 338.4, retrograde: false }, Moon: { sign: "Capricorn", degree: 295.1, retrograde: false }, Mercury: { sign: "Aquarius", degree: 312.8, retrograde: true }, }, houses: { cusps: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330], asc: 0, mc: 270, }, elements: { Fire: 1, Stone: 2, Air: 1, Water: 3, Time: 1, Space: 2 }, aspects: [], distinctions: { "1": 0, "2": 0, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0, "10": 0, "11": 0, "12": 0, }, house_system: "P", }; let svgEl, tooltipEl; beforeEach(() => { // SVG element — D3 draws into this svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgEl.setAttribute("id", "id_natus_svg"); svgEl.setAttribute("width", "400"); svgEl.setAttribute("height", "400"); svgEl.style.width = "400px"; svgEl.style.height = "400px"; document.body.appendChild(svgEl); // Tooltip portal — same markup as _natus_overlay.html tooltipEl = document.createElement("div"); tooltipEl.id = "id_natus_tooltip"; tooltipEl.className = "tt"; tooltipEl.style.display = "none"; document.body.appendChild(tooltipEl); NatusWheel.draw(svgEl, SYNTHETIC_CHART); }); afterEach(() => { NatusWheel.clear(); svgEl.remove(); tooltipEl.remove(); }); // ── T3 ── hover planet shows name / sign / in-sign degree + glow ───────── it("T3: hovering a planet group adds the glow class and shows the tooltip with name, sign, and in-sign degree", () => { const sun = svgEl.querySelector("[data-planet='Sun']"); expect(sun).not.toBeNull("expected [data-planet='Sun'] to exist in the SVG"); sun.dispatchEvent(new MouseEvent("mouseover", { bubbles: true })); expect(sun.classList.contains("nw-planet--hover")).toBe(true); expect(tooltipEl.style.display).toBe("block"); const text = tooltipEl.textContent; expect(text).toContain("Sun"); expect(text).toContain("Pisces"); // in-sign degree: 338.4° ecliptic − 330° (Pisces start) = 8.4° expect(text).toContain("8.4"); }); // ── T4 ── retrograde planet shows ℞ ────────────────────────────────────── it("T4: hovering a retrograde planet shows ℞ in the tooltip", () => { const mercury = svgEl.querySelector("[data-planet='Mercury']"); expect(mercury).not.toBeNull("expected [data-planet='Mercury'] to exist in the SVG"); mercury.dispatchEvent(new MouseEvent("mouseover", { bubbles: true })); expect(tooltipEl.style.display).toBe("block"); expect(tooltipEl.textContent).toContain("℞"); }); // ── T5 ── mouseout hides tooltip and removes glow ───────────────────────── it("T5: mouseout hides the tooltip and removes the glow class", () => { const sun = svgEl.querySelector("[data-planet='Sun']"); expect(sun).not.toBeNull("expected [data-planet='Sun'] to exist in the SVG"); sun.dispatchEvent(new MouseEvent("mouseover", { bubbles: true })); expect(tooltipEl.style.display).toBe("block"); // relatedTarget is document.body — outside the planet group sun.dispatchEvent(new MouseEvent("mouseout", { bubbles: true, relatedTarget: document.body, })); expect(tooltipEl.style.display).toBe("none"); expect(sun.classList.contains("nw-planet--hover")).toBe(false); }); });