Make the hidden attribute win over display rules
The tutorial panel and the loudness warning are flex boxes, and their display rule overrode the browser's hidden attribute, so both were drawn at all times. The browser tests now check the computed display of both, and that the Tutorial button opens and its close button closes the panel.
2 changed files+16−2
src/style.cssmodified+2−0View file
@@ -15,6 +15,8 @@
1515 color-scheme: dark;
1616 }
1717 * { box-sizing: border-box; }
18+/* The hidden attribute must win over any display rule below (the tutorial panel and the loudness warning are flex boxes). */
19+[hidden] { display: none !important; }
1820 html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg); }
1921 a { color: var(--accent); }
2022 #app { display: flex; height: 100vh; overflow: hidden; }
tests/gpu.test.tsmodified+14−2View file
@@ -90,7 +90,16 @@ test("the linear model computes the modes and synthesizes a strike", async () =>
9090 });
9191
9292 test("the tutorial opens, typesets its mathematics, and its actions drive the application", async () => {
93+ const shown = (page: Page) => page.evaluate(() => getComputedStyle(document.getElementById("tutorial")!).display !== "none");
94+ await withPage("preset=flat-rectangle&spacing=0.016", async (page) => {
95+ assert.equal(await shown(page), false, "closed by default");
96+ await page.click("#tutorialBtn");
97+ assert.equal(await shown(page), true, "the button opens it");
98+ await page.click("#tutorial .tut-close");
99+ assert.equal(await shown(page), false, "the close button closes it");
100+ });
93101 await withPage("preset=flat-rectangle&tutorial=modes&spacing=0.016", async (page, errors) => {
102+ assert.equal(await shown(page), true);
94103 const opened = await page.evaluate(() => {
95104 const t = document.getElementById("tutorial")!;
96105 return { hidden: t.hidden, katex: t.querySelectorAll(".katex").length, title: t.querySelector("h2")?.textContent ?? "", buttons: Array.from(t.querySelectorAll(".tut-actions button")).map((b) => b.textContent) };
@@ -129,10 +138,13 @@ test("a loud recording warns before playing and plays once accepted", async () =
129138 const run = (script: string) => page.evaluate((s: string) => {
130139 const a = (window as unknown as { cymbalsim: { app: A } }).cymbalsim.app;
131140 new Function("a", s)(a);
132- return { playing: a.player.playing, warn: !a.loudWarn.hidden, text: a.loudWarn.textContent ?? "" };
141+ // Whether the warning is drawn, not merely whether its attribute is set.
142+ return { playing: a.player.playing, warn: getComputedStyle(a.loudWarn).display !== "none", text: a.loudWarn.textContent ?? "" };
133143 }, script);
144+ let r = await run("");
145+ assert.equal(r.warn, false, "no warning before Play");
134146 // Normalizing the peak puts it at -1 dBFS: Play warns instead of playing.
135- let r = await run(`a.levelMode = "peak"; a.updatePeak(); a.togglePlay();`);
147+ r = await run(`a.levelMode = "peak"; a.updatePeak(); a.togglePlay();`);
136148 assert.equal(r.playing, false);
137149 assert.equal(r.warn, true);
138150 assert.match(r.text, /-1\.0 dBFS/);