#!/usr/bin/env node /* 三态主题专项验证:日间 / 夜间 / 自动 + iframe 同步。 */ import { readFileSync } from 'fs'; import { join } from 'path'; const ROOT = process.cwd(); const BASE = process.env.REG_BASE || 'http://127.0.0.1:3311'; let fail = 0; const ok = (condition, message) => { console.log((condition ? 'PASS' : 'FAIL') + ' ' + message); if (!condition) fail++; }; const app = readFileSync(join(ROOT, 'site/app.js'), 'utf8'); const index = readFileSync(join(ROOT, 'site/index.html'), 'utf8'); const css = readFileSync(join(ROOT, '.design_library/aurora-admin/colors_and_type.css'), 'utf8'); ok(/prefers-color-scheme/.test(app), '静态:支持 prefers-color-scheme'); ok(/localStorage\.setItem\(['"]aa-mode/.test(app), '静态:持久化 aa-mode'); ok(/data-mode="auto"/.test(index), '静态:站点包含自动模式选项'); ok(/html\.aa-dark/.test(css), '静态:暗色令牌入口存在'); let chromium; try { ({ chromium } = await import('playwright')); } catch { console.error('[FATAL] 未安装 playwright'); process.exit(2); } const browser = await chromium.launch(); try { async function siteCase(colorScheme, storedMode, expectedDark, label) { const page = await browser.newPage({ colorScheme }); await page.addInitScript((mode) => localStorage.setItem('aa-mode', mode), storedMode); await page.goto(BASE + '/site/index.html', { waitUntil: 'load', timeout: 15000 }); await page.waitForTimeout(150); const result = await page.evaluate(() => ({ dark: document.documentElement.classList.contains('aa-dark'), stored: localStorage.getItem('aa-mode'), menu: document.querySelectorAll('#mode-menu [role="radio"]').length, auto: document.querySelector('#mode-menu [data-mode="auto"]')?.getAttribute('aria-checked'), iframe: Array.from(document.querySelectorAll('iframe')).every((f) => { try { return f.contentDocument?.documentElement.classList.contains('aa-dark') === document.documentElement.classList.contains('aa-dark'); } catch { return true; } }) })); ok(result.dark === expectedDark, `${label}:aa-dark=${result.dark}`); ok(result.stored === storedMode, `${label}:aa-mode=${result.stored}`); ok(result.menu === 3 && result.auto === (storedMode === 'auto' ? 'true' : 'false'), `${label}:模式菜单 ARIA`); ok(result.iframe, `${label}:iframe 主题同步`); await page.close(); } await siteCase('light', 'auto', false, '自动 + 系统日间'); await siteCase('dark', 'auto', true, '自动 + 系统夜间'); await siteCase('dark', 'light', false, '手动日间覆盖系统夜间'); await siteCase('light', 'dark', true, '手动夜间覆盖系统日间'); const changing = await browser.newPage({ colorScheme: 'light' }); await changing.addInitScript(() => localStorage.setItem('aa-mode', 'auto')); await changing.goto(BASE + '/site/index.html', { waitUntil: 'load', timeout: 15000 }); await changing.waitForTimeout(100); await changing.emulateMedia({ colorScheme: 'dark' }); await changing.waitForTimeout(100); ok(await changing.locator('html').evaluate((el) => el.classList.contains('aa-dark')), '自动模式:系统切换到夜间即时生效'); await changing.emulateMedia({ colorScheme: 'light' }); await changing.waitForTimeout(100); ok(!(await changing.locator('html').evaluate((el) => el.classList.contains('aa-dark'))), '自动模式:系统切换到日间即时生效'); await changing.close(); const menuPage = await browser.newPage({ colorScheme: 'light' }); await menuPage.addInitScript(() => localStorage.removeItem('aa-mode')); await menuPage.goto(BASE + '/site/index.html', { waitUntil: 'load', timeout: 15000 }); await menuPage.locator('#fab-mode').click(); await menuPage.locator('#mode-menu [data-mode="dark"]').click(); ok(await menuPage.evaluate(() => localStorage.getItem('aa-mode') === 'dark' && document.documentElement.classList.contains('aa-dark')), '菜单选择夜间模式'); await menuPage.close(); const switcher = await browser.newPage({ colorScheme: 'light' }); await switcher.addInitScript(() => localStorage.removeItem('aa-mode')); await switcher.goto(BASE + '/frameworks/ThemeSwitcher.html', { waitUntil: 'load', timeout: 15000 }); const modes = await switcher.locator('.aa-themesw-opt').count(); ok(modes === 3, 'ThemeSwitcher H5:三种模式'); await switcher.locator('[data-mode="dark"]').click(); ok(await switcher.locator('html').evaluate((el) => el.classList.contains('aa-dark')), 'ThemeSwitcher H5:夜间模式生效'); await switcher.locator('[data-mode="auto"]').click(); ok(await switcher.locator('[data-mode="auto"]').getAttribute('aria-checked') === 'true', 'ThemeSwitcher H5:自动模式 ARIA'); await switcher.close(); } finally { await browser.close(); } console.log(fail ? `THEME VERIFY FAIL (${fail})` : 'THEME VERIFY OK'); process.exit(fail ? 1 : 0);