完整关口收尾:端点认证头重名只标后加的那一行(原有的那行本身没错);check-apps 实例状态只认状态标签本身(标签里嵌着带 data-status 的图标);check-app-editor 选人输入框挂了候选列表,角色是 combobox,按输入框定位

This commit is contained in:
ThearchyHelios
2026-10-15 07:27:57 +08:00
parent 941723b17c
commit 77cd95901a
3 changed files with 8 additions and 6 deletions
+5 -4
View File
@@ -30,10 +30,11 @@ const rowsOf = (env?: EndpointEnv): HeaderRow[] => Object.entries(env?.headers ?
/** 请求头名称:HTTP 的 token(和服务端 capabilities/secrets.header_problem 同一条规矩,服务端为准) */
const HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
function headerProblem(row: HeaderRow, rows: HeaderRow[]): string | null {
/** 一行认证头的问题。重名只标后来的那一行:前面那一行本身没错,删掉或改掉后加的就好 */
function headerProblem(row: HeaderRow, rows: HeaderRow[], index: number): string | null {
if (!row.k.trim()) return T.headerEmpty
if (!HEADER_NAME.test(row.k)) return T.headerInvalid
if (rows.filter((r) => r.k.toLowerCase() === row.k.toLowerCase()).length > 1) return T.headerDuplicate
if (rows.slice(0, index).some((r) => r.k.toLowerCase() === row.k.toLowerCase())) return T.headerDuplicate
return null
}
@@ -168,7 +169,7 @@ function EndpointEditor({ row, onClose, onSaved, onConflict }: {
const [timeout, setTimeoutS] = useState(row?.timeout_s ?? 20)
const [busy, setBusy] = useState(false)
// 配了的环境里有标红的请求头(名称空、不合法、重复):不让保存
const headerBlocked = ENVS.some((env) => envs[env] && headers[env].some((r) => headerProblem(r, headers[env])))
const headerBlocked = ENVS.some((env) => envs[env] && headers[env].some((r, i) => headerProblem(r, headers[env], i)))
const idemProblem = HEADER_NAME.test(idem) ? null : T.headerInvalid
const setEnv = (env: EnvKey, patch: Partial<EndpointEnv> | null) =>
setEnvs((cur) => {
@@ -259,7 +260,7 @@ function EnvEditor({ env, value, onChange, headers, onHeaders }: {
<div>
<div className="mb-1 text-2xs text-faint">{T.headers} · {T.headersHint}</div>
{headers.map((r, i) => {
const problem = headerProblem(r, headers)
const problem = headerProblem(r, headers, i)
const errorId = `endpoint-${env}-header-${i}-error`
return (
<div key={i} className="mb-1" data-endpoint-header={i}>
+2 -1
View File
@@ -585,7 +585,8 @@ await section('岗位与授权:三档各写标题和说明;搭建者从名
&& (await rows.nth(1).innerText()).includes('全部实例') && (await rows.nth(2).innerText()).includes('编辑、发布'))
const use = rows.first()
check('已选的名录里没有:标签上标出来', await waitFor(page, async () => await use.locator('[data-principal-problem="missing"]').count() === 1))
const input = use.getByRole('textbox')
// 挂了候选列表(list)的输入框角色是 combobox,不是 textbox
const input = use.locator('input').first()
const chips = () => use.locator('li[data-principal]').count()
await input.fill('nobody')
await input.press('Enter')
+1 -1
View File
@@ -468,7 +468,7 @@ await section('实例页:状态、进度、待办卡、动作状态', async ()
await page.locator('[data-view-renderer]').waitFor({ timeout: 15000 })
check('写出发起人', (await page.locator('[data-instance-page]').innerText()).includes('由「张三」发起'))
check('实例状态按服务端的说法写(结果未知:等待核实写入结果,不是「等待审批」)',
(await page.locator('[data-component="instance_header"] [data-status]').innerText()).includes('等待核实写入结果')
(await page.locator('[data-component="instance_header"] span[data-status]').first().innerText()).includes('等待核实写入结果')
&& !(await page.locator('[data-component="instance_header"]').innerText()).includes('等待审批'))
check('进度按节点列出', (await page.locator('[data-timeline-step]').count()) === 3)
check('结果未知的那一步写「结果未知」,不写「完成」',