test(a11y): audit responsive routes and native keyboard boundaries
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# P5-15-02 — Native audit coverage checkpoint
|
||||
|
||||
This is test/evidence work only. No application, renderer, API, schema, provider, production configuration or deployment behavior changes. Source `cf847e9b256d9aec733abf3f37c42852c9dd2421`; development branch `codex/ui-redesign-phase4`.
|
||||
|
||||
## New independently runnable coverage
|
||||
|
||||
| Test file / case | Contract exercised | Evidence limitation |
|
||||
|---|---|---|
|
||||
| `responsive-accessibility-audit.spec.ts`: thirteen-area collection | Synthetic owned native SQLite/API entries, loaded content, responsive geometry, actual ARIA tree, all enabled axe rules plus explicit WCAG2.2 target-size, screenshots | Collection success is not accessibility acceptance; rule findings are retained rather than asserted away |
|
||||
| Reduced-motion mobile drawer | Keyboard opening, expected initial focus, Escape return; records active element before/after axe and optional Tab recovery | Real keyboard automation, not a human reader |
|
||||
| Command/workspace/CV keyboard | Command focus/empty result/Escape, Add dialog, manual-activation Job tabs, CV section selection, persisted keyboard reorder, preview entry/end-scroll/exit | Finite paths, not every field/menu or reader announcement |
|
||||
| Landscape text-spacing collection | Six areas at844×390 with WCAG text-spacing overrides | Parent app styles only; verified document iframe geometry is untouched |
|
||||
| CV source action | Actual keyboard activation of Open Career Profile, destination and native source content | Does not replace source/override revision safety tests |
|
||||
| Upload/import keyboard | Focus and Enter/Space on three real controls; positive pointer comparison to the same native file picker | No file data submitted; no synthetic success response |
|
||||
| Emulated touch | CV edit/preview, portrait/landscape CSS viewport changes, unchanged persisted CV, drawer Escape | Chromium touch emulation; not native hardware, orientation sensor or software keyboard |
|
||||
| `browser-zoom-audit.spec.ts`: English/light and Bokmål/dark | Actual Chromium tab zoom100/200/400%; asserts browser zoom, DPR and unchanged pinch scale;13 areas plus text-spacing geometry | Geometry collection is not proof every enabled action is reachable/readable; other browsers/manual vision and hardware remain open |
|
||||
|
||||
Nine ordinary browser cases are added (seven responsive/keyboard cases, two zoom cases). They are not skipped, quarantined, expected-failing or retried. Soft assertions keep known failures failing while collecting additional evidence. No provider requests leave loopback.
|
||||
|
||||
## Focused execution before the coverage commit
|
||||
|
||||
[Native proof](evidence/native-issues.json) retains source-report hashes, test statuses and actual observations. The six-case development audit after separating the drawer from other workflows had **2 passes /4 failures**; one failure was a test assumption: arrows move Job-tab focus, Enter activates. The corrected existing manual-activation contract then passed with command/dialog/CV keyboard checks in the three-case controls rerun (**1 pass /2 failures**).
|
||||
|
||||
The two remaining controls failures are genuine: source action goes to unsupported `/career/profile` (404), and all six Enter/Space picker attempts fail while all three pointer comparisons succeed. No upload/import data was written. The reduced-motion drawer evidence shows focus still on the hidden background trigger before and after axe; immediate Escape leaves the drawer open. Tab plus Escape can close it, but focus lands on another background button rather than returning to the navigation trigger. Emulated CV mode/portrait-landscape/readback succeeds before the same drawer-return assertion fails.
|
||||
|
||||
Genuine zoom collection **2/2 passes**,102 geometry observations. Earlier zoom harness attempts are retained locally: explicit `deviceScaleFactor:undefined` is required with `viewport:null`; Correspondence has two actual H1s, so readiness now identifies its intended inbox heading exactly while still recording both headings. Those harness corrections do not close product heading/manual-review issues. Earlier metadata incorrectly implied tag-only axe selection: installed builder `.options()` replaces earlier `.withTags()` options. The committed collector correctly declares **all enabled rules**, including best practices; per-rule tags distinguish them from WCAG failures.
|
||||
|
||||
App and E2E TypeScript, lint and whitespace checks pass. Complete ordinary regression and final rule/viewport/57-group reconciliation are separate pending audit evidence at this commit; neither the previous134 passes nor collection success is used to claim this audit green. Production remains NO-GO. P5-13 remains deferred, unqualified and Production-withheld; no UI/qualification/Docker work.
|
||||
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"scope": "Native synthetic owned SQLite/browser evidence; no human AT/device acceptance",
|
||||
"reports": [
|
||||
{
|
||||
"source": ".artifacts/p5-15-02/browser/audit-attempt3.json",
|
||||
"sha256": "89af6297f09ad03072e5a617e0e4b0dd55cd8ebe1a8b310872525a8d1d81319d",
|
||||
"stats": {
|
||||
"startTime": "2026-10-10T18:25:41.491Z",
|
||||
"duration": 197611.17,
|
||||
"expected": 2,
|
||||
"skipped": 0,
|
||||
"unexpected": 4,
|
||||
"flaky": 0
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"name": "[P5-15-02] reduced-motion mobile drawer enters focus and Escape returns it",
|
||||
"status": "failed",
|
||||
"errorMessages": [
|
||||
"Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeFocused\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: getByRole('dialog', { name: 'Navigation', exact: true }).getByRole('button', { name: 'Dashboard', exact: true })\nExpected: focused\nReceived: inactive\nTimeout: 5000ms\n\nCall log:\n\u001b[2m - Expect \"soft toBeFocused\" with timeout 5000ms\u001b[22m\n\u001b[2m - waiting for getByRole('dialog', { name: 'Navigation', exact: true }).getByRole('button', { name: 'Dashboard', exact: true })\u001b[22m\n\u001b[2m 12 × locator resolved to <div tabindex=\"0\" role=\"button\" aria-label=\"Dashboard\" class=\"MuiButtonBase-root MuiListItemButton-root MuiListItemButton-gutters MuiListItemButton-root MuiListItemButton-gutters css-j56oom\">…</div>\u001b[22m\n\u001b[2m - unexpected value \"inactive\"\u001b[22m\n\n\n 189 | await navigation.focus(); await navigation.press('Enter');\n 190 | const drawer = page.getByRole('dialog', { name: t.navigation, exact: true });\n> 191 | await expect.soft(drawer.getByRole('button', { name: t.dashboard, exact: true })).toBeFocused();\n | ^\n 192 | const focus = () => page.evaluate(() => ({ active: document.activeElement?.outerHTML.slice(0, 500), focusedInDialog: !!document.activeElement?.closest('[role=dialog]') }));\n 193 | const beforeScan = await focus();\n 194 | await collect(page, info, sample, 'navigation-open');\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:191:85",
|
||||
"Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeFocused\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: getByRole('button', { name: 'Open navigation', exact: true })\nExpected: focused\nTimeout: 5000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"soft toBeFocused\" with timeout 5000ms\u001b[22m\n\u001b[2m - waiting for getByRole('button', { name: 'Open navigation', exact: true })\u001b[22m\n\n\n 194 | await collect(page, info, sample, 'navigation-open');\n 195 | const afterScan = await focus();\n> 196 | await page.keyboard.press('Escape'); await expect.soft(navigation).toBeFocused();\n | ^\n 197 | const afterEscape = await focus();\n 198 | const stayedOpen = await drawer.isVisible();\n 199 | if (stayedOpen) {\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:196:70"
|
||||
],
|
||||
"observations": [
|
||||
{
|
||||
"name": "drawer-focus-recovery",
|
||||
"value": {
|
||||
"beforeScan": {
|
||||
"active": "<button class=\"MuiButtonBase-root Mui-focusVisible MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-edgeStart MuiIconButton-sizeSmall css-1bif13m\" tabindex=\"0\" type=\"button\" aria-label=\"Open navigation\" aria-haspopup=\"dialog\" aria-expanded=\"true\"><svg class=\"MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-1pi2lzz\" focusable=\"false\" aria-hidden=\"true\" viewBox=\"0 0 24 24\"><path d=\"M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z\"></path></svg><span class=\"MuiTouchRipple-root css-4mb1j7\"><span cla",
|
||||
"focusedInDialog": false
|
||||
},
|
||||
"afterScan": {
|
||||
"active": "<button class=\"MuiButtonBase-root Mui-focusVisible MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-edgeStart MuiIconButton-sizeSmall css-1bif13m\" tabindex=\"0\" type=\"button\" aria-label=\"Open navigation\" aria-haspopup=\"dialog\" aria-expanded=\"true\"><svg class=\"MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-1pi2lzz\" focusable=\"false\" aria-hidden=\"true\" viewBox=\"0 0 24 24\"><path d=\"M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z\"></path></svg><span class=\"MuiTouchRipple-root css-4mb1j7\"><span cla",
|
||||
"focusedInDialog": false
|
||||
},
|
||||
"afterEscape": {
|
||||
"active": "<button class=\"MuiButtonBase-root Mui-focusVisible MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-edgeStart MuiIconButton-sizeSmall css-1bif13m\" tabindex=\"0\" type=\"button\" aria-label=\"Open navigation\" aria-haspopup=\"dialog\" aria-expanded=\"true\"><svg class=\"MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-1pi2lzz\" focusable=\"false\" aria-hidden=\"true\" viewBox=\"0 0 24 24\"><path d=\"M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z\"></path></svg><span class=\"MuiTouchRipple-root css-4mb1j7\"><span cla",
|
||||
"focusedInDialog": false
|
||||
},
|
||||
"stayedOpen": true,
|
||||
"afterTabAndEscape": {
|
||||
"active": "<button class=\"MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeSmall MuiButton-containedSizeSmall MuiButton-colorPrimary Mui-focusVisible MuiButtonGroup-grouped MuiButtonGroup-groupedHorizontal MuiButtonGroup-groupedOutlined MuiButtonGroup-groupedOutlinedHorizontal MuiButtonGroup-groupedOutlinedPrimary MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeSmall MuiButton-containedSizeSmall MuiButton-colorPrimary MuiButtonGroup-",
|
||||
"focusedInDialog": false
|
||||
},
|
||||
"drawerStillVisible": false,
|
||||
"humanScreenReader": "NOT VERIFIED"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[P5-15-02 C06 C07] CV source action reaches the existing Career Profile workflow",
|
||||
"status": "failed",
|
||||
"errorMessages": [
|
||||
"Error: \u001b[2mexpect(\u001b[22m\u001b[31mpage\u001b[39m\u001b[2m).\u001b[22mtoHaveURL\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m failed\n\nExpected: predicate to succeed\nReceived: \u001b[31m\"http://localhost:3300/career/profile\"\u001b[39m\nTimeout: 5000ms\n\n\n 272 | await expect(page.getByRole('main')).toBeVisible();\n 273 | await info.attach('cv-source-action-destination', { body: JSON.stringify({ href, destination: page.url(), expected: '/career or /career?section=profile; established canonical source workflow', observedText: await page.getByRole('main').innerText() }), contentType: 'application/json' });\n> 274 | await expect(page).toHaveURL(url => url.pathname === '/career');\n | ^\n 275 | await expect(page.getByLabel(t.profileCvContactFullName, { exact: true })).toHaveValue('Åse Revisjonseksempel');\n 276 | });\n 277 |\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:274:22"
|
||||
],
|
||||
"observations": [
|
||||
{
|
||||
"name": "cv-source-action-destination",
|
||||
"value": {
|
||||
"href": "/career/profile",
|
||||
"destination": "http://localhost:3300/career/profile",
|
||||
"expected": "/career or /career?section=profile; established canonical source workflow",
|
||||
"observedText": "Home\n/\nCareer Workspace\n/\nCV Builder\nCV Builder\nThis CV only\nVersion 1\nSaved\nDownload PDF\nCV editing controls\nContent\nTemplate\nCustomize\nAI Tools\nHistory\nGo to section\n\nGo to section\nGo To Preview\nCareer Profile is your source. Editing wording, order or inclusion here changes only this CV.\nOpen Career Profile\nHeadline override\nHeadline override\n\nBlank uses your Career Profile headline. Changes here affect only this CV.\n\nSections\nDrag to reorder, or use the arrows. Omitted content stays editable.\nAdd Content\nLive preview\nFit width · 68%\n1-page CV\nGo To Editor\nUse Page Up/Down to scroll. Tab moves into or out of the preview.\nPage 1 of 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[P5-15-02] emulated taps preserve CV modes and navigation across portrait/landscape viewport changes",
|
||||
"status": "failed",
|
||||
"errorMessages": [
|
||||
"Error: \u001b[2mexpect(\u001b[22m\u001b[31mlocator\u001b[39m\u001b[2m).\u001b[22mtoBeFocused\u001b[2m(\u001b[22m\u001b[2m)\u001b[22m failed\n\nLocator: getByRole('button', { name: 'Åpne navigasjon', exact: true })\nExpected: focused\nTimeout: 5000ms\nError: element(s) not found\n\nCall log:\n\u001b[2m - Expect \"soft toBeFocused\" with timeout 5000ms\u001b[22m\n\u001b[2m - waiting for getByRole('button', { name: 'Åpne navigasjon', exact: true })\u001b[22m\n\n\n 299 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n 300 | if (pointerChooser) await pointerChooser.setFiles([]);\n> 301 | expect.soft(!!pointerChooser, `${label} pointer comparison opens the same picker`).toBe(true);\n | ^\n 302 | }\n 303 | }\n 304 | await info.attach('native-keyboard-file-chooser', { body: JSON.stringify({ outcomes, fileDataWritten: false }), contentType: 'application/json' });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:301:72"
|
||||
],
|
||||
"observations": [
|
||||
{
|
||||
"name": "emulated-touch-boundary",
|
||||
"value": {
|
||||
"hasTouch": true,
|
||||
"input": "Playwright Chromium touch tap",
|
||||
"portraitLandscape": "CSS viewport changes, not physical orientation sensor",
|
||||
"physicalTouch": "NOT VERIFIED",
|
||||
"nativeTouchDrag": "NOT VERIFIED",
|
||||
"softwareKeyboard": "NOT VERIFIED",
|
||||
"cvUnchanged": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": ".artifacts/p5-15-02/browser/audit-controls.json",
|
||||
"sha256": "cc1e74867b5103ff214fd1355c3029a5f9027265bd978bacd5382574b7decb06",
|
||||
"stats": {
|
||||
"startTime": "2026-10-10T18:29:22.564Z",
|
||||
"duration": 86727.949,
|
||||
"expected": 1,
|
||||
"skipped": 0,
|
||||
"unexpected": 2,
|
||||
"flaky": 0
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"name": "[P5-15-02] keyboard command, dialog, section and document controls keep deliberate focus contracts",
|
||||
"status": "passed",
|
||||
"errorMessages": [],
|
||||
"observations": [
|
||||
{
|
||||
"name": "native-keyboard-contracts",
|
||||
"value": {
|
||||
"commandEntryAndEscapeReturn": true,
|
||||
"commandWorkflowDialog": true,
|
||||
"workspaceArrowNavigation": true,
|
||||
"cvKeyboardOrderPersisted": true,
|
||||
"previewEntryScrollExit": true,
|
||||
"evidence": "preceding hard assertions completed",
|
||||
"humanScreenReader": "NOT VERIFIED"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[P5-15-02 C06 C07] CV source action reaches the existing Career Profile workflow",
|
||||
"status": "failed",
|
||||
"errorMessages": [
|
||||
"Error: \u001b[2mexpect(\u001b[22m\u001b[31mpage\u001b[39m\u001b[2m).\u001b[22mtoHaveURL\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m failed\n\nExpected: predicate to succeed\nReceived: \u001b[31m\"http://localhost:3300/career/profile\"\u001b[39m\nTimeout: 5000ms\n\n\n 276 | await expect(page.getByRole('main')).toBeVisible();\n 277 | await info.attach('cv-source-action-destination', { body: JSON.stringify({ href, destination: page.url(), expected: '/career or /career?section=profile; established canonical source workflow', observedText: await page.getByRole('main').innerText() }), contentType: 'application/json' });\n> 278 | await expect(page).toHaveURL(url => url.pathname === '/career');\n | ^\n 279 | await expect(page.getByLabel(t.profileCvContactFullName, { exact: true })).toHaveValue('Åse Revisjonseksempel');\n 280 | });\n 281 |\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:278:22"
|
||||
],
|
||||
"observations": [
|
||||
{
|
||||
"name": "cv-source-action-destination",
|
||||
"value": {
|
||||
"href": "/career/profile",
|
||||
"destination": "http://localhost:3300/career/profile",
|
||||
"expected": "/career or /career?section=profile; established canonical source workflow",
|
||||
"observedText": "Home\n/\nCareer Workspace\nCareer Workspace\n\n404\n\nPage not found\n\nThe page you were looking for does not exist or may have moved.\n\nGo Home\nGo Back"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[P5-15-02 W08 J10] keyboard upload and import controls open the native file chooser",
|
||||
"status": "failed",
|
||||
"errorMessages": [
|
||||
"Error: Upload Enter opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75",
|
||||
"Error: Upload Space opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75",
|
||||
"Error: Import JSON Enter opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75",
|
||||
"Error: Import JSON Space opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75",
|
||||
"Error: Convert CSV to Import JSON Enter opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75",
|
||||
"Error: Convert CSV to Import JSON Space opens the native picker\n\n\u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoBe\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // Object.is equality\u001b[22m\n\nExpected: \u001b[32mtrue\u001b[39m\nReceived: \u001b[31mfalse\u001b[39m\n\n 298 | outcomes.push({ route: path, label, key, opened: !!chooser });\n 299 | if (chooser) await chooser.setFiles([]);\n> 300 | expect.soft(!!chooser, `${label} ${key} opens the native picker`).toBe(true);\n | ^\n 301 | }\n 302 | const [pointerChooser] = await Promise.all([page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null), control.click()]);\n 303 | outcomes.push({ route: path, label, key: 'pointer comparison', opened: !!pointerChooser });\n at E:\\Storage\\Projects\\Active\\Job tracker\\job-tracker-ui\\e2e\\responsive-accessibility-audit.spec.ts:300:75"
|
||||
],
|
||||
"observations": [
|
||||
{
|
||||
"name": "native-keyboard-file-chooser",
|
||||
"value": {
|
||||
"outcomes": [
|
||||
{
|
||||
"route": "/jobs/13?section=documents",
|
||||
"label": "Upload",
|
||||
"key": "Enter",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/jobs/13?section=documents",
|
||||
"label": "Upload",
|
||||
"key": "Space",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/jobs/13?section=documents",
|
||||
"label": "Upload",
|
||||
"key": "pointer comparison",
|
||||
"opened": true
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Import JSON",
|
||||
"key": "Enter",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Import JSON",
|
||||
"key": "Space",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Import JSON",
|
||||
"key": "pointer comparison",
|
||||
"opened": true
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Convert CSV to Import JSON",
|
||||
"key": "Enter",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Convert CSV to Import JSON",
|
||||
"key": "Space",
|
||||
"opened": false
|
||||
},
|
||||
{
|
||||
"route": "/settings",
|
||||
"label": "Convert CSV to Import JSON",
|
||||
"key": "pointer comparison",
|
||||
"opened": true
|
||||
}
|
||||
],
|
||||
"fileDataWritten": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"source": ".artifacts/p5-15-02/browser/zoom.json",
|
||||
"sha256": "ec2688b919aac5eade1613c94405d889dacd649cfa932e83f9faea748edc4e1a",
|
||||
"stats": {
|
||||
"startTime": "2026-10-10T18:22:11.787Z",
|
||||
"duration": 43911.678,
|
||||
"expected": 2,
|
||||
"skipped": 0,
|
||||
"unexpected": 0,
|
||||
"flaky": 0
|
||||
},
|
||||
"tests": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user