Test gap: INV-AUDIO-103 parity guard only enforces TS-side, CSS literal can drift silently #107

Closed
opened 2026-05-01 14:24:01 +00:00 by Brouie · 4 comments
Brouie commented 2026-05-01 14:24:01 +00:00 (Migrated from gitlab.com)

P3-low test gap: mobileAlbumDockLayout.test.ts only asserts MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM === 4.5. It does not read frontend/src/index.css and verify the + 4.5rem literal still matches. The invariant INV-AUDIO-103 is one-way — TS-side drift fails CI, CSS-side drift passes silently.

Repro

frontend/src/audio/mobileAlbumDockLayout.test.ts (entire file):

import { MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM } from "./mobileAlbumDockLayout";

describe("mobileAlbumDockLayout (GitLab #103)", () => {
  it("exports clearance rem token mirrored in index.css for INV-AUDIO-103", () => {
    expect(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM).toBe(4.5);
  });
});

The test name says "mirrored in index.css" but the assertion only checks the TS-side constant.

Why it matters

INV-AUDIO-103 per docs/testing/invariants-and-business-logic.md and the new skills/contributor-mobile-album-dock/SKILL.md is bidirectional: the CSS + 4.5rem term and the TS constant must stay in sync. A contributor can:

  • Change MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM from 4.5 to 5 → test fails ✓ (caught)
  • Change index.css line 3157 + 4.5rem → + 5rem → test passes ✗ (silent drift, mobile dock overlap regresses)

The second path is exactly the regression #103 was filed to fix.

Proposed fix

Extend the test to read index.css and parse the literal:

import fs from "node:fs";
import path from "node:path";
import { MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM } from "./mobileAlbumDockLayout";

describe("mobileAlbumDockLayout (GitLab #103)", () => {
  it("TS constant matches the index.css safe-area-inset-top + Nrem literal (INV-AUDIO-103)", () => {
    const css = fs.readFileSync(path.resolve(__dirname, "../index.css"), "utf8");
    const m = css.match(/env\(safe-area-inset-top,\s*0px\)\s*\+\s*([\d.]+)rem/);
    expect(m).not.toBeNull();
    expect(parseFloat(m![1])).toBe(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM);
  });
});

This matches the pattern used in frontend-dapp/src/viteConfig.build.test.ts in the DEX repo (filesystem read in a unit test for cross-file invariants).

Verified locally: only one match for safe-area-inset-top in index.css (the line 3157 dock-clearance rule). Regex is unambiguous.

Severity

P3-low. Test gap, not a runtime bug. The current 4.5 value is correct; this is about preventing future silent drift on a documented invariant.

Acceptance

  • mobileAlbumDockLayout.test.ts reads index.css and asserts the safe-area-inset-top + Nrem literal equals MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM.
  • Test fails if either side drifts independently.
  • No regression on the existing single-side assertion.

cc @PlasticDigits

P3-low test gap: `mobileAlbumDockLayout.test.ts` only asserts `MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM === 4.5`. It does not read `frontend/src/index.css` and verify the `+ 4.5rem` literal still matches. The invariant `INV-AUDIO-103` is one-way — TS-side drift fails CI, CSS-side drift passes silently. ### Repro `frontend/src/audio/mobileAlbumDockLayout.test.ts` (entire file): ```ts import { MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM } from "./mobileAlbumDockLayout"; describe("mobileAlbumDockLayout (GitLab #103)", () => { it("exports clearance rem token mirrored in index.css for INV-AUDIO-103", () => { expect(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM).toBe(4.5); }); }); ``` The test name says "mirrored in index.css" but the assertion only checks the TS-side constant. ### Why it matters `INV-AUDIO-103` per `docs/testing/invariants-and-business-logic.md` and the new `skills/contributor-mobile-album-dock/SKILL.md` is **bidirectional**: the CSS `+ 4.5rem` term and the TS constant must stay in sync. A contributor can: - Change `MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM` from `4.5` to `5` → test fails ✓ (caught) - Change `index.css` line 3157 `+ 4.5rem` → `+ 5rem` → test passes ✗ (silent drift, mobile dock overlap regresses) The second path is exactly the regression #103 was filed to fix. ### Proposed fix Extend the test to read `index.css` and parse the literal: ```ts import fs from "node:fs"; import path from "node:path"; import { MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM } from "./mobileAlbumDockLayout"; describe("mobileAlbumDockLayout (GitLab #103)", () => { it("TS constant matches the index.css safe-area-inset-top + Nrem literal (INV-AUDIO-103)", () => { const css = fs.readFileSync(path.resolve(__dirname, "../index.css"), "utf8"); const m = css.match(/env\(safe-area-inset-top,\s*0px\)\s*\+\s*([\d.]+)rem/); expect(m).not.toBeNull(); expect(parseFloat(m![1])).toBe(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM); }); }); ``` This matches the pattern used in `frontend-dapp/src/viteConfig.build.test.ts` in the DEX repo (filesystem read in a unit test for cross-file invariants). Verified locally: only one match for `safe-area-inset-top` in `index.css` (the line 3157 dock-clearance rule). Regex is unambiguous. ### Severity P3-low. Test gap, not a runtime bug. The current 4.5 value is correct; this is about preventing future silent drift on a documented invariant. ### Acceptance - [ ] `mobileAlbumDockLayout.test.ts` reads `index.css` and asserts the `safe-area-inset-top + Nrem` literal equals `MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM`. - [ ] Test fails if either side drifts independently. - [ ] No regression on the existing single-side assertion. cc @PlasticDigits
PlasticDigits commented 2026-05-02 05:02:56 +00:00 (Migrated from gitlab.com)

mentioned in commit 117dca7fd7

mentioned in commit 117dca7fd7401e2616bc7e77e6d993e1c8936e22
PlasticDigits commented 2026-05-02 05:03:39 +00:00 (Migrated from gitlab.com)

Implemented on main (117dca7)

Extended mobileAlbumDockLayout.test.ts so INV-AUDIO-103 is enforced both ways: the canonical 4.5 assertion remains, and Vitest reads frontend/src/index.css and matches the env(safe-area-inset-top, 0px) + Nrem literal to MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM (GitLab #107 acceptance).

Docs / cross-links: docs/testing/invariants-and-business-logic.md §103, manual-qa-checklists.md #103, skills/contributor-mobile-album-dock/SKILL.md, skills/README.md, .cursor/skills/yieldomega-guardrails/SKILL.md.

Verification checklist for @brouie

  • cd frontend && npm run test -- src/audio/mobileAlbumDockLayout.test.ts passes locally (2 tests).
  • Temporarily change only + 4.5rem in .app-header mobile margin-top in index.css → Vitest should fail; revert.
  • Temporarily change only MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM → Vitest should fail; revert.
  • Confirm mobileAlbumDockLayout.ts JSDoc still points at the parity test (#107).

Leaving this issue open for your sign-off.

## Implemented on `main` (117dca7) Extended [`mobileAlbumDockLayout.test.ts`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/audio/mobileAlbumDockLayout.test.ts) so **INV-AUDIO-103** is enforced **both ways**: the canonical `4.5` assertion remains, and Vitest reads [`frontend/src/index.css`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/index.css) and matches the `env(safe-area-inset-top, 0px) + Nrem` literal to `MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM` (GitLab #107 acceptance). **Docs / cross-links:** [`docs/testing/invariants-and-business-logic.md` §103](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/invariants-and-business-logic.md), [`manual-qa-checklists.md` #103](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/manual-qa-checklists.md), [`skills/contributor-mobile-album-dock/SKILL.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/skills/contributor-mobile-album-dock/SKILL.md), [`skills/README.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/skills/README.md), [`.cursor/skills/yieldomega-guardrails/SKILL.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/.cursor/skills/yieldomega-guardrails/SKILL.md). **Verification checklist for @brouie** - [ ] `cd frontend && npm run test -- src/audio/mobileAlbumDockLayout.test.ts` passes locally (2 tests). - [ ] Temporarily change only `+ 4.5rem` in `.app-header` mobile `margin-top` in `index.css` → Vitest should fail; revert. - [ ] Temporarily change only `MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM` → Vitest should fail; revert. - [ ] Confirm [`mobileAlbumDockLayout.ts`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/audio/mobileAlbumDockLayout.ts) JSDoc still points at the parity test (#107). Leaving this issue **open** for your sign-off.
Brouie commented 2026-05-03 22:49:14 +00:00 (Migrated from gitlab.com)

Verification PASS on 117dca7

All acceptance items verified.

Acceptance items

[✓] Test passes baseline — npx vitest run src/audio/mobileAlbumDockLayout.test.ts → 2/2 PASS in 3ms.

[✓] CSS-side drift detected — Mutated index.css line 3157 from + 4.5rem to + 5.5rem. Test 2 (parity) failed:

AssertionError: expected 5.5 to be 4.5
src/audio/mobileAlbumDockLayout.test.ts:20:31
expect(parseFloat(m![1])).toBe(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM)

Reverted, baseline restored.

[✓] TS-side drift detected — Mutated mobileAlbumDockLayout.ts line 19 constant from 4.5 to 5.5. Both tests failed:

  • Test 1 (canonical): expected 5.5 to be 4.5 at line 13
  • Test 2 (parity): expected 4.5 to be 5.5 at line 20

Reverted, baseline restored (re-ran 2/2 PASS).

[✓] JSDoc points at parity test — mobileAlbumDockLayout.ts lines 14-16:

Vitest mobileAlbumDockLayout.test.ts asserts bidirectional parity (GitLab #107).

INV-AUDIO-103 now bidirectionally enforced. cc @PlasticDigits

## Verification PASS on `117dca7` All acceptance items verified. ### Acceptance items [✓] **Test passes baseline** — `npx vitest run src/audio/mobileAlbumDockLayout.test.ts` → 2/2 PASS in 3ms. [✓] **CSS-side drift detected** — Mutated `index.css` line 3157 from `+ 4.5rem` to `+ 5.5rem`. Test 2 (parity) failed: AssertionError: expected 5.5 to be 4.5 src/audio/mobileAlbumDockLayout.test.ts:20:31 expect(parseFloat(m![1])).toBe(MOBILE_HEADER_TOP_CLEARANCE_BELOW_SAFE_AREA_REM) Reverted, baseline restored. [✓] **TS-side drift detected** — Mutated `mobileAlbumDockLayout.ts` line 19 constant from `4.5` to `5.5`. Both tests failed: - Test 1 (canonical): `expected 5.5 to be 4.5` at line 13 - Test 2 (parity): `expected 4.5 to be 5.5` at line 20 Reverted, baseline restored (re-ran 2/2 PASS). [✓] **JSDoc points at parity test** — `mobileAlbumDockLayout.ts` lines 14-16: > Vitest mobileAlbumDockLayout.test.ts asserts bidirectional parity (GitLab #107). INV-AUDIO-103 now bidirectionally enforced. cc @PlasticDigits
Brouie commented 2026-05-04 01:09:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #103

mentioned in issue #103
Brouie (Migrated from gitlab.com) closed this issue 2026-05-04 03:10:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#107
No description provided.