feat(settings): add Codex link controls and authenticated phone bridge

This commit is contained in:
yilsem committed 2026-10-09 11:55:16 +03:00
1 parent 1acb5dd90f
commit 55a1beaf9d
22 files changed
+2857 -3

No files matched your search

@@ -0,0 +1,55 @@
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)
}