test(sw): align theme and consumer tests with the Dotum default
- theme-inheritance: default = Dotum stack, inheritance verification value = Noto Sans KR (same 23 checks). - SW/Theme Story: verification font and labels follow the new default. - ai-template-consumer: SWTheme token font now starts with Dotum. - footer-design-review (new): Footer design items (전체보기 / + hover, Model selected / unselected, category pockets, Model / Layout text) measured in Storybook with state screenshots.
This commit is contained in:
1 parent
633ea61c32
commit
d818d0308e
4 files changed
+166
-27
No files matched your search
@@ -1,7 +1,7 @@
|
||||
// SW theme token inheritance (2026-10-20, A-1).
|
||||
// 1) SW/Theme › Theme Inheritance: a token set through `style` on the outermost SW scope reaches the header, dropdowns,
|
||||
// More, panels, footer command line and tooltips; portals get it only when wrapped in a themed <SWTheme>; areas do
|
||||
// not mix; unthemed components keep Noto Sans KR. Dotum is a verification value only (not the SW default).
|
||||
// not mix; unthemed components keep the SW default Dotum (2026-10-20). Noto Sans KR is a verification value only.
|
||||
// 2) Regression: every existing SW Story renders identically with the new cascade and with the legacy cascade
|
||||
// (token blocks re-declared on every `.hm-sw-header, .hm-sw-theme`, i.e. the code before this change): computed
|
||||
// font / color / geometry of every SW element and an element screenshot comparison. No Story sets an override,
|
||||
@@ -22,9 +22,9 @@ const [storybook = 'http://127.0.0.1:6024', outArg] = process.argv.slice(2)
|
||||
const out = path.resolve(outArg ?? 'docs/sw/theme-inheritance-qa')
|
||||
await mkdir(out, { recursive: true })
|
||||
|
||||
const VERIFY = 'Dotum, 돋움, sans-serif'
|
||||
const VERIFY = '"Noto Sans KR", sans-serif'
|
||||
const NESTED = '"Malgun Gothic", sans-serif'
|
||||
const DEFAULT = '"Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif'
|
||||
const DEFAULT = 'Dotum, 돋움, "Malgun Gothic", "Apple SD Gothic Neo", sans-serif'
|
||||
const results = []
|
||||
const check = (name, pass, detail = '') => { results.push({ name, result: pass ? 'PASS' : 'FAIL', detail }); console.log(`${pass ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`) }
|
||||
const errors = []
|
||||
@@ -67,52 +67,52 @@ const fmt = map => Object.entries(map).map(([family, count]) => `${count}× ${fa
|
||||
|
||||
// Default (no theme): header, then its sample dropdown and More.
|
||||
const def = scope('default')
|
||||
check('기본: 단독 SWViewerHeader = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-header`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-header`)))
|
||||
check('기본: 단독 SWViewerHeader = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-header`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-header`)))
|
||||
await page.locator(`${def} .hm-sw-viewer-header [aria-haspopup="menu"]`).first().click()
|
||||
await page.waitForSelector(`${def} .hm-sw-viewer-menu`)
|
||||
check('기본: Dropdown = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
|
||||
check('기본: Dropdown = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
|
||||
await page.keyboard.press('Escape')
|
||||
await page.locator(`${def} .hm-sw-viewer-header button[aria-label="추가 도구"]`).click()
|
||||
await page.waitForSelector(`${def} .hm-sw-viewer-menu[data-surface="beige"]`)
|
||||
check('기본: More = Noto Sans KR', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
|
||||
check('기본: More = 기본 Dotum', only(await fonts(page, `${def} .hm-sw-viewer-menu`), DEFAULT), fmt(await fonts(page, `${def} .hm-sw-viewer-menu`)))
|
||||
await page.keyboard.press('Escape')
|
||||
|
||||
// Viewer, themed through <SWTheme style>.
|
||||
const viewer = scope('viewer-themed')
|
||||
check('뷰어 테마: SWViewerHeader 전체 = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-header`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-header`)))
|
||||
check('뷰어 테마: SWViewerHeader 전체 = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-header`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-header`)))
|
||||
await page.locator(`${viewer} .hm-sw-viewer-header [aria-haspopup="menu"]`).first().click()
|
||||
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu`)
|
||||
check('뷰어 테마: Dropdown = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
check('뷰어 테마: Dropdown = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
await page.keyboard.press('Escape')
|
||||
await page.locator(`${viewer} .hm-sw-viewer-header button[aria-label="추가 도구"]`).click()
|
||||
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu[data-surface="beige"]`)
|
||||
check('뷰어 테마: More = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
check('뷰어 테마: More = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
// A submenu of More, if any, is a nested menu inside a nested menu.
|
||||
const sub = page.locator(`${viewer} .hm-sw-viewer-menu[data-surface="beige"] [aria-haspopup="menu"]`).first()
|
||||
if (await sub.count()) {
|
||||
await sub.hover()
|
||||
await page.waitForTimeout(150)
|
||||
check('뷰어 테마: More 서브메뉴 = Dotum', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
check('뷰어 테마: More 서브메뉴 = 검증 글꼴', only(await fonts(page, `${viewer} .hm-sw-viewer-menu`), VERIFY), fmt(await fonts(page, `${viewer} .hm-sw-viewer-menu`)))
|
||||
}
|
||||
await page.keyboard.press('Escape')
|
||||
const panels = await page.locator(`${viewer} .hm-sw-viewer-panel`).count()
|
||||
check('뷰어 테마: SWViewerPanel(제목·입력·버튼·스위치·힌트) = Dotum', panels === 2 && only(await fonts(page, `${viewer} .hm-sw-viewer-panel`), VERIFY), `${panels} panels · ${fmt(await fonts(page, `${viewer} .hm-sw-viewer-panel`))}`)
|
||||
check('뷰어 테마: SWViewerPanel(제목·입력·버튼·스위치·힌트) = 검증 글꼴', panels === 2 && only(await fonts(page, `${viewer} .hm-sw-viewer-panel`), VERIFY), `${panels} panels · ${fmt(await fonts(page, `${viewer} .hm-sw-viewer-panel`))}`)
|
||||
await page.screenshot({ path: path.join(out, 'viewer-themed-more.png'), clip: await page.locator(viewer).boundingBox() })
|
||||
|
||||
// General mode: SWHeader (+ open layer dropdown, window-move tooltip), SWFooter (+ command line, guide tooltip).
|
||||
const general = scope('general-themed')
|
||||
const headerFonts = await fonts(page, `${general} .hm-sw-header`, '.hm-sw-header__motion-tooltip')
|
||||
check('일반 테마: SWHeader + 열린 레이어 Dropdown = Dotum (창 이동 Tooltip 별도)', only(headerFonts, VERIFY), fmt(headerFonts))
|
||||
check('일반 테마: SWHeader + 열린 레이어 Dropdown = 검증 글꼴 (창 이동 Tooltip 별도)', only(headerFonts, VERIFY), fmt(headerFonts))
|
||||
const tooltip = await page.locator(`${general} .hm-sw-header__motion-tooltip`).evaluate(element => getComputedStyle(element).fontFamily)
|
||||
check('일반 테마: 창 이동 Tooltip = Inter → 테마 글꼴', tooltip === `Inter, ${VERIFY}`, tooltip)
|
||||
const layerMenu = await page.locator(`${general} .hm-sw-header`).getByText('A-WALL').count()
|
||||
check('일반 테마: 레이어 Dropdown이 열린 상태(목록 행 A-WALL 표시)', layerMenu > 0, `${layerMenu} row`)
|
||||
check('일반 테마: SWFooter = Dotum', only(await fonts(page, `${general} .hm-sw-footer`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer`)))
|
||||
check('일반 테마: 명령창(SWFooterCommandLine, 중첩 hm-sw-theme) = Dotum', only(await fonts(page, `${general} .hm-sw-footer-command`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer-command`)))
|
||||
check('일반 테마: SWFooter = 검증 글꼴', only(await fonts(page, `${general} .hm-sw-footer`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer`)))
|
||||
check('일반 테마: 명령창(SWFooterCommandLine, 중첩 hm-sw-theme) = 검증 글꼴', only(await fonts(page, `${general} .hm-sw-footer-command`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer-command`)))
|
||||
await page.locator(`${general} .hm-sw-footer-add`).first().focus()
|
||||
await page.waitForTimeout(150)
|
||||
const guide = page.locator(`${general} .hm-sw-footer [role="tooltip"]`)
|
||||
check('일반 테마: 명령 등록 안내(Tooltip) = Dotum', (await guide.count()) > 0 && only(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`)))
|
||||
check('일반 테마: 명령 등록 안내(Tooltip) = 검증 글꼴', (await guide.count()) > 0 && only(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`), VERIFY), fmt(await fonts(page, `${general} .hm-sw-footer [role="tooltip"]`)))
|
||||
|
||||
// Portals.
|
||||
const [plain, themed, insideSource] = await page.evaluate(() => {
|
||||
@@ -122,15 +122,15 @@ const fmt = map => Object.entries(map).map(([family, count]) => `${count}× ${fa
|
||||
!!document.querySelector('[data-theme-case="portal-source"] [data-portal]')]
|
||||
})
|
||||
check('Portal: DOM이 테마 영역 밖에 렌더링됨', !insideSource)
|
||||
check('Portal: SWTheme만 감싸면 기본 글꼴(테마 미전달)', plain.startsWith('"Noto Sans KR"'), plain)
|
||||
check('Portal: SWTheme만 감싸면 기본 글꼴(테마 미전달)', plain === DEFAULT, plain)
|
||||
check('Portal: 같은 theme style의 SWTheme으로 감싸면 테마 적용', themed === VERIFY, themed)
|
||||
|
||||
// Areas.
|
||||
const area = name => fonts(page, `${scope(name)} .hm-sw-viewer-hint`)
|
||||
check('영역 A(Dotum)', only(await area('area-a'), VERIFY), fmt(await area('area-a')))
|
||||
check('영역 A(검증 글꼴)', only(await area('area-a'), VERIFY), fmt(await area('area-a')))
|
||||
check('영역 B(기본) — 옆 영역 값이 섞이지 않음', only(await area('area-b'), DEFAULT), fmt(await area('area-b')))
|
||||
const outer = await page.locator(`${scope('area-c')} > .hm-sw-viewer-hint`).evaluate(element => getComputedStyle(element).fontFamily)
|
||||
check('영역 C 바깥(Dotum)', outer === VERIFY, outer)
|
||||
check('영역 C 바깥(검증 글꼴)', outer === VERIFY, outer)
|
||||
check('영역 C 안쪽 SWTheme style(Malgun Gothic)만 안쪽에 적용', only(await area('area-c-nested'), NESTED), fmt(await area('area-c-nested')))
|
||||
await page.screenshot({ path: path.join(out, 'theme-inheritance-full.png'), fullPage: true })
|
||||
await page.close()
|
||||
@@ -213,7 +213,7 @@ for (const width of [1920, 1440, 1180, 900, 560]) for (const id of ids) {
|
||||
await page.waitForSelector(`${viewer} .hm-sw-viewer-menu[data-surface="beige"]`)
|
||||
const more = await fonts(page, `${viewer} .hm-sw-viewer-menu`)
|
||||
const command = await fonts(page, '[data-theme-case="general-themed"] .hm-sw-footer-command')
|
||||
check('대조: 기존 구조 주입 시 More·명령창이 Noto로 되돌아감(결함 재현)', only(more, DEFAULT) && only(command, DEFAULT), `More ${fmt(more)} · 명령창 ${fmt(command)}`)
|
||||
check('대조: 기존 구조 주입 시 More·명령창이 기본 글꼴로 되돌아감(결함 재현)', only(more, DEFAULT) && only(command, DEFAULT), `More ${fmt(more)} · 명령창 ${fmt(command)}`)
|
||||
await page.close()
|
||||
}
|
||||
const failedRegression = regression.filter(item => item.result !== 'PASS')
|
||||
|
||||
Reference in new issue
Block a user