test(sw): shared Playwright runtime resolver

This commit is contained in:
shkim4 committed 2026-10-20 21:49:46 +09:00
1 parent 94c0a13c74
commit df650c02dd
23 files changed
+120 -55

No files matched your search

@@ -1,14 +1,14 @@
// Browser check of the independent consumer built by ai-template-consumer.mjs.
// Usage: node packages/sw/tests/ai-template-consumer.browser.mjs <consumer-dir> <evidence-dir>
// Serves <consumer-dir>/dist and checks examples A–D (rendering, assets, dropdowns, callbacks, focus, styles).
import { createRequire } from "node:module"
import { createServer } from "node:http"
import { mkdir, readFile, writeFile } from "node:fs/promises"
import path from "node:path"
import { loadPlaywright } from "./playwright-runtime.mjs"
const dist = path.resolve(process.argv[2], "dist")
const out = path.resolve(process.argv[3])
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? "C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright")
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const types = { ".html": "text/html", ".js": "text/javascript", ".css": "text/css" }
const server = createServer(async (request, response) => {
+2 -2
View File
@@ -1,10 +1,10 @@
// Historical since 2026-10-19: opens SW Story IDs retired by the unused demo removal (composition, colorize, layer-detail-input; preservation/verify modes). Kept as evidence
// for its recorded run; current regression: storybook-unused-removal.browser.mjs.
import { createRequire } from 'node:module'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
import { swStoryEntries, retainedInventory, retiredPropertyPanelIds } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
// Usage: node packages/sw/tests/detail-buttons.browser.mjs baseline|verify <evidence-dir> [base-url]
const mode = process.argv[2] ?? 'verify'
@@ -16,7 +16,7 @@ if (base === 'static') {
server=http.createServer(async(req,res)=>{try{const p=new URL(req.url,'http://localhost').pathname,file=path.resolve(root,'.'+decodeURIComponent(p==='/'?'/index.html':p));if(path.relative(root,file).startsWith('..'))return res.writeHead(403).end();res.setHeader('Content-Type',mime[path.extname(file)]??'application/octet-stream');res.end(await readFile(file))}catch{res.writeHead(404).end()}})
await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));base=`http://127.0.0.1:${server.address().port}`
}
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
await mkdir(output, { recursive: true })
const browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1920, height: 1000 } })
@@ -1,12 +1,12 @@
// Build Storybook first. Historical QA is preserved; use a new evidence directory for every run.
// Usage: node packages/sw/tests/dropdown-consolidation.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import { execFileSync } from 'node:child_process'
import path from 'node:path'
import http from 'node:http'
import { parse } from '@babel/parser'
import { retiredDropdownIds, swStoryEntries, retainedInventory, inventorySignature } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-dropdown-page-qa')
await mkdir(out, { recursive: true })
@@ -50,7 +50,7 @@ const server = http.createServer(async (req, res) => {
})
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
const base = `http://127.0.0.1:${server.address().port}`
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
let browser
try {
browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
+2 -2
View File
@@ -1,12 +1,12 @@
// Historical since 2026-10-19: opens SW Story IDs retired by the unused demo removal (property-bar, additional-hover). Kept as evidence
// for its recorded run; current regression: storybook-unused-removal.browser.mjs.
// Usage: node packages/sw/tests/followup-four.browser.mjs <evidence-dir> [storybook-url] (Storybook uses packages/sw/dist: build first)
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2])
const base = process.argv[3] ?? 'http://127.0.0.1:6024'
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const browser = await chromium.launch({ executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1920, height: 1000 } })
@@ -3,12 +3,11 @@
// each state; design judgement (PASS / REVIEW) is written in the report, this script only records facts and checks
// the approved, unambiguous rules.
// Usage: node packages/sw/tests/footer-design-review.browser.mjs [storybook-url] [evidence-dir]
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const { chromium } = require('playwright')
const [storybook = 'http://127.0.0.1:6024', outArg = 'docs/sw/sw-noto-bold-qa/footer-design'] = process.argv.slice(2)
const out = path.resolve(outArg); await mkdir(out, { recursive: true })
@@ -1,12 +1,11 @@
// 2026-10-20 SW Footer · Popup · Viewer refinement: Footer Story cleanup, Header field dropdowns inside SWPopup,
// SWSlider appearances (panel / property), Popup B, viewer title art at narrow widths.
// Usage: build Storybook first, then node packages/sw/tests/footer-popup-viewer-refinement.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
import { runtimeRequire } from './playwright-runtime.mjs'
const require = runtimeRequire()
const { chromium } = require('playwright')
const out = path.resolve(process.argv[2] ?? 'docs/sw/footer-popup-viewer-refinement-qa'); await mkdir(out, { recursive: true })
const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.png': 'image/png', '.ttf': 'font/ttf', '.woff2': 'font/woff2' }
@@ -1,12 +1,11 @@
// Core checks of the Task A + B integration (SWHeader homeMenu, 2026-10-19) on the built Storybook.
// Usage: node packages/sw/tests/home-menu-integration.browser.mjs <evidence-dir> (build Storybook first)
import { createRequire } from 'node:module'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const out = path.resolve(process.argv[2] ?? 'docs/sw/home-menu-integration-qa/home-menu')
await mkdir(out, { recursive: true })
const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.png': 'image/png', '.ttf': 'font/ttf', '.woff2': 'font/woff2' }
@@ -4,12 +4,11 @@
// including the ▲ panel). Also: SWHeader field values are Noto Sans KR 400 and not cut; long footer commands end in an
// ellipsis inside the unchanged 68 × 47 slot and show their full name on hover.
// Usage: build Storybook first, then node packages/sw/tests/hover-stability.browser.mjs [evidence-dir] [chromium|firefox]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
import { runtimeRequire } from './playwright-runtime.mjs'
const require = runtimeRequire()
const playwright = require('playwright')
const out = path.resolve(process.argv[2] ?? 'docs/sw/hover-stability-qa'); await mkdir(out, { recursive: true })
const engine = process.argv[3] ?? 'chromium'
@@ -1,14 +1,14 @@
// Browser check of the consumer built by integrated-consumer.mjs (2026-10-19): both stylesheet orders, examples
// E (custom popup) and F (Open + tool bar), HM UI inside an SW popup, Escape stack, computed-style identity.
// Usage: node packages/sw/tests/integrated-consumer.browser.mjs <consumer-dir> <evidence-dir>
import { createRequire } from "node:module"
import { createServer } from "node:http"
import { mkdir, readFile, writeFile } from "node:fs/promises"
import path from "node:path"
import { loadPlaywright } from "./playwright-runtime.mjs"
const dist = path.resolve(process.argv[2], "dist")
const out = path.resolve(process.argv[3])
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? "C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright")
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const types = { ".html": "text/html", ".js": "text/javascript", ".css": "text/css", ".ttf": "font/ttf" }
const server = createServer(async (request, response) => {
@@ -1,13 +1,12 @@
// Functional checks of the 2026-10-19 SW integrated improvement on the built Storybook (storybook-static).
// Usage: node packages/sw/tests/integrated-improvement.browser.mjs <evidence-dir> [section ...]
// Sections: options, tool, popup (default: all). Screenshots and result JSON go to <evidence-dir>.
import { createRequire } from 'node:module'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const out = path.resolve(process.argv[2] ?? 'docs/sw/integrated-improvement-qa/verify')
// 'tool' opens sw-tool--tool-buttons, retired 2026-10-19 (storybook-inventory retiredToolIds): historical, run it only
// by name against an old build. The default runs the sections whose Stories exist (2026-10-20).
@@ -3,13 +3,12 @@
// compare: pixel-diffs two capture directories and writes compare-result.json.
// Usage: node packages/sw/tests/integrated-visual.browser.mjs capture <dir>
// node packages/sw/tests/integrated-visual.browser.mjs compare <before-dir> <after-dir> <out-dir>
import { createRequire } from 'node:module'
import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const [mode, a, b, c] = process.argv.slice(2)
// Stories that existed before the improvement; IDs are fixed so new Stories never enter the comparison.
+2 -2
View File
@@ -1,12 +1,12 @@
// Focused Overview integration checks. Build Storybook first; historical evidence stays untouched.
// Usage: node packages/sw/tests/overview.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import { execFileSync } from 'node:child_process'
import path from 'node:path'
import http from 'node:http'
import { parse } from '@babel/parser'
import { swStoryEntries, retainedInventory, inventorySignature, retiredDropdownIds, integratedChangedFiles } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-overview-qa')
await mkdir(out, { recursive: true })
@@ -37,7 +37,7 @@ const server = http.createServer(async(req,res) => {
})
await new Promise(resolve => server.listen(0,'127.0.0.1',resolve))
const base = `http://127.0.0.1:${server.address().port}`
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
let browser, page
try {
browser = await chromium.launch({ headless:true, executablePath:process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
+76
View File
@@ -0,0 +1,76 @@
// Playwright (and the image helpers pngjs / pixelmatch) for the SW browser tests. Playwright is not a repository
// dependency, so the first location that has it is used:
// 1. SW_PLAYWRIGHT_PATH the playwright package directory (or its entry file)
// 2. SW_RUNTIME_MODULES a node_modules directory that contains playwright
// 3. HM_PLAYWRIGHT_DIR a project directory whose node_modules contains playwright (scripts/verify-quality-runtime.mjs)
// 4. this repository node_modules/playwright (npm i -D playwright, not committed)
// 5. the Codex runtime <home>/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules
// 6. global npm `npm root -g`
// A location set by an environment variable must exist: a wrong value fails instead of falling back silently.
import { createRequire } from 'node:module'
import { execFileSync } from 'node:child_process'
import { existsSync } from 'node:fs'
import os from 'node:os'
import path from 'node:path'
const nodeModulesOf = file => {
const parts = path.resolve(file).split(path.sep)
const index = parts.lastIndexOf('node_modules')
return index < 0 ? null : parts.slice(0, index + 1).join(path.sep)
}
const fromNodeModules = dir => createRequire(path.join(dir, 'index.js'))
const globalRoot = () => {
try { return execFileSync('npm', ['root', '-g'], { encoding: 'utf8', shell: process.platform === 'win32', stdio: ['ignore', 'pipe', 'ignore'] }).trim() } catch { return null }
}
function candidates() {
const list = []
const { SW_PLAYWRIGHT_PATH: entry, SW_RUNTIME_MODULES: modules, HM_PLAYWRIGHT_DIR: project } = process.env
if (entry) {
const modulesDir = nodeModulesOf(entry)
list.push({ source: `SW_PLAYWRIGHT_PATH=${entry}`, explicit: true, entry: path.resolve(entry), require: modulesDir ? fromNodeModules(modulesDir) : createRequire(import.meta.url) })
}
if (modules) list.push({ source: `SW_RUNTIME_MODULES=${modules}`, explicit: true, require: fromNodeModules(path.resolve(modules)) })
if (project) list.push({ source: `HM_PLAYWRIGHT_DIR=${project}`, explicit: true, require: createRequire(path.join(path.resolve(project), 'package.json')) })
list.push({ source: 'repository node_modules', require: createRequire(import.meta.url) })
const codex = path.join(os.homedir(), '.cache', 'codex-runtimes', 'codex-primary-runtime', 'dependencies', 'node', 'node_modules')
if (existsSync(codex)) list.push({ source: `Codex runtime ${codex}`, require: fromNodeModules(codex) })
const global = globalRoot()
if (global && existsSync(global)) list.push({ source: `global npm ${global}`, require: fromNodeModules(global) })
return list
}
let resolved
function resolve() {
if (resolved) return resolved
const tried = []
for (const candidate of candidates()) {
try {
const entry = candidate.entry ?? candidate.require.resolve('playwright')
if (candidate.entry && !existsSync(candidate.entry)) throw new Error('path does not exist')
resolved = { ...candidate, entry }
return resolved
} catch (error) {
tried.push(`${candidate.source}: ${error.message.split('\n')[0]}`)
if (candidate.explicit) break
}
}
throw new Error(`Playwright not found for the SW browser tests. Set SW_RUNTIME_MODULES to a node_modules directory that contains playwright (or SW_PLAYWRIGHT_PATH to the playwright package).\n tried:\n - ${tried.join('\n - ')}`)
}
/** The playwright module (`{ chromium, firefox, ... }`). */
export const loadPlaywright = () => resolve().require(resolve().entry)
/**
* A `require` rooted where Playwright was found, for the other runtime modules the tests use (pngjs, pixelmatch).
* `require('playwright')` through it returns the same module as `loadPlaywright()`.
*/
export function runtimeRequire() {
const { require, entry } = resolve()
const wrapped = id => (id === 'playwright' ? require(entry) : require(id))
wrapped.resolve = (id, options) => (id === 'playwright' ? entry : require.resolve(id, options))
return wrapped
}
/** Where Playwright came from (for reports). */
export const playwrightSource = () => resolve().source
+2 -2
View File
@@ -3,13 +3,13 @@
// Property panel close button (Figma 26:12366): canvas bleed, Default / Hover, close by click and Escape.
// Usage: node packages/sw/tests/property-close.browser.mjs <evidence-dir> <label> [storybook-url]
// Storybook serves packages/sw/dist: build @hm-design/sw first.
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/property-close-qa')
const label = process.argv[3] ?? 'run'
const base = process.argv[4] ?? 'http://127.0.0.1:6024'
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const browser = await chromium.launch({ executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1400, height: 1000 }, deviceScaleFactor: 4 })
@@ -4,13 +4,13 @@
// selection callbacks, keyboard, Escape, external data, Disabled / ReadOnly, and the four panel states.
// Usage: node packages/sw/tests/property-fields.browser.mjs <evidence-dir> <label> [storybook-url]
// Storybook serves packages/sw/dist: build @hm-design/sw first.
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/property-fields-qa')
const label = process.argv[3] ?? 'run'
const base = process.argv[4] ?? 'http://127.0.0.1:6024'
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const browser = await chromium.launch({ executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1400, height: 1000 }, deviceScaleFactor: 2 })
@@ -1,10 +1,10 @@
// 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.
import { createRequire } from 'node:module'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
import { swStoryEntries, retiredPropertyPanelIds } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
// Property panel comparison consolidation (2026-10-19).
// Usage: node packages/sw/tests/property-panel-comparison.browser.mjs before|verify <evidence-dir> [base-url|static]
@@ -17,7 +17,7 @@ if (base === 'static') {
server = http.createServer(async (req, res) => { try { const p = new URL(req.url, 'http://localhost').pathname, file = path.resolve(root, '.' + decodeURIComponent(p === '/' ? '/index.html' : p)); if (path.relative(root, file).startsWith('..')) return res.writeHead(403).end(); res.setHeader('Content-Type', mime[path.extname(file)] ?? 'application/octet-stream'); res.end(await readFile(file)) } catch { res.writeHead(404).end() } })
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); base = `http://127.0.0.1:${server.address().port}`
}
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
await mkdir(out, { recursive: true })
const browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } })
@@ -2,13 +2,13 @@
// for its recorded run; current regression: storybook-unused-removal.browser.mjs.
// Scoped verification for the five approved Story removals; serves the production build locally.
// Usage: node packages/sw/tests/storybook-cleanup-stage1.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import { execFileSync } from 'node:child_process'
import path from 'node:path'
import http from 'node:http'
import { parse } from '@babel/parser'
import { swStoryEntries, retiredDropdownIds, retainedInventory, inventorySignature } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-cleanup-stage1-qa')
await mkdir(out, { recursive: true })
@@ -62,7 +62,7 @@ const server = http.createServer(async (req, res) => {
})
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
const base = `http://127.0.0.1:${server.address().port}`
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
let browser
try {
browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
@@ -1,12 +1,11 @@
// 2026-10-20 SW Storybook simplification: sidebar order, hidden verification Stories, removed IDs, direct URL render of
// every SW Story and the moved Property Panel (SW/Popup, ID sw-header--property-panel-compare).
// Usage: build Storybook first, then node packages/sw/tests/storybook-simplification.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
import { runtimeRequire } from './playwright-runtime.mjs'
const require = runtimeRequire()
const { chromium } = require('playwright')
const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-simplification-qa'); await mkdir(out, { recursive: true })
const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.png': 'image/png', '.ttf': 'font/ttf', '.woff2': 'font/woff2' }
@@ -2,13 +2,13 @@
// Build Storybook first. Usage: node packages/sw/tests/storybook-unused-removal.browser.mjs [evidence-dir]
// Older scripts that open the retired IDs (detail-buttons preservation/verify, followup-four, property-close,
// property-fields, property-panel-comparison verify, storybook-cleanup-stage1) are historical evidence for their runs.
import { createRequire } from 'node:module'
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 { parse } from '@babel/parser'
import { swStoryEntries, retiredUnusedDemoIds, integratedStoryIds, integratedChangedFiles, movedToPopupIds } from './storybook-inventory.mjs'
import { loadPlaywright } from './playwright-runtime.mjs'
const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-unused-story-removal-qa/verify')
const qa = 'docs/sw/storybook-unused-story-removal-qa/before'
@@ -59,7 +59,7 @@ const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.
const server = http.createServer(async (req, res) => { try { const p = new URL(req.url, 'http://localhost').pathname, file = path.resolve(root, '.' + decodeURIComponent(p === '/' ? '/index.html' : p)); if (path.relative(root, file).startsWith('..')) return res.writeHead(403).end(); res.setHeader('Content-Type', mime[path.extname(file)] ?? 'application/octet-stream'); res.end(await readFile(file)) } catch { res.writeHead(404).end() } })
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
const base = `http://127.0.0.1:${server.address().port}`
const { chromium } = createRequire(import.meta.url)(process.env.SW_PLAYWRIGHT_PATH ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
const { chromium } = loadPlaywright()
const browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' })
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } })
report.browser = browser.version()
+2 -3
View File
@@ -3,12 +3,11 @@
// titles and category tabs (700, 전체보기 / Model · Layout / commands unchanged) · Viewer header file name, labels and
// Model / Layout tabs (700, More kept) · recent files name / path / preview title (700 + outline). Hover keeps the
// text in place. Usage: build Storybook first, then node packages/sw/tests/text-weight.browser.mjs [evidence-dir]
import { createRequire } from 'node:module'
import { readFile, writeFile, mkdir } from 'node:fs/promises'
import path from 'node:path'
import http from 'node:http'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
import { runtimeRequire } from './playwright-runtime.mjs'
const require = runtimeRequire()
const { chromium } = require('playwright')
const out = path.resolve(process.argv[2] ?? 'docs/sw/text-weight-qa'); await mkdir(out, { recursive: true })
const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.png': 'image/png', '.ttf': 'font/ttf', '.woff2': 'font/woff2' }
@@ -8,13 +8,12 @@
// so any difference would be a regression. Pixels are compared with a control shot taken after the CURRENT token
// blocks are injected once more (2026-10-20): re-declaring them alone re-rasterizes a few gradient pixels.
// Usage: node packages/sw/tests/theme-inheritance.browser.mjs <storybook-url> <out-dir>
import { createRequire } from 'node:module'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const { chromium } = require('playwright')
const { PNG } = require('pngjs')
const pixelmatch = require('pixelmatch').default ?? require('pixelmatch')
@@ -3,12 +3,11 @@
// Element mode compares every .hm-sw-header / .hm-sw-property element; the full page is reported for information
// (the 2026-10-19 follow-up changed the Story work-area background to the shared grid canvas on purpose).
// Usage: node packages/sw/tests/viewer-regression.browser.mjs <base-storybook-url> <new-storybook-url> <out-dir>
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const { chromium } = require('playwright')
const { PNG } = require('pngjs')
const pixelmatch = require('pixelmatch').default ?? require('pixelmatch')
+2 -3
View File
@@ -3,12 +3,11 @@
// 2) Runs interaction checks on the Stories (menus, keyboard, Escape, outside click, panels, More, modal).
// Usage: node packages/sw/tests/viewer.browser.mjs <storybook-url> <reference-url|-> <out-dir>
// e.g. node packages/sw/tests/viewer.browser.mjs http://127.0.0.1:6034 http://127.0.0.1:5182 docs/sw/viewer-qa
import { createRequire } from 'node:module'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { runtimeRequire } from './playwright-runtime.mjs'
const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules'
const require = createRequire(path.join(runtime, 'index.js'))
const require = runtimeRequire()
const { chromium } = require('playwright')
const [storybook, reference, outArg] = process.argv.slice(2)
const out = path.resolve(outArg ?? 'docs/sw/viewer-qa')