Files
ycode/scripts/task-popconfirm-browser-fixture.tsx
T

63 lines
4.8 KiB
TypeScript

/** Real Chromium fixture, isolated callbacks only: no IPC, sessions, models, or original app. */
import React from 'react'
import { createRoot } from 'react-dom/client'
import { flushSync } from 'react-dom'
import '../src/renderer/src/workbuddy/typography/tokens.css'
import '../src/renderer/src/styles/tokens.css'
import '../src/renderer/src/ui/tokens.css'
import '../src/renderer/src/styles/app.css'
import '../src/renderer/src/styles/sidebar.css'
import '../src/renderer/src/workbuddy/conversation/source-styles.css'
import '../src/renderer/src/workbuddy/conversation/source-adapters.css'
import '../src/renderer/src/components/workspace-source.css'
import '../src/renderer/src/components/source-select/source-select-recovered.css'
import '../src/renderer/src/components/source-select/source-select.css'
import { TaskPopconfirm } from '../src/renderer/src/components/TaskPopconfirm'
const root = createRoot(document.getElementById('root')!)
const anchor = document.getElementById('anchor')!
const results: unknown[] = []
const pause = () => new Promise(resolve => setTimeout(resolve, 200))
function check(actual: unknown, expected: unknown, label: string) {
results.push({label, actual, expected})
if (JSON.stringify(actual) !== JSON.stringify(expected)) throw Error(label + ': ' + JSON.stringify(actual))
}
const button = (name: string) => document.querySelector<HTMLButtonElement>('.task-popconfirm__' + name)!
async function run() {
for (const theme of ['light', 'dark']) for (const kind of ['archive', 'delete'] as const) for (const running of (kind === 'delete' ? [false, true] : [false])) {
document.documentElement.dataset.theme = theme
let calls = 0, closes = 0, resolve!: () => void, reject!: (cause: Error) => void
const close = () => { closes++; flushSync(() => root.render(null)) }
flushSync(() => root.render(<TaskPopconfirm kind={kind} running={running} anchor={anchor} onClose={close} onConfirm={() => { calls++; return new Promise<void>((yes, no) => { resolve = yes; reject = no }) }} />))
await pause()
const label = `${theme}/${kind}/${running}`
const dark = theme === 'dark'
const confirm = button('confirm'), cancel = button('cancel')
for (const node of [confirm, cancel]) {
const s = getComputedStyle(node)
check([s.minWidth, s.paddingLeft, s.paddingRight, s.height, s.borderRadius, s.fontSize], ['66px', '19px', '19px', '28px', '6px', '12px'], label + ' geometry')
}
const primary = getComputedStyle(confirm), secondary = getComputedStyle(cancel)
check([primary.backgroundColor, primary.color], kind === 'delete' ? [dark ? 'rgb(175, 25, 26)' : 'rgb(232, 92, 92)', 'rgb(255, 255, 255)'] : dark ? ['rgba(255, 255, 255, 0.9)', 'rgba(0, 0, 0, 0.9)'] : ['rgba(0, 0, 0, 0.9)', 'rgb(255, 255, 255)'], label + ' primary/danger colors')
check([secondary.backgroundColor, secondary.borderTopWidth, secondary.borderTopStyle, secondary.borderTopColor], [dark ? 'rgb(38, 38, 38)' : 'rgb(255, 255, 255)', '1px', 'solid', dark ? 'rgb(61, 61, 61)' : 'rgb(222, 222, 222)'], label + ' secondary colors/border')
const popup = document.querySelector<HTMLElement>('.task-popconfirm')!
check([getComputedStyle(popup).width, getComputedStyle(popup).borderRadius, getComputedStyle(document.querySelector('.task-popconfirm__title')!).fontWeight], ['240px', '16px', '600'], label + ' shell')
check(getComputedStyle(popup).backgroundColor, dark ? 'rgb(36, 36, 36)' : 'rgb(255, 255, 255)', label + ' shell background')
check(document.activeElement === confirm, true, label + ' initial focus')
if (running) check(confirm.textContent, '停止并删除', label + ' running delete semantic')
confirm.click(); confirm.click(); await pause()
check([calls, confirm.disabled, cancel.disabled, confirm.textContent], [1, true, true, '处理中…'], label + ' busy prevents duplicates')
document.dispatchEvent(new KeyboardEvent('keydown', {key:'Escape', bubbles:true})); cancel.click()
check(closes, 0, label + ' busy cannot dismiss')
if (kind === 'delete') check(getComputedStyle(confirm).backgroundColor, dark ? 'rgb(128, 56, 56)' : 'rgb(245, 185, 185)', label + ' danger busy background')
reject(new Error('fixture failure')); await pause()
check(document.querySelector('[role="alert"]')?.textContent, 'fixture failure', label + ' failure retained')
check(confirm.disabled, false, label + ' retry enabled')
confirm.click(); await pause(); resolve(); await pause()
check([calls, closes, !!document.querySelector('.task-popconfirm')], [2, 1, false], label + ' retry success')
}
}
run().then(() => finish(true), error => finish(false, String(error)))
function finish(pass: boolean, error?: string) {
const output = document.createElement('pre'); output.id = 'result'; output.textContent = JSON.stringify({pass, error, results}); document.body.append(output)
}