diff --git a/tests/e2e/dashboard-mobile.html b/tests/e2e/dashboard-mobile.html index 889749f8..4fb87e3c 100644 --- a/tests/e2e/dashboard-mobile.html +++ b/tests/e2e/dashboard-mobile.html @@ -30,7 +30,13 @@
-
+ +
diff --git a/tests/e2e/dashboard-mobile.spec.js b/tests/e2e/dashboard-mobile.spec.js index 78877eae..00671aa5 100644 --- a/tests/e2e/dashboard-mobile.spec.js +++ b/tests/e2e/dashboard-mobile.spec.js @@ -200,17 +200,24 @@ test.describe('Dashboard mobile layout', () => { await expect(list).toBeVisible(); const popover = await list.evaluate((node) => { const input = document.querySelector('[aria-label="region"]'); - const toolbar = document.querySelector('.dash-toolbar.has-variables'); + // #473: `.dash-toolbar-variables` is the real class the app always builds; + // `ui/dashboard.ts` never sets a `has-variables`/`has-filters` class. The + // show/hide contract is its inline `style.display`, which the app leaves + // unset (not `'none'`) whenever ordinary variables are present, as here. + const toolbar = document.querySelector('.dash-toolbar-variables'); const listRect = node.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); return { position: getComputedStyle(node).position, anchored: Math.abs(listRect.left - inputRect.left) < 2 && listRect.top >= inputRect.bottom, escapesToolbar: listRect.bottom > toolbar.getBoundingClientRect().bottom, + toolbarDisplay: toolbar.style.display, pageOverflow: document.documentElement.scrollWidth - innerWidth, }; }); - expect(popover).toEqual({ position: 'fixed', anchored: true, escapesToolbar: true, pageOverflow: 0 }); + expect(popover).toEqual({ + position: 'fixed', anchored: true, escapesToolbar: true, toolbarDisplay: '', pageOverflow: 0, + }); await first.press('Enter'); await expect(first).toHaveValue('alpha'); }); @@ -290,7 +297,11 @@ test.describe('Dashboard mobile layout', () => { await expect(page.locator('.dash-filter-count')).toHaveCount(0); await expect(page.locator('.dash-filter-count-host')).toHaveCount(0); - const toolbar = page.locator('.dash-toolbar.has-variables'); + // #473: real class (never `has-variables`/`has-filters` — the app doesn't set + // one); the actual show/hide contract is the inline `style.display` the app + // sets only to hide the toolbar, asserted here directly. + const toolbar = page.locator('.dash-toolbar-variables'); + expect(await toolbar.evaluate((node) => node.style.display)).toBe(''); const before = await toolbar.evaluate((node) => node.getBoundingClientRect().height); const layout = await page.evaluate(() => { diff --git a/tests/unit/dashboard.test.ts b/tests/unit/dashboard.test.ts index 03ac4e68..6ddaf435 100644 --- a/tests/unit/dashboard.test.ts +++ b/tests/unit/dashboard.test.ts @@ -3280,6 +3280,24 @@ describe('renderDashboard — compound time-range control (#335)', () => { expect(ordinaryToolbar.contains(liveRegion)).toBe(false); }); + // #473: the counterpart to the test above — the "shown" half of the same + // ternary (`src/ui/dashboard.ts`'s `hasOrdinaryVariables ? undefined : { + // display: 'none' }`) was asserted nowhere against a real `createApp` + // render; only the e2e fixture's hand-written markup modeled it. An ordinary + // (non-time-range) variable — `region` here — must leave the toolbar with NO + // inline display override at all, not merely "not none". + it('shows the ordinary-variable toolbar with no inline display override when an ordinary variable is present', async () => { + const { app } = dashApp({ + workspace: wsWith({ + queries: [paired(PAIR + ' AND r = {region:String}')], + tiles: [{ id: 't1', queryId: 'q1' }], + }), + }); + await render(app); + const ordinaryToolbar = qs(app.root, '.dash-toolbar-variables'); + expect(ordinaryToolbar.style.display).toBe(''); + }); + it('Apply commits BOTH bounds through session.applyVariables in one wave and announces the range', async () => { const { app, calls } = dashApp({ workspace: wsWith({ queries: [paired()], tiles: [{ id: 't1', queryId: 'q1' }] }),