fix(cms): stable bottom bar and self-save no longer trips the 409 lock
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions

MITHOME-68: the optimistic-lock fingerprint was frozen at page load, so the
user's own second save 409'd. /save now returns the hash of the written
content and the client refreshes CONTENT_HASH on success — 409 only fires
for genuine external changes (deploy, other tab, restore). Also: successful
logins no longer consume the auth failure budget (only failed attempts do).

MITHOME-69: bottom bar items no longer shift while saving/publishing — the
status message occupies a constant flex slot (visibility instead of
display), the publish button locks its width while running and restores
its env-specific label, auto margins removed. Layout guard test added.

Test markers are now run-unique so a crashed run can never poison the
next one's expectations.
This commit is contained in:
Do Siki
2026-08-19 14:04:49 +02:00
parent 41a2259ede
commit 88383049d5
6 changed files with 126 additions and 20 deletions
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env node
/**
* Layout guard for the CMS bottom bar (MITHOME-69): the bar items must not
* shift while saving/publishing. Asserts the invariants that keep the layout
* stable:
* - the status slot reserves constant space (flex + visibility, not display)
* - no auto margins redistribute free space between bar items
* - the publish handler locks the button width and restores its label
* - save refreshes the optimistic-lock fingerprint (MITHOME-68)
*/
const assert = require('assert/strict');
const fs = require('fs');
const path = require('path');
const pages = fs.readFileSync(path.join(__dirname, '../scripts/cms-pages.js'), 'utf8');
const client = fs.readFileSync(path.join(__dirname, '../scripts/cms-editor-client.js'), 'utf8');
const statusRule = pages.match(/\.save-status \{[^}]*\}/)[0];
assert.match(statusRule, /flex: 1 1 0/, 'status slot must reserve constant space');
assert.match(statusRule, /visibility: hidden/, 'status must hide via visibility (keeps layout slot)');
assert.doesNotMatch(statusRule, /display: none/, 'display:none would collapse the slot and shift items');
const previewRule = pages.match(/\.preview-link \{[^}]*\}/)[0];
assert.doesNotMatch(previewRule, /margin-left: auto/, 'auto margins redistribute space on width changes');
const logoutRule = pages.match(/\.btn-logout \{[^}]*\}/)[0];
assert.doesNotMatch(logoutRule, /margin-left: auto/, 'auto margins redistribute space on width changes');
assert.match(client, /btn\.style\.minWidth = btn\.offsetWidth \+ 'px'/, 'publish must lock the button width');
assert.match(client, /const originalLabel = btn\.textContent/, 'publish must restore the env-specific label');
assert.match(client, /if \(json\.contentHash\) CONTENT_HASH = json\.contentHash/, 'save must refresh the lock fingerprint');
console.log('Content Editor bottom bar layout guard: OK');