test(sw): align legacy storybook suites and add header composition fixture

- dropdown-consolidation, storybook-cleanup-stage1, detail-buttons, property-panel-comparison: assert their recorded
  state and accept today only the approved later Story changes (storybook-inventory.mjs helpers).
- header-composition.browser.mjs + fixtures/header-composition.tsx: the removed Composition Story presets, hidden
  controls, invalid menuOrder / hiddenControls and live changes, on a test-only page using the public API only.
- storybook-unused-removal: header comment lists which older scripts run on current Stories again.
This commit is contained in:
shkim4 committed 2026-10-21 06:08:23 +09:00
1 parent 1e05eaf1de
commit b50e95c325
8 files changed
+375 -66

No files matched your search

@@ -1,9 +1,12 @@
// Historical since 2026-10-19: opens SW Story IDs retired by the unused demo removal (property-panel and four others in verify). Kept as evidence
// for its recorded run; current regression: storybook-unused-removal.browser.mjs.
// 2026-10-20 (test alignment): `verify` is a current regression again. The preservation checks of the Stories retired by
// the unused demo removal (5faa1f1) run on current public Stories (Overview for the Header-connected panel; every other
// current SW/Header Story renders), and the inventory accepts only the approved changes in storybook-inventory.mjs.
// `before` stays the recorded capture of the five retired property panel Stories (historical; needs a build before c8e5fbe).
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { execFileSync } from 'node:child_process'
import path from 'node:path'
import http from 'node:http'
import { swStoryEntries, retiredPropertyPanelIds } from './storybook-inventory.mjs'
import { swStoryEntries, retiredPropertyPanelIds, retiredUnusedDemoIds, approvedAddedStoryIds, headerInventoryIssues } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
// Property panel comparison consolidation (2026-10-19).
@@ -62,8 +65,16 @@ try {
const before = JSON.parse(await readFile(path.resolve(process.env.SW_BEFORE_INVENTORY ?? 'docs/sw/property-panel-comparison-qa/before/story-inventory-before.json'), 'utf8'))
const expected = before.sw.filter(e => !retiredPropertyPanelIds.includes(e.id))
const signature = list => JSON.stringify(list.map(e => [e.id, e.name, e.title, e.tags]).sort((a, b) => a[0].localeCompare(b[0])))
check('inventory: 24 -> 19 SW Stories, 343 -> 338 total, only 5 approved retirements', before.sw.length === 24 && sw.length === 19 && before.total === 343 && stories.length === 338 && retiredPropertyPanelIds.every(id => !index.entries[id]), { before: [before.total, before.sw.length], after: [stories.length, sw.length] })
check('inventory: retained SW Story IDs, names, titles, tags unchanged', signature(expected) === signature(sw), { retained: sw.length })
// 2026-10-20 (test alignment): 24 -> 19 / 343 -> 338 is asserted on the run recorded at c8e5fbe (read from Git); today
// the index may differ from it only by the approved changes of storybook-inventory.mjs (nine unused-demo removals, the
// approved additions, the verification tags and the Popup move).
const recorded = JSON.parse(execFileSync('git', ['show', 'c8e5fbeebc26fba92998fc5ddcd28c6c110e452d:docs/sw/property-panel-comparison-qa/verify/result.json'], { encoding: 'utf8', maxBuffer: 1 << 26 })).data.inventory
const now = headerInventoryIssues(before.sw, index)
report.data.inventory.recorded = { total: recorded.total, sw: recorded.sw }
check('inventory: 24 -> 19 SW Stories, 343 -> 338 total, only 5 approved retirements (recorded at c8e5fbe); now only approved later changes', before.sw.length === 24 && recorded.sw === 19 && before.total === 343 && recorded.total === 338 &&
JSON.stringify(recorded.ids.map(([id]) => id).sort()) === JSON.stringify(expected.map(e => e.id).sort()) && retiredPropertyPanelIds.every(id => !index.entries[id]) &&
stories.length === 338 - retiredUnusedDemoIds.length + approvedAddedStoryIds.length && now.unexpected.length === 0 && now.missing.length === 0 && now.retiredPresent.length === 0, { before: [before.total, before.sw.length], recorded: [recorded.total, recorded.sw], after: [stories.length, sw.length], ...now })
check('inventory: retained SW Story IDs, names, titles, tags unchanged (recorded at c8e5fbe); now only the approved tags and Popup move', JSON.stringify(recorded.ids) === JSON.stringify(expected.map(e => [e.id, e.name])) && now.changed.length === 0, { retained: sw.length, changed: now.changed })
check('inventory: compare Story keeps its ID and name', index.entries['sw-header--property-panel-compare']?.name === 'Property Panel · 4개 비교')
check('inventory: Dropdown Story keeps ID / name / title', index.entries['sw-header--composed-controls']?.name === 'Dropdown' && index.entries['sw-header--composed-controls']?.title === 'SW/Header')
@@ -181,12 +192,14 @@ try {
check('Dropdown Story renders composed controls', await page.locator('.sw-composed-controls').count() > 0)
await goto('window-move-motion')
check('Window Move Motion Story renders', await page.locator('[data-sw-window-move]').count() > 0)
await goto('property-panel')
// 2026-10-20: the Property Panel page was removed (5faa1f1); the Header-connected panel is the one of Overview.
await goto('overview')
const trigger = page.locator('.hm-sw-header [data-property-panel-trigger]')
await trigger.click(); const opened = await page.locator('.hm-sw-property').count()
await page.keyboard.press('Escape'); await page.keyboard.press('Escape')
check('Property Panel (Header-connected) still opens; Escape closes', opened === 1 && await page.locator('.hm-sw-property').count() === 0, { opened })
for (const id of ['property-shape-slot', 'property-fields', 'property-bar', 'layer-detail-input', 'k-guide']) {
check('Property Panel (Header-connected, Overview) still opens; Escape closes', opened === 1 && await page.locator('.hm-sw-property').count() === 0, { opened })
// Every other current SW/Header Story renders (the original list named the then-retained Stories; four were removed in 5faa1f1).
for (const id of sw.map(e => e.id.replace('sw-header--', '')).filter(id => !['overview', 'composed-controls', 'window-move-motion'].includes(id))) {
await goto(id); check(`render ${id}`, !(await page.locator('.sb-errordisplay').isVisible()))
}
check('no browser console or page errors', report.errors.length === 0, report.errors)