56 lines
3.7 KiB
JavaScript
56 lines
3.7 KiB
JavaScript
import { spawn } from 'node:child_process'
|
||
import { mkdir, writeFile } from 'node:fs/promises'
|
||
import path from 'node:path'
|
||
import { fileURLToPath } from 'node:url'
|
||
import { chromium } from '@playwright/test'
|
||
|
||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||
const output = process.argv[2]
|
||
if (!output || !path.isAbsolute(output)) throw new Error('An absolute evidence output directory is required')
|
||
await mkdir(output, { recursive: true })
|
||
const port = 5178
|
||
const server = spawn(process.execPath, [path.resolve(root, '../../node_modules/vite/bin/vite.js'), '--host', '127.0.0.1', '--port', String(port), '--strictPort'], { cwd: root, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] })
|
||
let log = ''
|
||
const capture = chunk => { log = (log + String(chunk)).slice(-12000) }
|
||
server.stdout.on('data', capture); server.stderr.on('data', capture)
|
||
let browser
|
||
try {
|
||
let ready = false
|
||
for (let i = 0; i < 100; i++) {
|
||
if (server.exitCode !== null) throw new Error('Preview server exited: ' + log)
|
||
try { ready = (await fetch(`http://127.0.0.1:${port}/e2e/fixtures/codex-link-settings.html`)).ok } catch {}
|
||
if (ready) break
|
||
await new Promise(resolve => setTimeout(resolve, 300))
|
||
}
|
||
if (!ready) throw new Error('Preview server not ready: ' + log)
|
||
browser = await chromium.launch({ channel: 'chrome', headless: true })
|
||
const evidence = []
|
||
for (const width of [360, 390, 414, 1280]) {
|
||
const page = await browser.newPage({ viewport: { width, height: 900 }, reducedMotion: 'reduce' })
|
||
const errors = []
|
||
page.on('pageerror', error => errors.push(error.message))
|
||
await page.goto(`http://127.0.0.1:${port}/e2e/fixtures/codex-link-settings.html`, { waitUntil: 'domcontentloaded', timeout: 90000 })
|
||
await page.getByText('Proje sohbeti · örnek kayıt').waitFor({ timeout: 90000 })
|
||
await page.evaluate(() => document.fonts.ready)
|
||
const layout = await page.evaluate(() => ({ width: innerWidth, scroll: document.documentElement.scrollWidth, buttons: [...document.querySelectorAll('button:not([role=switch]), input, select, label[for="codex-link-enabled"], label[for="codex-link-compression"]')].map(element => ({ text: element.textContent || element.id, height: element.getBoundingClientRect().height })) }))
|
||
if (layout.scroll > width) throw new Error(`Horizontal overflow at ${width}: ${layout.scroll}`)
|
||
await writeFile(path.join(output, `layout-${width}.json`), JSON.stringify(layout, null, 2) + '\n')
|
||
await page.screenshot({ path: path.join(output, `codex-link-${width}.png`), fullPage: true })
|
||
if (layout.buttons.some(button => button.height < 43.5)) throw new Error(`Small touch target at ${width}: ${JSON.stringify(layout.buttons.filter(button => button.height < 43.5))}`)
|
||
if (errors.length) throw new Error(errors.join('\n'))
|
||
// Tap the label as a finger would, then verify the manager-confirmed value.
|
||
await page.locator('label[for="codex-link-enabled"]').click()
|
||
await page.waitForFunction(() => document.querySelector('#codex-link-enabled')?.getAttribute('aria-checked') === 'false')
|
||
await page.getByRole('button', { name: 'Şimdi sıkıştır' }).scrollIntoViewIfNeeded()
|
||
await page.screenshot({ path: path.join(output, `codex-link-${width}-history.png`), fullPage: true })
|
||
evidence.push({ width, horizontal_overflow: false, touch_targets_passed: true, preference_update_passed: true, errors })
|
||
await page.close()
|
||
}
|
||
await writeFile(path.join(output, 'layout-result.json'), JSON.stringify({ synthetic_fixture: true, real_manager: false, checks: evidence }, null, 2) + '\n')
|
||
console.log(JSON.stringify({ passed: evidence.length, output }))
|
||
} finally {
|
||
await browser?.close()
|
||
server.kill()
|
||
await writeFile(path.join(output, 'preview-server.log'), log)
|
||
}
|