Files
aiturk-hermes-ide/apps/desktop/scripts/check-codex-link-layout.mjs
T

56 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}/visual-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}/visual-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)
}