mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
test(web): scope the aria age normalizer to the region that needs it
Collapsing every relative-time bucket to `{{age}}` reached the session-tree
goldens, where a literal age is the assertion: a fresh row reads `now` and an
older one does not. Six e2e files failed, two of them by aborting mid-scenario
and leaving their replay fixtures half-consumed.
`captureStableAria` now takes the rule as an opt-in, and only the reference
menu — whose rows are dated from the live Host list — asks for it.
Refs #3154
This commit is contained in:
@@ -147,7 +147,11 @@ describe.skipIf(MODE === 'record')('web e2e: file and session references through
|
||||
|
||||
await input.fill('@')
|
||||
await expect.poll(() => menu.getByRole('option').count(), { timeout: 15_000 }).toBeGreaterThanOrEqual(2)
|
||||
const snapshot = await captureStableAria(page, '[role="listbox"]', scaffold.workspaceCwd)
|
||||
// Session rows are dated from the live Host list, so their age bucket
|
||||
// advances while the suite runs.
|
||||
const snapshot = await captureStableAria(
|
||||
page, '[role="listbox"]', scaffold.workspaceCwd, { normalizeAge: true },
|
||||
)
|
||||
await compareOrRefreshGolden(MENU_EXPECTED, snapshot, MODE)
|
||||
expect(snapshot).toContain('Files & folders')
|
||||
expect(snapshot).toContain('Sessions')
|
||||
|
||||
+25
-13
@@ -1094,22 +1094,26 @@ async function persistSeedSession(
|
||||
* on one machine (measured 69 → 70 tok/s) and swings wildly on a fast replay
|
||||
* (26333 tok/s for a 3 ms stream).
|
||||
*/
|
||||
function normalizeAria(snapshot: string, workspaceCwd: string): string {
|
||||
/**
|
||||
* Relative-time buckets rendered by a dated row, in both dictionaries.
|
||||
*
|
||||
* Opt-in per capture: a session-tree golden asserts its own literal age (a
|
||||
* fresh row reads `now`, an older one does not), so collapsing the vocabulary
|
||||
* everywhere would delete that assertion. A region whose rows are dated from
|
||||
* live wall-clock state asks for it instead. Anchored on an aria label's
|
||||
* closing quote, where the bucket is always last.
|
||||
*/
|
||||
const ARIA_AGE =
|
||||
/(?:now|\d+min|\d+h|\d+d|\d+mo|\d+y|刚刚|\d+分钟|\d+小时|\d+天|\d+个月|\d+年)(?=")/g
|
||||
|
||||
function normalizeAria(snapshot: string, workspaceCwd: string, age: boolean): string {
|
||||
// The session heading renders the workspace's basename, not the full
|
||||
// path, so both spellings must collapse to the token.
|
||||
const base = workspaceCwd.split('/').pop()!
|
||||
return snapshot
|
||||
return (age ? snapshot.replace(ARIA_AGE, '{{age}}') : snapshot)
|
||||
.split(workspaceCwd).join('{{cwd}}')
|
||||
.split(base).join('{{workspace}}')
|
||||
.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '{{uuid}}')
|
||||
// Rows dating a session render the shared relative-time bucket, which
|
||||
// advances while the suite runs. Anchored on an aria label's closing
|
||||
// quote, where the bucket is always last, and applied before the duration
|
||||
// rules so the whole vocabulary collapses to one token.
|
||||
.replace(
|
||||
/(?:now|\d+min|\d+h|\d+d|\d+mo|\d+y|刚刚|\d+分钟|\d+小时|\d+天|\d+个月|\d+年)(?=")/g,
|
||||
'{{age}}',
|
||||
)
|
||||
// The optional space in `\d+m ?\d+s` covers both minute spellings: the
|
||||
// stats line's compact `2m42s` and the message-chrome template's `2m 42s`.
|
||||
.replace(
|
||||
@@ -1141,13 +1145,21 @@ function normalizeAria(snapshot: string, workspaceCwd: string): string {
|
||||
* @param page - the page under test.
|
||||
* @param selector - the region locator selector.
|
||||
* @param workspaceCwd - normalization input.
|
||||
* @param options - `normalizeAge` collapses relative-time buckets to `{{age}}`
|
||||
* for a region whose rows are dated from live wall-clock state.
|
||||
* @returns the stable normalized snapshot.
|
||||
*/
|
||||
export async function captureStableAria(page: Page, selector: string, workspaceCwd: string): Promise<string> {
|
||||
export async function captureStableAria(
|
||||
page: Page,
|
||||
selector: string,
|
||||
workspaceCwd: string,
|
||||
options: { normalizeAge?: boolean } = {},
|
||||
): Promise<string> {
|
||||
const region = page.locator(selector).first()
|
||||
let previous = normalizeAria(await region.ariaSnapshot(), workspaceCwd)
|
||||
const age = options.normalizeAge === true
|
||||
let previous = normalizeAria(await region.ariaSnapshot(), workspaceCwd, age)
|
||||
await expect.poll(async () => {
|
||||
const current = normalizeAria(await region.ariaSnapshot(), workspaceCwd)
|
||||
const current = normalizeAria(await region.ariaSnapshot(), workspaceCwd, age)
|
||||
const stable = current === previous
|
||||
previous = current
|
||||
return stable
|
||||
|
||||
Reference in New Issue
Block a user