From eabc6e04aa250e25e18f03726a8d2232161c1190 Mon Sep 17 00:00:00 2001 From: Mx Corey Frang Date: Wed, 5 Nov 2025 15:37:43 -0500 Subject: [PATCH 1/6] fix: Consistent column order for ARIA and HTML Features tabs (#1620) * fix: order report table headings alphabetical * updated snapshots --- .../Reports/FeatureSupportTable.jsx | 1 + .../Reports/SummarizeTestPlanReports.jsx | 81 +++++++------ .../tests/e2e/snapshots/saved/_reports.html | 110 +++++++++--------- 3 files changed, 96 insertions(+), 96 deletions(-) diff --git a/client/components/Reports/FeatureSupportTable.jsx b/client/components/Reports/FeatureSupportTable.jsx index afc24df9c..a9579b6a7 100644 --- a/client/components/Reports/FeatureSupportTable.jsx +++ b/client/components/Reports/FeatureSupportTable.jsx @@ -10,6 +10,7 @@ const none = None(); const FeatureSupportTable = ({ featureData, featureLabel }) => { const supportCombos = [...new Set(featureData.map(columnName))]; + supportCombos.sort((a, b) => a.localeCompare(b)); const dataByFeature = {}; const links = {}; diff --git a/client/components/Reports/SummarizeTestPlanReports.jsx b/client/components/Reports/SummarizeTestPlanReports.jsx index 84f47822b..3d1ef0a47 100644 --- a/client/components/Reports/SummarizeTestPlanReports.jsx +++ b/client/components/Reports/SummarizeTestPlanReports.jsx @@ -50,8 +50,11 @@ const SummarizeTestPlanReports = ({ testPlanTargetsById[testPlanTarget.id] = testPlanTarget; }); }); - testPlanTargetsById = alphabetizeObjectBy(testPlanTargetsById, keyValue => - getTestPlanTargetTitle(keyValue[1]) + const orderedColumns = Object.entries(testPlanTargetsById).map( + ([, data]) => data + ); + orderedColumns.sort((a, b) => + getTestPlanTargetTitle(a).localeCompare(getTestPlanTargetTitle(b)) ); const none = None(); @@ -92,13 +95,11 @@ const SummarizeTestPlanReports = ({ Test Plan - {Object.values(testPlanTargetsById).map( - testPlanTarget => ( - - {getTestPlanTargetTitle(testPlanTarget)} - - ) - )} + {orderedColumns.map(testPlanTarget => ( + + {getTestPlanTargetTitle(testPlanTarget)} + + ))} @@ -128,43 +129,41 @@ const SummarizeTestPlanReports = ({ {derivePhaseName(phase)} - {Object.values(testPlanTargetsById).map( - testPlanTarget => { - const testPlanReport = testPlanReports.find( - testPlanReport => - testPlanReport.at.id === - testPlanTarget.at.id && - testPlanReport.browser.id === - testPlanTarget.browser.id - ); + {orderedColumns.map(testPlanTarget => { + const testPlanReport = testPlanReports.find( + testPlanReport => + testPlanReport.at.id === + testPlanTarget.at.id && + testPlanReport.browser.id === + testPlanTarget.browser.id + ); - if (!testPlanReport) { - return ( - - {none} - - ); - } - const metrics = testPlanReport.metrics; + if (!testPlanReport) { return ( - - - - + + {none} ); } - )} + const metrics = testPlanReport.metrics; + return ( + + + + + + ); + })} ); })} diff --git a/client/tests/e2e/snapshots/saved/_reports.html b/client/tests/e2e/snapshots/saved/_reports.html index 8c5885f96..df6eb2b2f 100644 --- a/client/tests/e2e/snapshots/saved/_reports.html +++ b/client/tests/e2e/snapshots/saved/_reports.html @@ -151,10 +151,10 @@

Test Plan Support Levels

Test Plan - JAWS and Firefox JAWS and Chrome - NVDA and Firefox + JAWS and Firefox NVDA and Chrome + NVDA and Firefox VoiceOver for macOS and Chrome VoiceOver for macOS and Safari @@ -174,7 +174,7 @@

Test Plan Support Levels

> -
Test Plan Support Levels > -
Test Plan Support Levels > -
Test Plan Support Levels > -
Test Plan Support Levels >Recommended - None
@@ -285,6 +284,7 @@

Test Plan Support Levels

> None + None
@@ -308,7 +308,6 @@

Test Plan Support Levels

>Candidate - None
@@ -335,6 +334,7 @@

Test Plan Support Levels

> None + None
@@ -368,12 +368,12 @@

ARIA Feature Support Levels

ARIA Feature - VoiceOver for macOS and Safari + JAWS and Chrome JAWS and Firefox - VoiceOver for macOS and Chrome NVDA and Chrome NVDA and Firefox - JAWS and Chrome + VoiceOver for macOS and Chrome + VoiceOver for macOS and Safari @@ -389,7 +389,7 @@

ARIA Feature Support Levels

ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels >menu - None
ARIA Feature Support Levels
- None
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
+ None + None @@ -927,7 +927,7 @@

ARIA Feature Support Levels

ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
ARIA Feature Support Levels
HTML Feature Support Levels HTML Feature - VoiceOver for macOS and Safari + JAWS and Chrome JAWS and Firefox - VoiceOver for macOS and Chrome NVDA and Chrome NVDA and Firefox - JAWS and Chrome + VoiceOver for macOS and Chrome + VoiceOver for macOS and Safari @@ -1050,7 +1050,7 @@

HTML Feature Support Levels

HTML Feature Support Levels
HTML Feature Support Levels
HTML Feature Support Levels
HTML Feature Support Levels
Date: Thu, 6 Nov 2025 08:00:46 -0800 Subject: [PATCH 2/6] feat: open new tab, close tab and return to open queue on save (#1605) * feat: open new tab, close tab on save * fix e2e tests, better button disabled toggle * Fix e2e tests * Fix snapshots * Track new tabs * Close all pages afterEach * Track pages at test level * use global to determine link behavior * use evaluateOnNewDocument for global --------- Co-authored-by: Howard Edwards --- client/components/TestQueue/Actions.jsx | 26 +++++++++++++++++++ .../Conflicts/TestConflictsActions.jsx | 12 +++++++++ client/components/TestRun/index.jsx | 4 ++- client/tests/util/getPage.js | 4 +++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/client/components/TestQueue/Actions.jsx b/client/components/TestQueue/Actions.jsx index d6fd4000c..10f997ab7 100644 --- a/client/components/TestQueue/Actions.jsx +++ b/client/components/TestQueue/Actions.jsx @@ -240,6 +240,20 @@ const Actions = ({ variant="primary" disabled={!selfAssignedRun} href={selfAssignedRun ? `/run/${selfAssignedRun.id}` : undefined} + target={selfAssignedRun ? '_blank' : undefined} + onClick={e => { + if (!selfAssignedRun) { + e.preventDefault(); + e.stopPropagation(); + return; + } + e.preventDefault(); + if (window.PUPPETEER_TESTING) { + window.location.href = `/run/${selfAssignedRun.id}`; + } else { + window.open(`/run/${selfAssignedRun.id}`, '_blank'); + } + }} > {selfAssignedRun?.testResultsLength ? 'Continue Testing' @@ -260,6 +274,18 @@ const Actions = ({ key={testPlanRun.id} role="menuitem" href={`/run/${testPlanRun.id}?user=${testPlanRun.tester.id}`} + target="_blank" + onClick={e => { + e.preventDefault(); + if (window.PUPPETEER_TESTING) { + window.location.href = `/run/${testPlanRun.id}?user=${testPlanRun.tester.id}`; + } else { + window.open( + `/run/${testPlanRun.id}?user=${testPlanRun.tester.id}`, + '_blank' + ); + } + }} > {testPlanRun.tester.username} diff --git a/client/components/TestQueue/Conflicts/TestConflictsActions.jsx b/client/components/TestQueue/Conflicts/TestConflictsActions.jsx index 16d65dc2e..dc995c272 100644 --- a/client/components/TestQueue/Conflicts/TestConflictsActions.jsx +++ b/client/components/TestQueue/Conflicts/TestConflictsActions.jsx @@ -37,6 +37,18 @@ const TestConflictsActions = ({ { + e.preventDefault(); + if (window.PUPPETEER_TESTING) { + window.location.href = `/run/${testPlanRun.id}?user=${testPlanRun.tester.id}#${testIndex}`; + } else { + window.open( + `/run/${testPlanRun.id}?user=${testPlanRun.tester.id}#${testIndex}`, + '_blank' + ); + } + }} > {testPlanRun.tester.username} diff --git a/client/components/TestRun/index.jsx b/client/components/TestRun/index.jsx index b7b0bfe17..10a32c807 100644 --- a/client/components/TestRun/index.jsx +++ b/client/components/TestRun/index.jsx @@ -645,7 +645,9 @@ const TestRun = () => { case 'closeTest': { // Save renderer's form state await saveForm(); - navigate('/test-queue'); + if (!window.PUPPETEER_TESTING) { + window.close(); + } break; } } diff --git a/client/tests/util/getPage.js b/client/tests/util/getPage.js index 1b68058b3..60f4ad432 100644 --- a/client/tests/util/getPage.js +++ b/client/tests/util/getPage.js @@ -135,6 +135,10 @@ const getPage = async (options, callback) => { const page = await incognitoContext.newPage(); + await page.evaluateOnNewDocument(() => { + window.PUPPETEER_TESTING = true; + }); + if (!url) { throw new Error('Please provide a URL, even if it it is simply "/"'); } From 9e89b8ad228ea96cf11422a13ddf254c77f5cf3a Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Thu, 6 Nov 2025 12:28:38 -0500 Subject: [PATCH 3/6] fix: Prefer "No Data" instead of "None" on reports pages (#1622) * Prefer No Data instead of None on reports pages * Update snapshots --- .../Reports/FeatureSupportTable.jsx | 2 +- .../Reports/SummarizeTestPlanReport.jsx | 2 +- .../Reports/SummarizeTestPlanReports.jsx | 3 +- .../Reports/SummarizeTestPlanVersion.jsx | 2 +- .../saved/_report_67_targets_20.html | 34 +++++++++---------- .../tests/e2e/snapshots/saved/_reports.html | 16 ++++----- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/client/components/Reports/FeatureSupportTable.jsx b/client/components/Reports/FeatureSupportTable.jsx index a9579b6a7..dd4570e8c 100644 --- a/client/components/Reports/FeatureSupportTable.jsx +++ b/client/components/Reports/FeatureSupportTable.jsx @@ -6,7 +6,7 @@ import ProgressBar from '@components/common/ProgressBar'; import { None } from '@components/common/None'; const columnName = ({ atName, browserName }) => `${atName} and ${browserName}`; -const none = None(); +const none = None('No Data'); const FeatureSupportTable = ({ featureData, featureLabel }) => { const supportCombos = [...new Set(featureData.map(columnName))]; diff --git a/client/components/Reports/SummarizeTestPlanReport.jsx b/client/components/Reports/SummarizeTestPlanReport.jsx index dadd160d6..043e21111 100644 --- a/client/components/Reports/SummarizeTestPlanReport.jsx +++ b/client/components/Reports/SummarizeTestPlanReport.jsx @@ -53,7 +53,7 @@ const SummarizeTestPlanReport = ({ testPlanVersion, testPlanReports }) => { atVersion: recommendedAtVersion }; - const none = None(); + const none = None('No Data'); const renderVersionsSummaryTable = () => { if (testPlanVersion.phase !== 'RECOMMENDED') return null; diff --git a/client/components/Reports/SummarizeTestPlanReports.jsx b/client/components/Reports/SummarizeTestPlanReports.jsx index 3d1ef0a47..30318275f 100644 --- a/client/components/Reports/SummarizeTestPlanReports.jsx +++ b/client/components/Reports/SummarizeTestPlanReports.jsx @@ -4,7 +4,6 @@ import { Helmet } from 'react-helmet'; import { Link } from 'react-router-dom'; import { Container, Table } from 'react-bootstrap'; import clsx from 'clsx'; -import alphabetizeObjectBy from '../../utils/alphabetizeObjectBy'; import { derivePhaseName } from '../../utils/aria'; import { None } from '@components/common/None'; import { getTestPlanTargetTitle, getTestPlanVersionTitle } from './getTitles'; @@ -57,7 +56,7 @@ const SummarizeTestPlanReports = ({ getTestPlanTargetTitle(a).localeCompare(getTestPlanTargetTitle(b)) ); - const none = None(); + const none = None('No Data'); return ( { return 0; }); - const none = None(); + const none = None('No Data'); return ( NVDA Versions Summary 2023.3.3 124 of 124 passed 35 of 36 passed - None + No Data 2020.4 124 of 124 passed 36 of 36 passed - None + No Data @@ -209,7 +209,7 @@

Results for NVDA 2023.3.3 and Chrome

24 of 24 passed 4 of 4 passed - None + No Data @@ -221,7 +221,7 @@

Results for NVDA 2023.3.3 and Chrome

6 of 6 passed 1 of 1 passed - None + No Data @@ -232,7 +232,7 @@

Results for NVDA 2023.3.3 and Chrome

24 of 24 passed 3 of 4 passed - None + No Data @@ -244,7 +244,7 @@

Results for NVDA 2023.3.3 and Chrome

6 of 6 passed 1 of 1 passed - None + No Data @@ -256,7 +256,7 @@

Results for NVDA 2023.3.3 and Chrome

8 of 8 passed 6 of 6 passed - None + No Data @@ -268,7 +268,7 @@

Results for NVDA 2023.3.3 and Chrome

8 of 8 passed 6 of 6 passed - None + No Data @@ -279,7 +279,7 @@

Results for NVDA 2023.3.3 and Chrome

2 of 2 passed 1 of 1 passed - None + No Data @@ -290,7 +290,7 @@

Results for NVDA 2023.3.3 and Chrome

2 of 2 passed 1 of 1 passed - None + No Data @@ -301,7 +301,7 @@

Results for NVDA 2023.3.3 and Chrome

2 of 2 passed 1 of 1 passed - None + No Data @@ -312,7 +312,7 @@

Results for NVDA 2023.3.3 and Chrome

2 of 2 passed 1 of 1 passed - None + No Data @@ -324,7 +324,7 @@

Results for NVDA 2023.3.3 and Chrome

16 of 16 passed 4 of 4 passed - None + No Data @@ -336,7 +336,7 @@

Results for NVDA 2023.3.3 and Chrome

4 of 4 passed 1 of 1 passed - None + No Data @@ -348,7 +348,7 @@

Results for NVDA 2023.3.3 and Chrome

16 of 16 passed 4 of 4 passed - None + No Data @@ -360,13 +360,13 @@

Results for NVDA 2023.3.3 and Chrome

4 of 4 passed 1 of 1 passed - None + No Data All Tests 124 of 124 passed 35 of 36 passed - None + No Data diff --git a/client/tests/e2e/snapshots/saved/_reports.html b/client/tests/e2e/snapshots/saved/_reports.html index df6eb2b2f..2dc6da4fb 100644 --- a/client/tests/e2e/snapshots/saved/_reports.html +++ b/client/tests/e2e/snapshots/saved/_reports.html @@ -270,7 +270,7 @@

Test Plan Support Levels

- None + No Data
@@ -283,8 +283,8 @@

Test Plan Support Levels

- None - None + No Data + No Data
@@ -320,7 +320,7 @@

Test Plan Support Levels

- None + No Data
@@ -333,8 +333,8 @@

Test Plan Support Levels

- None - None + No Data + No Data
@@ -912,8 +912,8 @@

ARIA Feature Support Levels

- None - None + No Data + No Data From 849301d58ad6f800eeba71427f5c5725b9147f41 Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Thu, 6 Nov 2025 17:01:20 -0500 Subject: [PATCH 4/6] feat: Support for subfolders in `/aria-at/tests/*` (#1613) * Add support for importing content from aria-at with subfolders in tests * Fix path changes with TestPlanVersions page * Quickfix support for finding the issues * Fix test * Update tests-import to prepend TestPlanVersion directory with '/apg' by default; update tests and snapshots * Fix embed test * Update e2e tests * Update graphql.test.js * Escape selectors * Fix selectors * Update TestQueue.e2e * Fix TestRun.e2e test * Fix TestRun.e2e * Fix TestRun.e2e --- .../components/TestPlanVersionsPage/index.jsx | 11 +- client/routes/index.js | 6 +- client/tests/e2e/TestPlanVersions.e2e.test.js | 10 +- client/tests/e2e/TestQueue.e2e.test.js | 69 ++--- client/tests/e2e/TestRun.e2e.test.js | 35 +-- .../snapshots/saved/_account_settings.html | 2 +- ...idate-test-plan_24_1#summary-failures.html | 4 +- .../saved/_candidate-test-plan_24_1.html | 4 +- .../e2e/snapshots/saved/_data-management.html | 241 +++++++++++------- ...r.html => _data-management_apg_meter.html} | 4 +- .../saved/_report_67_targets_20.html | 28 +- client/tests/e2e/snapshots/saved/_run_2.html | 2 +- .../snapshots/saved/_test-plan-report_1.html | 10 +- .../e2e/snapshots/saved/_test-queue.html | 72 +++--- .../saved/_test-queue_2_conflicts.html | 6 +- .../e2e/snapshots/saved/_test-review_8.html | 4 +- client/tests/e2e/snapshots/utils.js | 2 +- server/apps/embed.js | 4 +- ...251103214245-update-directory-names-apg.js | 32 +++ .../TestPlanReport/issuesResolver.js | 11 +- server/scripts/import-tests/gitOperations.js | 2 +- .../import-tests/testPlanVersionOperations.js | 98 +++++-- .../tests/integration/dataManagement.test.js | 4 +- server/tests/integration/embed.test.js | 8 +- server/tests/integration/graphql.test.js | 2 +- 25 files changed, 414 insertions(+), 257 deletions(-) rename client/tests/e2e/snapshots/saved/{_data-management_meter.html => _data-management_apg_meter.html} (99%) create mode 100644 server/migrations/20251103214245-update-directory-names-apg.js diff --git a/client/components/TestPlanVersionsPage/index.jsx b/client/components/TestPlanVersionsPage/index.jsx index ff7608eca..47d68b47a 100644 --- a/client/components/TestPlanVersionsPage/index.jsx +++ b/client/components/TestPlanVersionsPage/index.jsx @@ -2,7 +2,7 @@ import React, { useMemo, useRef } from 'react'; import { useQuery } from '@apollo/client'; import { TEST_PLAN_VERSIONS_PAGE_QUERY } from './queries'; import PageStatus from '../common/PageStatus'; -import { useParams } from 'react-router-dom'; +import { useParams, Navigate } from 'react-router-dom'; import { Helmet } from 'react-helmet'; import { Container, Table } from 'react-bootstrap'; import VersionString from '../common/VersionString'; @@ -23,7 +23,8 @@ import styles from './TestPlanVersionsPage.module.css'; import commonStyles from '../common/styles.module.css'; const TestPlanVersionsPage = () => { - const { testPlanDirectory } = useParams(); + const params = useParams(); + const testPlanDirectory = params['*']?.replace(/\/$/, '') || ''; const { loading, data, error } = useQuery(TEST_PLAN_VERSIONS_PAGE_QUERY, { variables: { testPlanDirectory }, @@ -37,9 +38,13 @@ const TestPlanVersionsPage = () => { // GraphQL results are read only so they need to be cloned // before passing to SortableIssuesTable const issues = useMemo(() => { - return data ? [...data.testPlan.issues] : []; + return data?.testPlan?.issues ? [...data.testPlan.issues] : []; }, [data]); + if (data && !data.testPlan) { + return ; + } + if (error) { return ( ( } /> } /> - } - /> + } /> } /> } /> } /> diff --git a/client/tests/e2e/TestPlanVersions.e2e.test.js b/client/tests/e2e/TestPlanVersions.e2e.test.js index b80d7c947..65f67541a 100644 --- a/client/tests/e2e/TestPlanVersions.e2e.test.js +++ b/client/tests/e2e/TestPlanVersions.e2e.test.js @@ -4,7 +4,7 @@ import { text } from './util'; describe('Versions page for pattern with highest report being recommended', () => { it('renders page h1', async () => { await getPage( - { role: false, url: '/data-management/checkbox-tri-state' }, + { role: false, url: '/data-management/apg/checkbox-tri-state' }, async (page, { consoleErrors }) => { await text( page, @@ -20,7 +20,7 @@ describe('Versions page for pattern with highest report being recommended', () = describe('Versions page for pattern with highest report being candidate', () => { it('renders page h1', async () => { await getPage( - { role: false, url: '/data-management/modal-dialog' }, + { role: false, url: '/data-management/apg/modal-dialog' }, async page => { await text( page, @@ -34,7 +34,7 @@ describe('Versions page for pattern with highest report being candidate', () => describe('Versions page for pattern with highest report being draft', () => { it('renders page h1', async () => { await getPage( - { role: false, url: '/data-management/alert' }, + { role: false, url: '/data-management/apg/alert' }, async page => { await text(page, 'h1 ::-p-text(Alert Example Test Plan Versions)'); } @@ -45,7 +45,7 @@ describe('Versions page for pattern with highest report being draft', () => { describe('Versions page for pattern with highest report being R&D', () => { it('renders page h1', async () => { await getPage( - { role: false, url: '/data-management/banner' }, + { role: false, url: '/data-management/apg/banner' }, async page => { await text(page, 'h1 ::-p-text(Banner Landmark Test Plan Versions)'); } @@ -54,7 +54,7 @@ describe('Versions page for pattern with highest report being R&D', () => { }); describe('Issues table interactions', () => { - const TEST_URL = '/data-management/alert'; + const TEST_URL = '/data-management/apg/alert'; it('displays correct issue counts in heading', async () => { await getPage({ role: false, url: TEST_URL }, async page => { diff --git a/client/tests/e2e/TestQueue.e2e.test.js b/client/tests/e2e/TestQueue.e2e.test.js index b5ed2a69c..469a4ee45 100644 --- a/client/tests/e2e/TestQueue.e2e.test.js +++ b/client/tests/e2e/TestQueue.e2e.test.js @@ -56,11 +56,11 @@ describe('Test Queue admin traits when reports exist', () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { const alertSectionHeaderSelector = 'h2 ::-p-text(Alert Example)'; const alertSectionContainerSelector = - 'div#disclosure-btn-controls-alert-0'; + 'div#disclosure-btn-controls-apg\\/alert-0'; const modalDialogSectionHeaderSelector = 'h2 ::-p-text(Modal Dialog Example)'; const modalDialogSectionContainerSelector = - 'div#disclosure-btn-controls-modal-dialog-0'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0'; const alertSectionTitle = await text(page, alertSectionHeaderSelector); const alertSectionDisplay = await display( @@ -86,11 +86,11 @@ describe('Test Queue admin traits when reports exist', () => { it("renders page and open pattern section's table", async () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { const modalDialogSectionContainerSelector = - 'div#disclosure-btn-controls-modal-dialog-0'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0'; const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); @@ -103,7 +103,7 @@ describe('Test Queue admin traits when reports exist', () => { modalDialogSectionContainerSelector ); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); const postClickModalDialogSectionDisplay = await display( page, @@ -169,7 +169,7 @@ describe('Test Queue admin traits when reports exist', () => { ); }); - expect(modalDialogSectionButton.includes('V24.06.07')).toBe(true); + expect(modalDialogSectionButton.includes('V25.10.16')).toBe(true); expect(preClickModalDialogSectionDisplay).toBe('none'); expect(postClickModalDialogSectionDisplay).toBe('block'); expect(validTable).toBe(true); @@ -179,13 +179,13 @@ describe('Test Queue admin traits when reports exist', () => { it("renders page, opens pattern section's table and assigns bot and shows context related action", async () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); // Wait for the table to render @@ -193,7 +193,7 @@ describe('Test Queue admin traits when reports exist', () => { const assignTestersDropdownButton = await page.evaluateHandle(() => { const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; const modalDialogTable = document.querySelector( modalDialogTableSelector ); @@ -259,15 +259,15 @@ describe('Test Queue admin traits when reports exist', () => { it("renders page, opens pattern section's table and creates report using test plan report status dialog", async () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogRequiredReportsButtonSelector = - 'div#disclosure-btn-controls-modal-dialog-0 div.metadata-container button.test-plan-report-status-dialog-button'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0 div.metadata-container button.test-plan-report-status-dialog-button'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); // Wait for the table to render @@ -317,15 +317,15 @@ describe('Test Queue admin traits when reports exist', () => { it("renders page, opens pattern section's table and creates report using test plan report status dialog after updating minimum AT version", async () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogRequiredReportsButtonSelector = - 'div#disclosure-btn-controls-modal-dialog-0 div.metadata-container button.test-plan-report-status-dialog-button'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0 div.metadata-container button.test-plan-report-status-dialog-button'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); // Wait for the table to render @@ -388,9 +388,10 @@ describe('Test Queue admin traits when reports exist', () => { it('allows admin to toggle On hold and shows pill in Status', async () => { await getPage({ role: 'admin', url: '/test-queue' }, async page => { - const sectionButtonSelector = 'button#disclosure-btn-modal-dialog-0'; + const sectionButtonSelector = + 'button#disclosure-btn-apg\\/modal-dialog-0'; const tableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(sectionButtonSelector); await page.click(sectionButtonSelector); @@ -485,11 +486,11 @@ describe('Test Queue tester traits when reports exist', () => { await getPage({ role: 'tester', url: '/test-queue' }, async page => { const alertSectionHeaderSelector = 'h2 ::-p-text(Alert Example)'; const alertSectionContainerSelector = - 'div#disclosure-btn-controls-alert-0'; + 'div#disclosure-btn-controls-apg\\/alert-0'; const modalDialogSectionHeaderSelector = 'h2 ::-p-text(Modal Dialog Example)'; const modalDialogSectionContainerSelector = - 'div#disclosure-btn-controls-modal-dialog-0'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0'; const alertSectionTitle = await text(page, alertSectionHeaderSelector); const alertSectionDisplay = await display( @@ -515,11 +516,11 @@ describe('Test Queue tester traits when reports exist', () => { it("renders page and open pattern section's table", async () => { await getPage({ role: 'tester', url: '/test-queue' }, async page => { const modalDialogSectionContainerSelector = - 'div#disclosure-btn-controls-modal-dialog-0'; + 'div#disclosure-btn-controls-apg\\/modal-dialog-0'; const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); @@ -532,7 +533,7 @@ describe('Test Queue tester traits when reports exist', () => { modalDialogSectionContainerSelector ); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); const postClickModalDialogSectionDisplay = await display( page, @@ -599,7 +600,7 @@ describe('Test Queue tester traits when reports exist', () => { ); }); - expect(modalDialogSectionButton.includes('V24.06.07')).toBe(true); + expect(modalDialogSectionButton.includes('V25.10.16')).toBe(true); expect(preClickModalDialogSectionDisplay).toBe('none'); expect(postClickModalDialogSectionDisplay).toBe('block'); expect(validTable).toBe(true); @@ -609,13 +610,13 @@ describe('Test Queue tester traits when reports exist', () => { it("renders page, opens pattern section's table and assigns yourself and shows proper state of context related action", async () => { await getPage({ role: 'tester', url: '/test-queue' }, async page => { const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.click(modalDialogSectionButtonSelector); // Wait for the table to render @@ -654,7 +655,7 @@ describe('Test Queue tester traits when reports exist', () => { const assignYourselfButton = await page.evaluateHandle(() => { const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; const modalDialogTable = document.querySelector( modalDialogTableSelector ); @@ -716,9 +717,9 @@ describe('Test Queue tester traits when reports exist', () => { it('starts a bot run and reassigns self after completion', async () => { await getPage({ role: 'tester', url: '/test-queue' }, async page => { const modalDialogSectionButtonSelector = - 'button#disclosure-btn-modal-dialog-0'; + 'button#disclosure-btn-apg\\/modal-dialog-0'; const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(modalDialogSectionButtonSelector); await page.click(modalDialogSectionButtonSelector); diff --git a/client/tests/e2e/TestRun.e2e.test.js b/client/tests/e2e/TestRun.e2e.test.js index fe1a9f25b..fca6ea149 100644 --- a/client/tests/e2e/TestRun.e2e.test.js +++ b/client/tests/e2e/TestRun.e2e.test.js @@ -113,11 +113,11 @@ describe('Test Run when signed in as admin', () => { const navigateToRunAsTester = async ( page, { - testPlanSectionButtonSelector = 'button#disclosure-btn-modal-dialog-0', - testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]' + testPlanSectionButtonSelector = 'button#disclosure-btn-apg\\/modal-dialog-0', + testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]' } = {} ) => { - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.waitForSelector(testPlanSectionButtonSelector); await page.click(testPlanSectionButtonSelector); @@ -127,7 +127,7 @@ describe('Test Run when signed in as admin', () => { // Find the 'Open run as...' dropdown button from the Actions Column await page.evaluate(() => { const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; const modalDialogTable = document.querySelector(modalDialogTableSelector); // Find the 'Open run as...' button from the Actions Column @@ -280,14 +280,14 @@ describe('Test Run when signed in as tester', () => { const assignSelfAndNavigateToRun = async ( page, { - testPlanSectionButtonSelector = 'button#disclosure-btn-modal-dialog-0', - testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]' + testPlanSectionButtonSelector = 'button#disclosure-btn-apg\\/modal-dialog-0', + testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]' } = {} ) => { const startTestingButtonSelector = 'a[role="button"] ::-p-text(Start Testing)'; - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.waitForSelector(testPlanSectionButtonSelector); await page.click(testPlanSectionButtonSelector); @@ -339,11 +339,11 @@ describe('Test Run when signed in as tester', () => { const navigateToRunAsAnotherTester = async ( page, { - testPlanSectionButtonSelector = 'button#disclosure-btn-modal-dialog-0', - testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]' + testPlanSectionButtonSelector = 'button#disclosure-btn-apg\\/modal-dialog-0', + testPlanTableSelector = 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]' } = {} ) => { - // Expand Modal Dialog's V24.06.07 section + // Expand Modal Dialog's V25.10.16 section await page.waitForSelector(testPlanSectionButtonSelector); await page.click(testPlanSectionButtonSelector); @@ -353,7 +353,7 @@ describe('Test Run when signed in as tester', () => { // Find the 'View Results for...' dropdown button from the Actions Column await page.evaluate(() => { const modalDialogTableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; const modalDialogTable = document.querySelector(modalDialogTableSelector); // Find the 'View Results for...' button from the Actions Column @@ -627,7 +627,7 @@ describe('Test Run when signed in as tester', () => { }; await getPage({ role: 'tester', url: '/test-queue' }, async page => { await assignSelfAndNavigateToRun(page, { - testPlanSectionButtonSelector: 'button#disclosure-btn-alert-0', + testPlanSectionButtonSelector: 'button#disclosure-btn-apg\\/alert-0', testPlanTableSelector: 'table[aria-label="Reports for Alert Example V22.04.14 in draft phase"]' }); @@ -691,7 +691,7 @@ describe('Test Run when signed in as tester', () => { }; await getPage({ role: 'tester', url: '/test-queue' }, async page => { await assignSelfAndNavigateToRun(page, { - testPlanSectionButtonSelector: 'button#disclosure-btn-alert-0', + testPlanSectionButtonSelector: 'button#disclosure-btn-apg\\/alert-0', testPlanTableSelector: 'table[aria-label="Reports for Alert Example V22.04.14 in draft phase"]' }); @@ -797,9 +797,9 @@ describe('Test Run when signed in as tester', () => { await page.goto(`${baseUrl}/test-queue`); await assignSelfAndNavigateToRun(page, { testPlanSectionButtonSelector: - 'button#disclosure-btn-horizontal-slider-0', + 'button#disclosure-btn-apg\\/horizontal-slider-0', testPlanTableSelector: - 'table[aria-label="Reports for Color Viewer Slider V24.12.04 in draft phase"]' + 'table[aria-label="Reports for Color Viewer Slider V25.10.16 in draft phase"]' }); await handlePageSubmit(page, { expectConflicts: false }); } @@ -828,9 +828,10 @@ describe('Test Run when signed in as tester', () => { it('enforces read-only and shows on-hold modal when report is On hold', async () => { // Ensure the report is On hold as admin first, then switch to tester in same page await getPage({ role: 'admin', url: '/test-queue' }, async page => { - const sectionButtonSelector = 'button#disclosure-btn-modal-dialog-0'; + const sectionButtonSelector = + 'button#disclosure-btn-apg\\/modal-dialog-0'; const tableSelector = - 'table[aria-label="Reports for Modal Dialog Example V24.06.07 in draft phase"]'; + 'table[aria-label="Reports for Modal Dialog Example V25.10.16 in draft phase"]'; await page.waitForSelector(sectionButtonSelector); await page.click(sectionButtonSelector); diff --git a/client/tests/e2e/snapshots/saved/_account_settings.html b/client/tests/e2e/snapshots/saved/_account_settings.html index c260009b8..c97ce0dfc 100644 --- a/client/tests/e2e/snapshots/saved/_account_settings.html +++ b/client/tests/e2e/snapshots/saved/_account_settings.html @@ -102,7 +102,7 @@

Admin Actions

-

Date of latest test plan version: November 4, 2025 02:14 UTC

+

Date of latest test plan version: November 6, 2025 15:43 UTC

diff --git a/client/tests/e2e/snapshots/saved/_candidate-test-plan_24_1#summary-failures.html b/client/tests/e2e/snapshots/saved/_candidate-test-plan_24_1#summary-failures.html index 401e840ac..8726a383c 100644 --- a/client/tests/e2e/snapshots/saved/_candidate-test-plan_24_1#summary-failures.html +++ b/client/tests/e2e/snapshots/saved/_candidate-test-plan_24_1#summary-failures.html @@ -592,7 +592,7 @@

Test Review Options

Test Review Options Test Review Options Test Review Options +
@@ -393,7 +394,7 @@

Test Plans Status Summary

data-testid="filter-all" aria-pressed="true" class="filter-button btn active btn-secondary"> - All Plans (40) + All Plans (41)
  • @@ -402,7 +403,7 @@

    Test Plans Status Summary

    data-testid="filter-rd" aria-pressed="false" class="filter-button btn btn-secondary"> - R&D Complete (36) + R&D Complete (37)
  • @@ -436,7 +437,7 @@

    Test Plans Status Summary

    @@ -513,7 +514,7 @@

    Test Plans Status Summary

    @@ -731,7 +732,7 @@

    Test Plans Status Summary

    @@ -772,7 +773,7 @@

    Test Plans Status Summary

    V24.06.07V25.10.16Test Plans Status Summary >2 Open Issues from 2 ATsTest Plans Status Summary @@ -968,7 +972,7 @@

    Test Plans Status Summary

    V24.12.04V25.10.16Test Plans Status Summary @@ -1033,7 +1037,7 @@

    Test Plans Status Summary

    V25.11.02V25.11.03 @@ -1181,7 +1185,7 @@

    Test Plans Status Summary

    @@ -1221,7 +1225,7 @@

    Test Plans Status Summary

    V24.10.22V25.10.16 @@ -1487,7 +1495,7 @@

    Test Plans Status Summary

    @@ -1500,7 +1508,7 @@

    Test Plans Status Summary

    @@ -1653,7 +1661,7 @@

    Test Plans Status Summary

    @@ -1707,7 +1715,7 @@

    Test Plans Status Summary

    @@ -1761,7 +1769,7 @@

    Test Plans Status Summary

    @@ -1815,7 +1823,7 @@

    Test Plans Status Summary

    @@ -1828,7 +1836,7 @@

    Test Plans Status Summary

    @@ -1980,7 +1988,7 @@

    Test Plans Status Summary

    @@ -2086,7 +2094,7 @@

    Test Plans Status Summary

    @@ -2140,7 +2148,7 @@

    Test Plans Status Summary

    @@ -2153,7 +2161,7 @@

    Test Plans Status Summary

    @@ -2316,7 +2324,7 @@

    Test Plans Status Summary

    @@ -2422,7 +2430,7 @@

    Test Plans Status Summary

    @@ -2476,7 +2484,7 @@

    Test Plans Status Summary

    @@ -2530,7 +2539,7 @@

    Test Plans Status Summary

    @@ -2584,7 +2593,7 @@

    Test Plans Status Summary

    @@ -2679,7 +2688,9 @@

    Test Plans Status Summary

    @@ -2744,7 +2755,7 @@

    Test Plans Status Summary

    @@ -2798,7 +2809,7 @@

    Test Plans Status Summary

    @@ -2852,7 +2863,7 @@

    Test Plans Status Summary

    @@ -2906,7 +2917,7 @@

    Test Plans Status Summary

    @@ -2960,7 +2971,7 @@

    Test Plans Status Summary

    + + + + + + + + + ; - const detailLink = `/aria-html-feature/${row.atId}/${row.browserId}/${key}`; + const detailLink = `/aria-html-feature/${row.atId}/${row.browserId}/${key}/${row.type}`; return (
    Action Menu Button Example Using aria-activedescendantTest Plans Status Summary V25.10.26V25.11.03Review Completed Sep 22, 2024Test Plans Status Summary V25.10.26V25.11.03Review Completed Sep 23, 2024Test Plans Status Summary V25.10.26V25.11.03Test Plans Status Summary
    - Checkbox Example (Tri State)
    - Modal Dialog Example
    - Alert Example + Alert Example
    @@ -879,7 +883,7 @@

    Test Plans Status Summary

    V25.11.02V25.11.03
    - Color Viewer Slider
    - Command Button Example
    - Select Only Combobox Example
    - Toggle Button
    - Accordion + Accordion
    @@ -1284,7 +1290,7 @@

    Test Plans Status Summary

    R&D -

    Complete Jul 14, 2025

    +

    Complete Oct 16, 2025

    @@ -1305,7 +1311,7 @@

    Test Plans Status Summary

    V25.07.14V25.10.16
    - Action Menu Button Example Using element.focus()Test Plans Status Summary
    R&D -

    Complete Feb 13, 2025

    +

    Complete Oct 16, 2025

    @@ -1361,7 +1367,7 @@

    Test Plans Status Summary

    V25.02.13V25.10.16
    - Banner Landmark + Banner Landmark
    @@ -1433,7 +1441,7 @@

    Test Plans Status Summary

    - Breadcrumb Example
    - Checkbox Example (Two State)
    R&D -

    Complete Oct 20, 2025

    +

    Complete Nov 3, 2025

    @@ -1521,7 +1529,7 @@

    Test Plans Status Summary

    V25.10.20V25.11.03
    Combobox with Both List and Inline Autocomplete ExampleTest Plans Status Summary
    - Complementary Landmark
    - Contentinfo Landmark
    - Data Grid Example 1: Minimal Data Grid
    - Date Picker Spin Button Example
    - Disclosure Navigation Menu Example
    R&D -

    Complete Oct 27, 2025

    +

    Complete Nov 3, 2025

    @@ -1849,7 +1857,7 @@

    Test Plans Status Summary

    V25.10.27V25.11.03
    - Disclosure of Answers to Frequently Asked Questions ExampleTest Plans Status Summary
    R&D -

    Complete Nov 4, 2025

    +

    Complete Nov 3, 2025

    @@ -1906,7 +1914,7 @@

    Test Plans Status Summary

    V25.11.04V25.11.03
    - Editor Menubar Example
    - Form Landmark + Form Landmark
    @@ -2032,7 +2040,7 @@

    Test Plans Status Summary

    - Horizontal Multi-Thumb Slider
    - Link Example 1 (span element with text content)
    - Link Example 2 (img element with alt attribute)
    R&D -

    Complete Jan 23, 2025

    +

    Complete Oct 16, 2025

    @@ -2174,7 +2182,7 @@

    Test Plans Status Summary

    V25.01.23V25.10.16
    - Link Example 3 (CSS :before content property on a span element)Test Plans Status Summary
    R&D -

    Complete Jan 23, 2025

    +

    Complete Oct 16, 2025

    @@ -2231,7 +2239,7 @@

    Test Plans Status Summary

    V25.01.23V25.10.16
    - Main Landmark + Main Landmark
    @@ -2303,7 +2311,7 @@

    Test Plans Status Summary

    - Media Seek Slider
    R&D -

    Complete Mar 14, 2025

    +

    Complete Oct 16, 2025

    @@ -2337,7 +2345,7 @@

    Test Plans Status Summary

    V25.03.14V25.10.16
    - Meter + Meter
    @@ -2409,7 +2417,7 @@

    Test Plans Status Summary

    - Navigation Menu Button
    R&D -

    Complete Feb 13, 2025

    +

    Complete Oct 16, 2025

    @@ -2443,7 +2451,7 @@

    Test Plans Status Summary

    V25.02.13V25.10.16
    - Radio Group Example Using Roving tabindex
    R&D -

    Complete Oct 27, 2025

    +

    Complete Nov 3, 2025

    @@ -2497,7 +2505,7 @@

    Test Plans Status Summary

    V25.10.27V25.11.03
    - Radio Group Example Using aria-activedescendant
    R&D -

    Complete Oct 26, 2025

    +

    Complete Nov 3, 2025

    @@ -2551,7 +2560,7 @@

    Test Plans Status Summary

    V25.10.26V25.11.03
    - Rating Radio Group
    R&D -

    Complete Apr 22, 2025

    +

    Complete Oct 16, 2025

    @@ -2605,7 +2614,7 @@

    Test Plans Status Summary

    V25.04.22V25.10.16
    - Rating Slider
    - Switch Example + Switch Example
    @@ -2690,7 +2701,7 @@

    Test Plans Status Summary

    R&D -

    Complete Oct 1, 2025

    +

    Complete Oct 16, 2025

    @@ -2711,7 +2722,7 @@

    Test Plans Status Summary

    V25.10.01V25.10.16
    - Switch Example Using HTML Button
    R&D -

    Complete Oct 1, 2025

    +

    Complete Oct 16, 2025

    @@ -2765,7 +2776,7 @@

    Test Plans Status Summary

    V25.10.01V25.10.16
    - Switch Example Using HTML Checkbox Input
    R&D -

    Complete Oct 6, 2025

    +

    Complete Oct 16, 2025

    @@ -2819,7 +2830,7 @@

    Test Plans Status Summary

    V25.10.06V25.10.16
    - Tabs with Automatic Activation
    R&D -

    Complete Aug 21, 2025

    +

    Complete Oct 16, 2025

    @@ -2873,7 +2884,7 @@

    Test Plans Status Summary

    V25.08.21V25.10.16
    - Tabs with Manual Activation
    R&D -

    Complete Oct 20, 2025

    +

    Complete Nov 3, 2025

    @@ -2927,7 +2938,7 @@

    Test Plans Status Summary

    V25.10.20V25.11.03
    - Vertical Temperature Slider
    R&D -

    Complete Jul 24, 2025

    +

    Complete Oct 16, 2025

    @@ -2981,7 +2992,61 @@

    Test Plans Status Summary

    V25.07.24V25.10.16 + +
    + Not Started + + Not Started + None Yet
    + aria-required on a Text Input + +
    + JAWS, NVDA and VoiceOver for macOS +
    +
    +
    + R&D +

    Complete Nov 6, 2025

    +
    +
    +
    + V25.11.06

    Test Options

    After 'Down Arrow' Raise an issue for 'Down Arrow'After 'B' Raise an issue for 'B'After 'F' Raise an issue for 'F'After 'Tab' Raise an issue for 'Tab'Test Options -

    Alert Example

    +

    Alert Example

    -

    +

    Color Viewer Slider

    @@ -855,15 +855,17 @@

    -

    +

    + Modal Dialog Example +

    @@ -1103,10 +1105,10 @@

  • Phase: Deprecated
  • Version: V22.05.04 - (View all versions of this test plan)
  • @@ -174,7 +174,7 @@

    GitHub Issues (0 open, 0 closed)

    Raise an Issue { +app.get('/reports/:testPlanDirectory*', async (req, res) => { // In the instance where an editor doesn't want to display a certain title // as it has defined when importing into the ARIA-AT database for being too // verbose, etc. eg. `Link Example 1 (span element with text content)` - // Usage: https://aria-at.w3.org/embed/reports/command-button?title=Link+Example+(span+element+with+text+content) + // Usage: https://aria-at.w3.org/embed/reports/apg/command-button?title=Link+Example+(span+element+with+text+content) const queryTitle = req.query.title; const testPlanDirectory = req.params.testPlanDirectory; const host = req.headers.host; diff --git a/server/migrations/20251103214245-update-directory-names-apg.js b/server/migrations/20251103214245-update-directory-names-apg.js new file mode 100644 index 000000000..87fbf66d0 --- /dev/null +++ b/server/migrations/20251103214245-update-directory-names-apg.js @@ -0,0 +1,32 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface) { + await queryInterface.sequelize.query( + `UPDATE "TestPlanVersion" + SET directory = 'apg/' || directory + WHERE directory IS NOT NULL AND directory NOT LIKE 'apg/%'` + ); + + await queryInterface.sequelize.query( + `UPDATE "TestPlan" + SET directory = 'apg/' || directory + WHERE directory IS NOT NULL AND directory NOT LIKE 'apg/%'` + ); + }, + + async down(queryInterface) { + await queryInterface.sequelize.query( + `UPDATE "TestPlanVersion" + SET directory = substring(directory FROM 5) + WHERE directory IS NOT NULL AND directory LIKE 'apg/%'` + ); + + await queryInterface.sequelize.query( + `UPDATE "TestPlan" + SET directory = substring(directory FROM 5) + WHERE directory IS NOT NULL AND directory LIKE 'apg/%'` + ); + } +}; diff --git a/server/resolvers/TestPlanReport/issuesResolver.js b/server/resolvers/TestPlanReport/issuesResolver.js index 612e44879..d66f10aa8 100644 --- a/server/resolvers/TestPlanReport/issuesResolver.js +++ b/server/resolvers/TestPlanReport/issuesResolver.js @@ -32,7 +32,11 @@ const getIssues = async ({ testPlanReport, testPlan, context }) => { return ( hiddenIssueMetadata && - hiddenIssueMetadata.testPlanDirectory === testPlanVersion.directory && + // TODO: Support a more robust back-support search + (hiddenIssueMetadata.testPlanDirectory === + testPlanVersion.directory || + `apg/${hiddenIssueMetadata.testPlanDirectory}` === + testPlanVersion.directory) && hiddenIssueMetadata.versionString === testPlanVersion.versionString && hiddenIssueMetadata.atName === at.name && (!hiddenIssueMetadata.browserName || @@ -41,7 +45,10 @@ const getIssues = async ({ testPlanReport, testPlan, context }) => { } else if (testPlan) { return ( hiddenIssueMetadata && - hiddenIssueMetadata.testPlanDirectory === testPlan.directory + // TODO: Support a more robust back-support search + (hiddenIssueMetadata.testPlanDirectory === testPlan.directory || + `apg/${hiddenIssueMetadata.testPlanDirectory}` === + testPlan.directory) ); } }) diff --git a/server/scripts/import-tests/gitOperations.js b/server/scripts/import-tests/gitOperations.js index dbd8b1a2e..2dab90afc 100644 --- a/server/scripts/import-tests/gitOperations.js +++ b/server/scripts/import-tests/gitOperations.js @@ -3,7 +3,7 @@ const spawn = require('cross-spawn'); const ariaAtRepo = 'https://github.com/w3c/aria-at.git'; -const ariaAtDefaultBranch = 'master'; +const ariaAtDefaultBranch = 'tests-sub-folder-support-example'; /** * Executes a git command and returns its output. diff --git a/server/scripts/import-tests/testPlanVersionOperations.js b/server/scripts/import-tests/testPlanVersionOperations.js index 168c05426..5c2397b4c 100644 --- a/server/scripts/import-tests/testPlanVersionOperations.js +++ b/server/scripts/import-tests/testPlanVersionOperations.js @@ -112,39 +112,79 @@ const buildTestsAndCreateTestPlanVersions = async ( await updateAtsJson({ ats, supportAts: support.ats }); } - for (const directory of fse.readdirSync(localBuiltTestsDirectory)) { - if (directory === 'resources') continue; - - const builtDirectoryPath = path.join(localBuiltTestsDirectory, directory); - if (!fse.statSync(builtDirectoryPath).isDirectory()) continue; - const sourceDirectoryPath = path.join(testsDirectory, directory); - - // https://github.com/w3c/aria-at/commit/9d73d6bb274b3fe75b9a8825e020c0546a33a162 - // This is the date of the last commit before the build folder removal. - // Meant to support backward compatability until the existing tests can - // be updated to the current structure - const buildRemovalDate = new Date('2022-03-10 18:08:36.000000 +00:00'); - const useBuildInAppAppUrlPath = - gitCommitDate.getTime() <= buildRemovalDate.getTime(); + // https://github.com/w3c/aria-at/commit/9d73d6bb274b3fe75b9a8825e020c0546a33a162 + // This is the date of the last commit before the build folder removal. + // Meant to support backward compatability until the existing tests can + // be updated to the current structure + const buildRemovalDate = new Date('2022-03-10 18:08:36.000000 +00:00'); + const useBuildInAppAppUrlPath = + gitCommitDate.getTime() <= buildRemovalDate.getTime(); + + /** + * Recursively processes test directories, checking for references.csv + * to determine if a directory is ready to be processed. + * @param {string} relativeDirectoryPath - Relative path from tests root (e.g., "apg/alert") + * @returns {Promise} + */ + const processTestDirectoriesRecursively = async relativeDirectoryPath => { + const builtDirectoryPath = relativeDirectoryPath + ? path.join(localBuiltTestsDirectory, relativeDirectoryPath) + : localBuiltTestsDirectory; + const sourceDirectoryPath = relativeDirectoryPath + ? path.join(testsDirectory, relativeDirectoryPath) + : testsDirectory; if ( !( fse.existsSync(sourceDirectoryPath) && + fse.existsSync(builtDirectoryPath) && fse.statSync(builtDirectoryPath).isDirectory() ) ) { - continue; + return; } - await processTestPlanVersion({ - directory, - builtDirectoryPath, + // Check if this directory has a references.csv (indicates it's a test directory) + const referencesCsvPath = path.join( sourceDirectoryPath, - useBuildInAppAppUrlPath, - ats, - transaction - }); - } + 'data', + 'references.csv' + ); + + if (fse.existsSync(referencesCsvPath)) { + // This is a test directory, process it + await processTestPlanVersion({ + // The expectation going forward is that tests will be within + // subfolders coming from aria-at + // If none exists, then most likely this is an older test which came + // directly from the APG + directory: relativeDirectoryPath.includes('/') + ? relativeDirectoryPath + : `apg/${relativeDirectoryPath}`, + builtDirectoryPath, + sourceDirectoryPath, + useBuildInAppAppUrlPath, + ats, + transaction + }); + } else { + // This is a subfolder, recursively search deeper + const entries = fse.readdirSync(builtDirectoryPath); + for (const entry of entries) { + if (entry === 'resources') continue; + const entryBuiltPath = path.join(builtDirectoryPath, entry); + if (!fse.statSync(entryBuiltPath).isDirectory()) continue; + + const nextRelativePath = relativeDirectoryPath + ? path.join(relativeDirectoryPath, entry) + : entry; + await processTestDirectoriesRecursively(nextRelativePath); + } + } + }; + + // Start processing from the root of the tests directory + await processTestDirectoriesRecursively(''); // To ensure build folder is clean when multiple commits are being processed // to prevent `EPERM` errors @@ -363,7 +403,10 @@ async function createAssertionsForTestPlanVersion({ * Imports the harness files from the test directory to the client resources. */ const importHarness = () => { - const sourceFolder = path.resolve(`${testsDirectory}/resources`); + let sourceFolder = path.resolve(`${gitCloneDirectory}/resources`); + sourceFolder = fse.existsSync(sourceFolder) + ? sourceFolder + : path.resolve(`${testsDirectory}/resources`); const targetFolder = path.resolve( __dirname, '../../../', @@ -465,9 +508,12 @@ const flattenObject = (obj, parentKey = '') => { */ const updateJsons = async () => { // Commands path info for v1 format - const keysMjsPath = pathToFileURL( - path.join(testsDirectory, 'resources', 'keys.mjs') + let keysMjsPath = pathToFileURL( + path.join(gitCloneDirectory, 'resources', 'keys.mjs') ); + keysMjsPath = fse.existsSync(keysMjsPath) + ? keysMjsPath + : pathToFileURL(path.join(testsDirectory, 'resources', 'keys.mjs')); const commands = Object.entries(await import(keysMjsPath)).map( ([id, text]) => ({ id, text }) ); diff --git a/server/tests/integration/dataManagement.test.js b/server/tests/integration/dataManagement.test.js index 29ce6ed1d..3089ce9f4 100644 --- a/server/tests/integration/dataManagement.test.js +++ b/server/tests/integration/dataManagement.test.js @@ -403,7 +403,7 @@ const getTestableModalDialogVersions = async transaction => { // https://github.com/w3c/aria-at/compare/5fe7afd82fe51c185b8661276105190a59d47322..d0e16b42179de6f6c070da2310e99de837c71215 // Modal Dialog was updated to show have differences between several NVDA and JAWS tests // There are no changes for the VO tests - const directory = 'modal-dialog'; + const directory = 'apg/modal-dialog'; const expectedOldVersionPhase = 'CANDIDATE'; const expectedNewVersionPhase = 'DRAFT'; const oldVersionSha = '5fe7afd82fe51c185b8661276105190a59d47322'; @@ -426,7 +426,7 @@ const getTestableCommandButtonVersions = async transaction => { // Based on https://github.com/w3c/aria-at/compare/d9a19f8...565a87b#diff-4e3dcd0a202f268ebec2316344f136c3a83d6e03b3f726775cb46c57322ff3a0, // only 'navForwardsToButton' and 'navBackToButton' tests were affected. The individual tests for // 'reqInfoAboutButton' should still match. - const directory = 'command-button'; + const directory = 'apg/command-button'; const expectedOldVersionPhase = 'DRAFT'; const oldVersionSha = 'd9a19f815d0f21194023b1c5919eb3b04d5c1ab7'; const newVersionSha = '565a87b4111acebdb883d187b581e82c42a73844'; diff --git a/server/tests/integration/embed.test.js b/server/tests/integration/embed.test.js index 0a848b425..ea157354c 100644 --- a/server/tests/integration/embed.test.js +++ b/server/tests/integration/embed.test.js @@ -28,12 +28,14 @@ describe('embed', () => { // Load the iframe, twice, one with a normal load and a second time from // the cache const initialLoadTimeStart = Number(new Date()); - const res = await sessionAgent.get('/embed/reports/checkbox-tri-state'); + const res = await sessionAgent.get('/embed/reports/apg/checkbox-tri-state'); const initialLoadTimeEnd = Number(new Date()); const initialLoadTime = initialLoadTimeEnd - initialLoadTimeStart; const cachedTimeStart = Number(new Date()); - const res2 = await sessionAgent.get('/embed/reports/checkbox-tri-state'); + const res2 = await sessionAgent.get( + '/embed/reports/apg/checkbox-tri-state' + ); const cachedTimeEnd = Number(new Date()); const cachedTime = cachedTimeEnd - cachedTimeStart; @@ -73,7 +75,7 @@ describe('embed', () => { ); expect(copyEmbedButton).toBeTruthy(); expect(copyEmbedButtonOnClick).toMatch( - /announceCopied\('https?:\/\/[\w.:]+\/embed\/reports\/checkbox-tri-state'\)/ + /announceCopied\('https?:\/\/[\w.:]+\/embed\/reports\/apg\/checkbox-tri-state'\)/ ); expect(cellWithData).toBeTruthy(); }); diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index 425db926d..fcf67e70d 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -515,7 +515,7 @@ describe('graphql', () => { } } } - testPlan(id: "checkbox") { + testPlan(id: "apg/checkbox") { __typename id directory From f5d92fe3fc9d1692af0e3ec5ec86ca9587980696 Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Thu, 6 Nov 2025 17:23:46 -0500 Subject: [PATCH 5/6] fix: Support dynamic renames of `aria-at/support.json/references` properties (#1617) * Update import-tests script to save the latest support.json on the server. Use the support.json to mutate references when needed for the reference linkText and value * Fix noisy autoformat * Update snapshots * Fix e2e selector * Fix tests * Change how support.json is imported * Remove unnecessary commented block * fix: ARIA and HTML feature reports are errantly combined and incorrectly named in the first column of the top-level report page (#1618) * Use reference.rawValue for ARIA and HTML features table column * Update links to feature pages and download urls to be reference type specific * Update snapshots * Fix tests * Fix tests * Fix tests * Fix tests * Update snapshots --- client/components/App/App.jsx | 5 +- .../Reports/AriaHtmlFeatureDetailReport.jsx | 19 +- .../Reports/FeatureSupportTable.jsx | 10 +- client/components/Reports/Reports.jsx | 2 +- client/components/Reports/queries.js | 11 +- client/routes/index.js | 5 + client/tests/e2e/Reports.e2e.test.js | 2 +- .../snapshots/saved/_account_settings.html | 2 +- .../e2e/snapshots/saved/_data-management.html | 151 ++--- .../tests/e2e/snapshots/saved/_reports.html | 92 +-- .../e2e/snapshots/saved/_test-queue.html | 12 +- server/controllers/MetricsController.js | 5 +- server/graphql-schema.js | 15 + ...5142314-fix-references-linkTextAndValue.js | 121 ++++ server/models/services/TestsService.js | 41 +- .../ariaHtmlFeatureDetailReportResolver.js | 3 +- server/resources/support.json | 601 ++++++++++++++++++ server/scripts/import-tests/gitOperations.js | 2 +- .../import-tests/testPlanVersionOperations.js | 87 ++- .../services/extractFeatureAssertionRows.js | 2 + server/tests/integration/graphql.test.js | 8 + shared/getMetrics.js | 2 + shared/tests/getMetrics.test.js | 20 + 23 files changed, 998 insertions(+), 220 deletions(-) create mode 100644 server/migrations/20251105142314-fix-references-linkTextAndValue.js create mode 100644 server/resources/support.json diff --git a/client/components/App/App.jsx b/client/components/App/App.jsx index 8233d7a35..3b91fe3f6 100644 --- a/client/components/App/App.jsx +++ b/client/components/App/App.jsx @@ -71,7 +71,10 @@ const App = () => { AT Interoperability Reports diff --git a/client/components/Reports/AriaHtmlFeatureDetailReport.jsx b/client/components/Reports/AriaHtmlFeatureDetailReport.jsx index 1eb37979f..ec6a240f0 100644 --- a/client/components/Reports/AriaHtmlFeatureDetailReport.jsx +++ b/client/components/Reports/AriaHtmlFeatureDetailReport.jsx @@ -10,12 +10,12 @@ import PageStatus from '../common/PageStatus'; import { ARIA_HTML_FEATURE_DETAIL_REPORT_QUERY } from './queries'; const AriaHtmlFeatureDetailReport = () => { - const { atId, browserId, refId } = useParams(); + const { atId, browserId, refId, refType } = useParams(); const { loading, data, error } = useQuery( ARIA_HTML_FEATURE_DETAIL_REPORT_QUERY, { - variables: { refId, atId, browserId }, + variables: { refId, refType, atId, browserId }, fetchPolicy: 'cache-and-network' } ); @@ -57,6 +57,12 @@ const AriaHtmlFeatureDetailReport = () => { return nameA.localeCompare(nameB); }); + let downloadURI = `/api/metrics/aria-html-features/details.csv?refId=${refId}&at=${encodeURIComponent( + at.name + )}&browser=${encodeURIComponent(browser.name)}`; + if (refType) + downloadURI = `${downloadURI}&refType=${encodeURIComponent(refType)}`; + return ( <> @@ -135,14 +141,7 @@ const AriaHtmlFeatureDetailReport = () => {
    - diff --git a/client/components/Reports/FeatureSupportTable.jsx b/client/components/Reports/FeatureSupportTable.jsx index dd4570e8c..647b2fc98 100644 --- a/client/components/Reports/FeatureSupportTable.jsx +++ b/client/components/Reports/FeatureSupportTable.jsx @@ -15,11 +15,11 @@ const FeatureSupportTable = ({ featureData, featureLabel }) => { const dataByFeature = {}; const links = {}; for (const row of featureData) { - if (!dataByFeature[row.refId]) { - dataByFeature[row.refId] = {}; + if (!dataByFeature[row.rawValue]) { + dataByFeature[row.rawValue] = {}; } - links[row.refId] = { href: row.value, text: row.linkText }; - dataByFeature[row.refId][columnName(row)] = row; + links[row.rawValue] = { href: row.value, text: row.linkText }; + dataByFeature[row.rawValue][columnName(row)] = row; } const keys = Object.keys(dataByFeature).sort(); @@ -55,7 +55,7 @@ const FeatureSupportTable = ({ featureData, featureLabel }) => { if (!row) return
    {none} {

    Assistive Technology Interoperability Reports

    -

    Loading...

    +

    Loading ...

    ); diff --git a/client/components/Reports/queries.js b/client/components/Reports/queries.js index a1eab35d5..ad7ab13ef 100644 --- a/client/components/Reports/queries.js +++ b/client/components/Reports/queries.js @@ -35,7 +35,6 @@ export const REPORTS_PAGE_QUERY = gql` } } } - ariaHtmlFeaturesMetrics { ariaFeaturesPassedCount ariaFeaturesCount @@ -49,7 +48,9 @@ export const REPORTS_PAGE_QUERY = gql` refId type linkText + rawLinkText value + rawValue total passed failed @@ -61,7 +62,9 @@ export const REPORTS_PAGE_QUERY = gql` refId type linkText + rawLinkText value + rawValue total passed failed @@ -73,7 +76,9 @@ export const REPORTS_PAGE_QUERY = gql` refId type linkText + rawLinkText value + rawValue total passed failed @@ -89,7 +94,9 @@ export const REPORTS_PAGE_QUERY = gql` refId type linkText + rawLinkText value + rawValue total passed failed @@ -186,11 +193,13 @@ export const ARIA_HTML_FEATURE_DETAIL_REPORT_QUERY = gql` ${BROWSER_FIELDS} query AriaHtmlFeatureDetailReport( $refId: String! + $refType: String $atId: ID! $browserId: ID! ) { ariaHtmlFeatureDetailReport( refId: $refId + refType: $refType atId: $atId browserId: $browserId ) { diff --git a/client/routes/index.js b/client/routes/index.js index 7f0a747fb..afb3c3705 100644 --- a/client/routes/index.js +++ b/client/routes/index.js @@ -63,6 +63,11 @@ export default () => ( path="/aria-html-feature/:atId/:browserId/:refId" element={} /> + } + /> { 'h1 ::-p-text(VoiceOver for macOS and Chrome Support for)' ); await page.waitForSelector( - 'a ::-p-text(button Accessibility API Mapping)' + 'a ::-p-text(button HTML-AAM Specification)' ); await page.waitForSelector('nav[aria-label="Breadcrumb"]'); diff --git a/client/tests/e2e/snapshots/saved/_account_settings.html b/client/tests/e2e/snapshots/saved/_account_settings.html index c97ce0dfc..7336eacb3 100644 --- a/client/tests/e2e/snapshots/saved/_account_settings.html +++ b/client/tests/e2e/snapshots/saved/_account_settings.html @@ -102,7 +102,7 @@

    Admin Actions

    -

    Date of latest test plan version: November 6, 2025 15:43 UTC

    +

    Date of latest test plan version: November 6, 2025 21:57 UTC

    diff --git a/client/tests/e2e/snapshots/saved/_data-management.html b/client/tests/e2e/snapshots/saved/_data-management.html index 701434526..e2abebf7f 100644 --- a/client/tests/e2e/snapshots/saved/_data-management.html +++ b/client/tests/e2e/snapshots/saved/_data-management.html @@ -294,7 +294,6 @@

    -
    @@ -394,7 +393,7 @@

    Test Plans Status Summary

    data-testid="filter-all" aria-pressed="true" class="filter-button btn active btn-secondary"> - All Plans (41) + All Plans (40)
  • @@ -403,7 +402,7 @@

    Test Plans Status Summary

    data-testid="filter-rd" aria-pressed="false" class="filter-button btn btn-secondary"> - R&D Complete (37) + R&D Complete (36)
  • @@ -437,7 +436,7 @@

    Test Plans Status Summary

    @@ -553,7 +552,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06Review Completed Sep 22, 2024Test Plans Status SummaryV25.11.03V25.11.06Review Completed Sep 23, 2024Test Plans Status SummaryV25.11.03V25.11.06Test Plans Status Summary V25.10.16V25.11.06Test Plans Status Summary V25.11.03V25.11.06 - - - - - - - - -
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -1311,7 +1310,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -1367,7 +1366,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -1529,7 +1528,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -1857,7 +1856,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -1914,7 +1913,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -2128,7 +2127,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2182,7 +2181,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2239,7 +2238,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2345,7 +2344,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2451,7 +2450,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -2505,7 +2504,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -2560,7 +2559,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2614,7 +2613,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2722,7 +2721,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2776,7 +2775,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2830,7 +2829,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Oct 16, 2025

    +

    Complete Nov 6, 2025

    @@ -2884,7 +2883,7 @@

    Test Plans Status Summary

    V25.10.16V25.11.06
    R&D -

    Complete Nov 3, 2025

    +

    Complete Nov 6, 2025

    @@ -2938,7 +2937,7 @@

    Test Plans Status Summary

    V25.11.03V25.11.06
    -
    - R&D -

    Complete Oct 16, 2025

    -
    -
    -
    - V25.10.16 -
    -
    - Not Started - - Not Started - None Yet
    - aria-required on a Text Input - -
    - JAWS, NVDA and VoiceOver for macOS -
    -
    R&D @@ -3031,7 +2976,7 @@

    Test Plans Status Summary

    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    ARIA Feature Support Levels
    HTML Feature Support Levels
    HTML Feature Support Levels
    HTML Feature Support Levels
    HTML Feature Support Levels
    HTML Feature Support Levels
    HTML Feature Support Levels
    V25.10.16V25.11.06 Draft View tests in V25.10.16View tests in V25.11.06
    @@ -881,7 +881,7 @@

    V25.10.16V25.11.06 Draft View tests in V25.10.16View tests in V25.11.06

    diff --git a/server/controllers/MetricsController.js b/server/controllers/MetricsController.js index f396b92d5..863d8fe2c 100644 --- a/server/controllers/MetricsController.js +++ b/server/controllers/MetricsController.js @@ -102,7 +102,7 @@ const downloadARIAHtmlFeaturesCSV = async (req, res, next) => { const downloadARIAHtmlFeaturesDetailsCSV = async (req, res, next) => { try { - const { at, browser, refId } = req.query; + const { at, browser, refId, refType } = req.query; if (!refId) { return res.status(400).json({ @@ -136,7 +136,8 @@ const downloadARIAHtmlFeaturesDetailsCSV = async (req, res, next) => { populatedTestPlanReport, report.id, finalizedTestResults, - refId + refId, + refType ); allRows.push(...extractedRows); diff --git a/server/graphql-schema.js b/server/graphql-schema.js index 89b2c2541..05322774b 100644 --- a/server/graphql-schema.js +++ b/server/graphql-schema.js @@ -700,17 +700,29 @@ const graphqlSchema = gql` """ The value of the reference. This could be link, an identifier such as an email or just text. + It's returned mutated according to these reference calculations: + https://github.com/w3c/aria-at/wiki/Test-Format-Definition-V2#reference-link-calculation """ value: String! """ + The non-mutated value. + """ + rawValue: String! + """ The type of the reference, such as "htmlAam", "aria", "metadata", etc. """ type: String """ The link text of the reference if value is, or will be transformed into a link. + It's returned mutated according to these reference calculations: + https://github.com/w3c/aria-at/wiki/Test-Format-Definition-V2#reference-link-calculation """ linkText: String + """ + The non-mutated linkText. + """ + rawLinkText: String } """ @@ -1717,6 +1729,7 @@ const graphqlSchema = gql` """ ariaHtmlFeatureDetailReport( refId: String! + refType: String atId: ID! browserId: ID! ): ARIAHTMLFeatureDetailReport @@ -2090,7 +2103,9 @@ const graphqlSchema = gql` refId: String! type: String! linkText: String! + rawLinkText: String! value: String! + rawValue: String! total: Int! passed: Int! failed: Int! diff --git a/server/migrations/20251105142314-fix-references-linkTextAndValue.js b/server/migrations/20251105142314-fix-references-linkTextAndValue.js new file mode 100644 index 000000000..66da46d5e --- /dev/null +++ b/server/migrations/20251105142314-fix-references-linkTextAndValue.js @@ -0,0 +1,121 @@ +'use strict'; + +const { regenerateResultsAndRecalculateHashes, dumpTable } = require('./utils'); +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + /* prettier-ignore */ + const references = { + /* eslint-disable */ + "accordion": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Accordion", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-5-5_135654/accordion.html", "linkText": "Test Case Page for Accordion Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/accordion/", "linkText": "APG Pattern: Accordion" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/accordion/examples/accordion/", "linkText": "APG Example: Accordion Example" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-required": { "refId": "aria-required", "type": "aria", "value": "aria-required", "linkText": "aria-required" }, "region": { "refId": "region", "type": "aria", "value": "region", "linkText": "region" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" }, "heading": { "refId": "heading", "type": "htmlAam", "value": "heading", "linkText": "heading" }, "inputTypeText": { "refId": "inputTypeText", "type": "htmlAam", "value": "inputTypeText", "linkText": "inputTypeText" } }, + "alert": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Alert Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-8_144013/alert.html", "linkText": "Test Case Page for Alert Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/alert/", "linkText": "APG Pattern: Alert" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/alert/examples/alert/", "linkText": "APG Example: Alert" }, "alert": { "refId": "alert", "type": "aria", "value": "alert", "linkText": "alert" } }, + "checkbox": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Checkbox Example (Two State)", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-10-2_121011/checkbox.html", "linkText": "Test Case Page for Checkbox Example (Two State)" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/", "linkText": "APG Pattern: Checkbox" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/examples/checkbox/", "linkText": "APG Example: Checkbox Example (Two State)" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "checkbox": { "refId": "checkbox", "type": "aria", "value": "Checkbox", "linkText": "checkbox" }, "group": { "refId": "group", "type": "aria", "value": "group", "linkText": "group" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "list": { "refId": "list", "type": "htmlAam", "value": "list", "linkText": "list" } }, + "command-button": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Command Button Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-8_124112/button.html", "linkText": "Test Case Page for Command Button Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/button/", "linkText": "APG Pattern: Button" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/button/examples/button/", "linkText": "APG Example: Button" }, "button": { "refId": "button", "type": "aria", "value": "button", "linkText": "button" } }, + "disclosure-faq": { "author": { "refId": "author", "type": "metadata", "value": "James Scholes", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "james@pac.bz", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Disclosure of Answers to Frequently Asked Questions Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-8-8_7334/disclosure-faq.html", "linkText": "Test Case Page for Disclosure of Answers to Frequently Asked Questions Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/", "linkText": "APG Pattern: Disclosure (Show/Hide)" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-faq/", "linkText": "APG Example: Disclosure (Show/Hide) for Answers to Frequently Asked Questions" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" }, "div": { "refId": "div", "type": "htmlAam", "value": "div", "linkText": "div" }, "ul": { "refId": "ul", "type": "htmlAam", "value": "ul", "linkText": "ul" }, "generic": { "refId": "generic", "type": "aria", "value": "generic", "linkText": "generic" } }, + "disclosure-navigation": { "author": { "refId": "author", "type": "metadata", "value": "James Scholes", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "james@pac.bz", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Disclosure Navigation Menu Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-9-9_13844/disclosure-navigation.html", "linkText": "Test Case Page for Disclosure Navigation Menu Example" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/", "linkText": "APG Example: Disclosure Navigation Menu" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" }, "heading": { "refId": "heading", "type": "htmlAam", "value": "heading", "linkText": "heading" }, "ul": { "refId": "ul", "type": "htmlAam", "value": "ul", "linkText": "ul" }, "htmlLink": { "refId": "htmlLink", "type": "htmlAam", "value": "a", "linkText": "a (hyperlink)" }, "nav": { "refId": "nav", "type": "htmlAam", "value": "nav", "linkText": "nav" }, "region": { "refId": "region", "type": "aria", "value": "region", "linkText": "region" }, "aria-label": { "refId": "aria-label", "type": "aria", "value": "aria-label", "linkText": "aria-label" }, "aria-current": { "refId": "aria-current", "type": "aria", "value": "aria-current", "linkText": "aria-current" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" } }, + "horizontal-slider": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Color Viewer Slider", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-11_11511/slider-color-viewer.html", "linkText": "Test Case Page for Color Viewer Slider" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/", "linkText": "APG Pattern: Slider" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-color-viewer/", "linkText": "APG Example: Color Viewer Slider" }, "slider": { "refId": "slider", "type": "aria", "value": "slider", "linkText": "slider" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-valuenow": { "refId": "aria-valuenow", "type": "aria", "value": "aria-valuenow", "linkText": "aria-valuenow" }, "aria-valuemin": { "refId": "aria-valuemin", "type": "aria", "value": "aria-valuemin", "linkText": "aria-valuemin" }, "aria-valuemax": { "refId": "aria-valuemax", "type": "aria", "value": "aria-valuemax", "linkText": "aria-valuemax" }, "aria-orientation": { "refId": "aria-orientation", "type": "aria", "value": "aria-orientation", "linkText": "aria-orientation" } }, + "link-css": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Link Example 3 (CSS :before content property on a span element)", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2023-3-13_142620/link-css.html", "linkText": "Test Case Page for Link Example 3 (CSS :before content property on a span element)" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/", "linkText": "APG Design Pattern" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/examples/link/", "linkText": "APG Link Examples" }, "aria-label": { "refId": "aria-label", "type": "aria", "value": "aria-label", "linkText": "aria-label" }, "link": { "refId": "link", "type": "aria", "value": "link", "linkText": "link" } }, + "link-img-alt": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Link Example 2 (img element with alt attribute)", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2023-3-13_11377/link-img-alt.html", "linkText": "Test Case Page for Link Example 2 (img element with alt attribute)" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/", "linkText": "APG Design Pattern" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/examples/link/", "linkText": "APG Link Examples" }, "link": { "refId": "link", "type": "aria", "value": "link", "linkText": "link" } }, + "link-span-text": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Link Example 1 (span element with text content)", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-6_14258/link.html", "linkText": "Test Case Page for Link Example 1 (span element with text content)" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/", "linkText": "APG Pattern: Link" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/link/examples/link/", "linkText": "APG Example: Link" }, "link": { "refId": "link", "type": "aria", "value": "link", "linkText": "link" } }, + "menu-button-navigation": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Navigation Menu Button", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2024-8-12_123937/menu-button-links.html", "linkText": "Test Case Page for Navigation Menu Button" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/", "linkText": "APG Pattern: Menu Button" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-links/", "linkText": "APG Example: Actions Menu Button Using" }, "menu": { "refId": "menu", "type": "aria", "value": "menu", "linkText": "menu" }, "menuitem": { "refId": "menuitem", "type": "aria", "value": "menuitem", "linkText": "menuitem" }, "aria-haspopup": { "refId": "aria-haspopup", "type": "aria", "value": "aria-haspopup", "linkText": "aria-haspopup" }, "aria-controls": { "refId": "aria-controls", "type": "aria", "value": "aria-controls", "linkText": "aria-controls" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" } }, + "menu-button-actions": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Action Menu Button Example Using element.focus()", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2024-8-28_1295/menu-button-actions.html", "linkText": "Test Case Page for Action Menu Button Example Using element.focus()" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/", "linkText": "APG Pattern: Menu Button" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/", "linkText": "APG Example: Actions Menu Button Using element.focus()" }, "menu": { "refId": "menu", "type": "aria", "value": "menu", "linkText": "menu" }, "menuitem": { "refId": "menuitem", "type": "aria", "value": "menuitem", "linkText": "menuitem" }, "aria-haspopup": { "refId": "aria-haspopup", "type": "aria", "value": "aria-haspopup", "linkText": "aria-haspopup" }, "aria-controls": { "refId": "aria-controls", "type": "aria", "value": "aria-controls", "linkText": "aria-controls" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" } }, + "menu-button-actions-active-descendant": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Action Menu Button Example Using aria-activedescendant", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2024-7-21_174946/menu-button-actions-active-descendant.html", "linkText": "Test Case Page for Action Menu Button Example Using aria-activedescendant" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/", "linkText": "APG Pattern: Menu Button" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/", "linkText": "APG Example: Actions Menu Button Using aria-activedescendant" }, "menu": { "refId": "menu", "type": "aria", "value": "menu", "linkText": "menu" }, "menuitem": { "refId": "menuitem", "type": "aria", "value": "menuitem", "linkText": "menuitem" }, "aria-haspopup": { "refId": "aria-haspopup", "type": "aria", "value": "aria-haspopup", "linkText": "aria-haspopup" }, "aria-controls": { "refId": "aria-controls", "type": "aria", "value": "aria-controls", "linkText": "aria-controls" }, "aria-activedescendant": { "refId": "aria-activedescendant", "type": "aria", "value": "aria-activedescendant", "linkText": "aria-activedescendant" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-expanded": { "refId": "aria-expanded", "type": "aria", "value": "aria-expanded", "linkText": "aria-expanded" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" } }, + "radiogroup-aria-activedescendant": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Radio Group Example Using aria-activedescendant", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-7_113015/radio-activedescendant.html", "linkText": "Test Case Page for Radio Group Example Using aria-activedescendant" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/", "linkText": "APG Pattern: Radio Group" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/examples/radio-activedescendant/", "linkText": "APG Example: Radio Group Using aria-activedescendant" }, "aria-activedescendant": { "refId": "aria-activedescendant", "type": "aria", "value": "aria-activedescendant", "linkText": "aria-activedescendant" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "radio": { "refId": "radio", "type": "aria", "value": "radio", "linkText": "radio" }, "radiogroup": { "refId": "radiogroup", "type": "aria", "value": "radiogroup", "linkText": "radiogroup" }, "htmlLink": { "refId": "htmlLink", "type": "htmlAam", "value": "a", "linkText": "HTML hyperlink" } }, + "modal-dialog": { "author": { "refId": "author", "type": "metadata", "value": "James Scholes", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "james@pac.bz", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Modal Dialog Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-7_15544/dialog.html", "linkText": "Test Case Page for Modal Dialog Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/", "linkText": "APG Pattern: Dialog (Modal)" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog/", "linkText": "APG Example: Modal Dialog" }, "dialog": { "refId": "dialog", "type": "aria", "value": "dialog", "linkText": "dialog" }, "aria-modal": { "refId": "aria-modal", "type": "aria", "value": "aria-modal", "linkText": "aria-modal" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-describedby": { "refId": "aria-describedby", "type": "aria", "value": "aria-describedby", "linkText": "aria-describedby" } }, + "radiogroup-roving-tabindex": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Radio Group Example Using Roving tabindex", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2021-3-15_144141/radio.html", "linkText": "Test Case Page for Radio Group Example Using Roving tabindex" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/", "linkText": "APG Pattern: Radio Group" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/examples/radio/", "linkText": "APG Example: Radio Group Using Roving tabindex" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "radio": { "refId": "radio", "type": "aria", "value": "radio", "linkText": "radio" }, "radiogroup": { "refId": "radiogroup", "type": "aria", "value": "radiogroup", "linkText": "radiogroup" }, "htmlLink": { "refId": "htmlLink", "type": "htmlAam", "value": "a", "linkText": "HTML hyperlink" } }, + "rating-radio-group": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Rating Radio Group", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-4-8_12716/radio-rating.html", "linkText": "Rating Radio Group Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/", "linkText": "APG Pattern: Radio Group" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/radio/examples/radio-rating/", "linkText": "APG Example: Rating Radio Group" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "aria-label": { "refId": "aria-label", "type": "aria", "value": "aria-label", "linkText": "aria-label" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "radio": { "refId": "radio", "type": "aria", "value": "radio", "linkText": "radio" }, "radiogroup": { "refId": "radiogroup", "type": "aria", "value": "radiogroup", "linkText": "radiogroup" }, "link": { "refId": "link", "type": "htmlAam", "value": "link", "linkText": "link" } }, + "seek-slider": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Media Seek Slider", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2021-9-21_14462/slider-seek.html", "linkText": "Test Case Page for Media Seek Slider" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/", "linkText": "APG Pattern: Slider" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-seek/", "linkText": "APG Example: Media Seek Slider" }, "slider": { "refId": "slider", "type": "aria", "value": "slider", "linkText": "slider" }, "none": { "refId": "none", "type": "aria", "value": "none", "linkText": "none" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-orientation": { "refId": "aria-orientation", "type": "aria", "value": "aria-orientation", "linkText": "aria-orientation" }, "aria-valuenow": { "refId": "aria-valuenow", "type": "aria", "value": "aria-valuenow", "linkText": "aria-valuenow" }, "aria-valuemin": { "refId": "aria-valuemin", "type": "aria", "value": "aria-valuemin", "linkText": "aria-valuemin" }, "aria-valuemax": { "refId": "aria-valuemax", "type": "aria", "value": "aria-valuemax", "linkText": "aria-valuemax" }, "aria-valuetext": { "refId": "aria-valuetext", "type": "aria", "value": "aria-valuetext", "linkText": "aria-valuetext" }, "aria-hidden": { "refId": "aria-hidden", "type": "aria", "value": "aria-hidden", "linkText": "aria-hidden" } }, + "switch": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Switch Example", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-8-1_103716/switch.html", "linkText": "Test Case Page for Switch Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/", "linkText": "APG Pattern: Switch" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/examples/switch/", "linkText": "APG Example: Switch" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "switch": { "refId": "switch", "type": "aria", "value": "switch", "linkText": "switch" } }, + "switch-button": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Switch Example Using HTML Button", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-8-22_17848/switch-button.html", "linkText": "Test Case Page for Switch Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/", "linkText": "APG Pattern: Switch" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/examples/switch-button/", "linkText": "APG Example: Switch Using HTML Button" }, "aria-checked": { "refId": "aria-checked", "type": "aria", "value": "aria-checked", "linkText": "aria-checked" }, "switch": { "refId": "switch", "type": "aria", "value": "switch", "linkText": "switch" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" } }, + "tabs-automatic-activation": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Tabs with Automatic Activation", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-6-5_142619/tabs-automatic.html", "linkText": "Tabs with Automatic Activation" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/tabs/", "linkText": "Tabs Pattern" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-automatic/", "linkText": "Example of Tabs with Automatic Activation" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-selected": { "refId": "aria-selected", "type": "aria", "value": "aria-selected", "linkText": "aria-selected" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "tab": { "refId": "tab", "type": "aria", "value": "tab", "linkText": "tab" }, "tablist": { "refId": "tablist", "type": "aria", "value": "tablist", "linkText": "tablist" }, "tabpanel": { "refId": "tabpanel", "type": "aria", "value": "tabpanel", "linkText": "tabpanel" }, "htmlButton": { "refId": "htmlButton", "type": "htmlAam", "value": "button", "linkText": "HTML button" }, "htmlParagraph": { "refId": "htmlParagraph", "type": "htmlAam", "value": "p", "linkText": "HTML paragraph" } }, + "switch-checkbox": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Switch Example Using HTML Checkbox Input", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-8-25_124251/switch-checkbox.html", "linkText": "Test Case Page for Switch Example" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/", "linkText": "APG Pattern: Switch" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/switch/examples/switch-checkbox/", "linkText": "APG Example: Switch Using HTML Checkbox Input" }, "switch": { "refId": "switch", "type": "aria", "value": "switch", "linkText": "switch" }, "inputTypeCheckbox": { "refId": "inputTypeCheckbox", "type": "htmlAam", "value": "inputTypeCheckbox", "linkText": "inputTypeCheckbox" }, "label": { "refId": "label", "type": "htmlAam", "value": "label", "linkText": "HTML label" }, "@checked": { "refId": "@checked", "type": "htmlAam", "value": "@checked", "linkText": "@checked" } }, + "tabs-manual-activation": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Tabs with Manual Activation", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-8-28_13240/tabs-manual.html", "linkText": "Tabs with Automatic Activation" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/tabs/", "linkText": "Tabs Pattern" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-manual/", "linkText": "Example of Tabs with Manual Activation" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-posinset": { "refId": "aria-posinset", "type": "aria", "value": "aria-posinset", "linkText": "aria-posinset" }, "aria-selected": { "refId": "aria-selected", "type": "aria", "value": "aria-selected", "linkText": "aria-selected" }, "aria-setsize": { "refId": "aria-setsize", "type": "aria", "value": "aria-setsize", "linkText": "aria-setsize" }, "tab": { "refId": "tab", "type": "aria", "value": "tab", "linkText": "tab" }, "tablist": { "refId": "tablist", "type": "aria", "value": "tablist", "linkText": "tablist" }, "tabpanel": { "refId": "tabpanel", "type": "aria", "value": "tabpanel", "linkText": "tabpanel" }, "htmlButton": { "refId": "htmlButton", "type": "htmlAam", "value": "button", "linkText": "HTML button" }, "htmlLink": { "refId": "htmlLink", "type": "htmlAam", "value": "a", "linkText": "HTML hyperlink" }, "htmlParagraph": { "refId": "htmlParagraph", "type": "htmlAam", "value": "p", "linkText": "HTML paragraph" } }, + "toggle-button": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Toggle Button", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2022-4-8_135651/button.html", "linkText": "Test Case Page for Toggle Button" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/button/", "linkText": "APG Pattern: Button" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/button/examples/button/", "linkText": "APG Example: Button" }, "button": { "refId": "button", "type": "htmlAam", "value": "button", "linkText": "button" }, "aria-pressed": { "refId": "aria-pressed", "type": "aria", "value": "aria-pressed", "linkText": "aria-pressed" } }, + "vertical-temperature-slider": { "author": { "refId": "author", "type": "metadata", "value": "Isabel Del Castillo", "linkText": "" }, "title": { "refId": "title", "type": "metadata", "value": "Vertical Temperature Slider", "linkText": "" }, "authorEmail": { "refId": "authorEmail", "type": "metadata", "value": "isa.delcastillo5@gmail.com", "linkText": "" }, "reference": { "refId": "reference", "type": "metadata", "value": "reference/2025-7-15_112752/slider-temperature.html", "linkText": "Test Case Page for Vertical Temperature Slider" }, "designPattern": { "refId": "designPattern", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/", "linkText": "APG Pattern: Slider" }, "example": { "refId": "example", "type": "metadata", "value": "https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-temperature/", "linkText": "APG Example: Vertical Temperature Slider" }, "slider": { "refId": "slider", "type": "aria", "value": "slider", "linkText": "slider" }, "none": { "refId": "none", "type": "aria", "value": "none", "linkText": "none" }, "aria-labelledby": { "refId": "aria-labelledby", "type": "aria", "value": "aria-labelledby", "linkText": "aria-labelledby" }, "aria-orientation": { "refId": "aria-orientation", "type": "aria", "value": "aria-orientation", "linkText": "aria-orientation" }, "aria-valuenow": { "refId": "aria-valuenow", "type": "aria", "value": "aria-valuenow", "linkText": "aria-valuenow" }, "aria-valuemin": { "refId": "aria-valuemin", "type": "aria", "value": "aria-valuemin", "linkText": "aria-valuemin" }, "aria-valuemax": { "refId": "aria-valuemax", "type": "aria", "value": "aria-valuemax", "linkText": "aria-valuemax" }, "aria-valuetext": { "refId": "aria-valuetext", "type": "aria", "value": "aria-valuetext", "linkText": "aria-valuetext" }, "aria-hidden": { "refId": "aria-hidden", "type": "aria", "value": "aria-hidden", "linkText": "aria-hidden" } }, + /* eslint-enable */ + }; + + return queryInterface.sequelize.transaction(async transaction => { + const testPlanVersions = await queryInterface.sequelize.query( + `SELECT id, directory, tests FROM "TestPlanVersion" + WHERE metadata->>'testFormatVersion' = '2'`, + { + type: Sequelize.QueryTypes.SELECT, + transaction + } + ); + + for (const testPlanVersion of testPlanVersions) { + const { id, directory, tests } = testPlanVersion; + + if (!directory || !tests || !Array.isArray(tests)) { + continue; + } + + const directoryReferences = references[directory]; + if (!directoryReferences) { + continue; + } + + let modified = false; + + const updatedTests = tests.map(test => { + if ( + !test.renderableContent || + !test.renderableContent.info || + !test.renderableContent.info.references || + !Array.isArray(test.renderableContent.info.references) + ) { + return test; + } + + const updatedReferences = test.renderableContent.info.references.map( + ref => { + if (directoryReferences[ref.refId]) { + const replacementRef = directoryReferences[ref.refId]; + modified = true; + return { + ...ref, + linkText: replacementRef.linkText, + value: replacementRef.value + }; + } + return ref; + } + ); + + return { + ...test, + renderableContent: { + ...test.renderableContent, + info: { + ...test.renderableContent.info, + references: updatedReferences + } + } + }; + }); + + if (modified) { + await queryInterface.sequelize.query( + `UPDATE "TestPlanVersion" SET "tests" = ? WHERE id = ?`, + { + replacements: [JSON.stringify(updatedTests), id], + transaction + } + ); + } + } + + await dumpTable('TestPlanVersion'); + await regenerateResultsAndRecalculateHashes(queryInterface, transaction, { + testPlanVersionWhere: `WHERE metadata->>'testFormatVersion' = '2'`, + pruneOldVersions: false + }); + }); + }, + + async down() { + // This migration cannot be reversed as we don't have the original values; use the dumped TestPlanVersion table + } +}; diff --git a/server/models/services/TestsService.js b/server/models/services/TestsService.js index 6ba3538d9..3ef776f79 100644 --- a/server/models/services/TestsService.js +++ b/server/models/services/TestsService.js @@ -1,9 +1,25 @@ const ats = require('../../resources/ats.json'); +const support = require('../../resources/support.json'); const { getCommandV1, getCommandV2 } = require('../../resolvers/helpers/retrieveCommands'); +const mutateReference = reference => { + if (!reference || !reference.type) return reference; + + const supportReferenceObj = support.references[reference.type]; + const fragmentId = supportReferenceObj?.fragmentIds[reference.value]; + if (fragmentId) { + reference.rawValue = reference.value; + reference.rawLinkText = reference.linkText; + reference.value = `${supportReferenceObj.baseUrl}${fragmentId}`; + reference.linkText = `${reference.linkText} ${supportReferenceObj.linkText}`; + } + + return reference; +}; + const getTests = parentRecord => { let testPlanVersion; let testPlanReport; @@ -68,21 +84,24 @@ const getTests = parentRecord => { `unexpected.renderableContentAssertion.found: ${assertion.rawAssertionId}` ); + let references = + isV2 && renderableContentAssertion.refIds.trim() !== '' + ? renderableContentAssertion.refIds + .trim() + .split(' ') + .map(refId => { + const reference = test.renderableContent.info.references.find( + r => r.refId === refId + ); + return mutateReference(reference); + }) + : null; + return { ...assertion, text: isV2 ? assertion.assertionStatement : assertion.text, phrase: isV2 ? assertion.assertionPhrase : null, - references: - isV2 && renderableContentAssertion.refIds.trim() !== '' - ? renderableContentAssertion.refIds - .trim() - .split(' ') - .map(refId => - test.renderableContent.info.references.find( - r => r.refId === refId - ) - ) - : null + references }; }) })); diff --git a/server/resolvers/ariaHtmlFeatureDetailReportResolver.js b/server/resolvers/ariaHtmlFeatureDetailReportResolver.js index 1cc8d76a1..ee9dfc8ef 100644 --- a/server/resolvers/ariaHtmlFeatureDetailReportResolver.js +++ b/server/resolvers/ariaHtmlFeatureDetailReportResolver.js @@ -9,7 +9,7 @@ const calculateAssertionStatistics = require('../util/calculateAssertionStatisti const ariaHtmlFeatureDetailReportResolver = async ( _, - { refId, atId, browserId }, + { refId, refType, atId, browserId }, context ) => { const { transaction } = context; @@ -71,6 +71,7 @@ const ariaHtmlFeatureDetailReportResolver = async ( report.id, finalizedTestResults, refId, + refType, testIdToResultIdMap ); diff --git a/server/resources/support.json b/server/resources/support.json new file mode 100644 index 000000000..b1c4226b9 --- /dev/null +++ b/server/resources/support.json @@ -0,0 +1,601 @@ +{ + "subfolders": { + "apg": "ARIA Practices Guidelines Tests" + }, + "ats": [ + { + "name": "JAWS", + "key": "jaws", + "defaultConfigurationInstructionsHTML": "Configure JAWS with default settings. For help, read <a href="https://github.com/w3c/aria-at/wiki/Configuring-Screen-Readers-for-Testing">Configuring Screen Readers for Testing</a>.", + "assertionTokens": { + "screenReader": "JAWS", + "interactionMode": "PC cursor active", + "readingMode": "virtual cursor active", + "readingCursor": "virtual cursor" + }, + "settings": { + "virtualCursor": { + "screenText": "virtual cursor active", + "instructions": [ + "Press <kbd>Alt</kbd>+<kbd>Delete</kbd> to determine which cursor is active.", + "If the PC cursor is active, press <kbd>Escape</kbd> to activate the virtual cursor." + ] + }, + "pcCursor": { + "screenText": "PC cursor active", + "instructions": [ + "Press <kbd>Alt</kbd>+<kbd>Delete</kbd> to determine which cursor is active.", + "If the virtual cursor is active, press <kbd>Insert</kbd>+<kbd>z</kbd> to disable the virtual cursor." + ] + } + } + }, + { + "name": "NVDA", + "key": "nvda", + "defaultConfigurationInstructionsHTML": "Configure NVDA with default settings. For help, read <a href="https://github.com/w3c/aria-at/wiki/Configuring-Screen-Readers-for-Testing">Configuring Screen Readers for Testing</a>.", + "assertionTokens": { + "screenReader": "NVDA", + "interactionMode": "focus mode", + "readingMode": "browse mode", + "readingCursor": "browse mode caret" + }, + "settings": { + "browseMode": { + "screenText": "browse mode on", + "instructions": [ + "Press <kbd>Insert</kbd>+<kbd>Space</kbd>.", + "If NVDA made the focus mode sound, press <kbd>Insert</kbd>+<kbd>Space</kbd> again to turn browse mode back on." + ] + }, + "focusMode": { + "screenText": "focus mode on", + "instructions": [ + "Press <kbd>Insert</kbd>+<kbd>Space</kbd>.", + "If NVDA made the browse mode sound, press <kbd>Insert</kbd>+<kbd>Space</kbd> again to turn focus mode back on." + ] + } + } + }, + { + "name": "VoiceOver for macOS", + "key": "voiceover_macos", + "defaultConfigurationInstructionsHTML": "Configure VoiceOver with default settings. For help, read <a href="https://github.com/w3c/aria-at/wiki/Configuring-Screen-Readers-for-Testing">Configuring Screen Readers for Testing</a>.", + "assertionTokens": { + "screenReader": "VoiceOver", + "readingCursor": "VoiceOver cursor" + }, + "settings": { + "quickNavOn": { + "screenText": "quick nav on", + "instructions": [ + "Simultaneously press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd>.", + "If VoiceOver said 'quick nav off', press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd> again to turn it back on." + ] + }, + "quickNavOff": { + "screenText": "quick nav off", + "instructions": [ + "Simultaneously press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd>.", + "If VoiceOver said 'quick nav on', press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd> again to turn it back off." + ] + }, + "arrowQuickKeyNavOn": { + "screenText": "arrow quick key nav on", + "instructions": [ + "Simultaneously press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd>.", + "If VoiceOver said 'arrow quick key nav off', press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd> again to turn it back on." + ] + }, + "arrowQuickKeyNavOff": { + "screenText": "arrow quick key nav off", + "instructions": [ + "Simultaneously press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd>.", + "If VoiceOver said 'arrow quick key nav on', press <kbd>Left Arrow</kbd> and <kbd>Right Arrow</kbd> again to turn it back off." + ] + }, + "singleQuickKeyNavOn": { + "screenText": "single quick key nav on", + "instructions": [ + "Press <kbd>Control</kbd>+<kbd>Option</kbd>+<kbd>q</kbd>.", + "If VoiceOver said 'single quick key nav off', press <kbd>Control</kbd>+<kbd>Option</kbd>+<kbd>q</kbd> again to turn it back on." + ] + }, + "singleQuickKeyNavOff": { + "screenText": "single quick key nav off", + "instructions": [ + "Press <kbd>Control</kbd>+<kbd>Option</kbd>+<kbd>q</kbd>.", + "If VoiceOver said 'single quick key nav on', press <kbd>Control</kbd>+<kbd>Option</kbd>+<kbd>q</kbd> again to turn it back off." + ] + } + } + } + ], + "applies_to": { + "Desktop Screen Readers": ["VoiceOver for macOS", "NVDA", "JAWS"], + "Screen Readers": ["VoiceOver for macOS", "NVDA", "JAWS"] + }, + "testPlanStrings": { + "ariaSpecsPreface": "Tested ARIA features:", + "openExampleInstruction": "Activate the "Open test page" button, which opens the example to test in a new window and runs a script that", + "commandListPreface": "Do this with each of the following commands or command sequences.", + "commandListSettingsPreface": "If any settings are specified in parentheses, ensure the settings are active before executing the command or command sequence.", + "settingInstructionsPreface": "To perform a task with", + "assertionResponseQuestion": "Which statements are true about the response to" + }, + "references": { + "aria": { + "baseUrl": "https://www.w3.org/TR/wai-aria/", + "linkText": "ARIA Specification", + "fragmentIds": { + "alert": "#alert", + "alertdialog": "#alertdialog", + "application": "#application", + "article": "#article", + "associationlist": "#associationlist", + "associationlistitemkey": "#associationlistitemkey", + "associationlistitemvalue": "#associationlistitemvalue", + "banner": "#banner", + "blockquote": "#blockquote", + "button": "#button", + "caption": "#caption", + "cell": "#cell", + "checkbox": "#checkbox", + "code": "#code", + "columnheader": "#columnheader", + "combobox": "#combobox", + "command": "#command", + "comment": "#comment", + "complementary": "#complementary", + "composite": "#composite", + "contentinfo": "#contentinfo", + "definition": "#definition", + "deletion": "#deletion", + "dialog": "#dialog", + "directory": "#directory", + "document": "#document", + "emphasis": "#emphasis", + "feed": "#feed", + "figure": "#figure", + "form": "#form", + "generic": "#generic", + "grid": "#grid", + "gridcell": "#gridcell", + "group": "#group", + "heading": "#heading", + "image": "#image", + "img": "#img", + "input": "#input", + "insertion": "#insertion", + "landmark": "#landmark", + "link": "#link", + "list": "#list", + "listbox": "#listbox", + "listitem": "#listitem", + "log": "#log", + "main": "#main", + "mark": "#mark", + "marquee": "#marquee", + "math": "#math", + "menu": "#menu", + "menubar": "#menubar", + "menuitem": "#menuitem", + "menuitemcheckbox": "#menuitemcheckbox", + "menuitemradio": "#menuitemradio", + "meter": "#meter", + "navigation": "#navigation", + "none": "#none", + "note": "#note", + "option": "#option", + "paragraph": "#paragraph", + "presentation": "#presentation", + "progressbar": "#progressbar", + "radio": "#radio", + "radiogroup": "#radiogroup", + "range": "#range", + "region": "#region", + "roletype": "#roletype", + "row": "#row", + "rowgroup": "#rowgroup", + "rowheader": "#rowheader", + "scrollbar": "#scrollbar", + "search": "#search", + "searchbox": "#searchbox", + "section": "#section", + "sectionhead": "#sectionhead", + "select": "#select", + "separator": "#separator", + "slider": "#slider", + "spinbutton": "#spinbutton", + "status": "#status", + "strong": "#strong", + "structure": "#structure", + "subscript": "#subscript", + "suggestion": "#suggestion", + "superscript": "#superscript", + "switch": "#switch", + "tab": "#tab", + "table": "#table", + "tablist": "#tablist", + "tabpanel": "#tabpanel", + "term": "#term", + "textbox": "#textbox", + "time": "#time", + "timer": "#timer", + "toolbar": "#toolbar", + "tooltip": "#tooltip", + "tree": "#tree", + "treegrid": "#treegrid", + "treeitem": "#treeitem", + "widget": "#widget", + "window": "#window", + "aria-activedescendant": "#aria-activedescendant", + "aria-atomic": "#aria-atomic", + "aria-autocomplete": "#aria-autocomplete", + "aria-braillelabel": "#aria-braillelabel", + "aria-brailleroledescription": "#aria-brailleroledescription", + "aria-busy": "#aria-busy", + "aria-checked": "#aria-checked", + "aria-colcount": "#aria-colcount", + "aria-colindex": "#aria-colindex", + "aria-colindextext": "#aria-colindextext", + "aria-colspan": "#aria-colspan", + "aria-controls": "#aria-controls", + "aria-current": "#aria-current", + "aria-describedby": "#aria-describedby", + "aria-description": "#aria-description", + "aria-details": "#aria-details", + "aria-disabled": "#aria-disabled", + "aria-errormessage": "#aria-errormessage", + "aria-expanded": "#aria-expanded", + "aria-flowto": "#aria-flowto", + "aria-haspopup": "#aria-haspopup", + "aria-hidden": "#aria-hidden", + "aria-invalid": "#aria-invalid", + "aria-keyshortcuts": "#aria-keyshortcuts", + "aria-label": "#aria-label", + "aria-labelledby": "#aria-labelledby", + "aria-level": "#aria-level", + "aria-live": "#aria-live", + "aria-modal": "#aria-modal", + "aria-multiline": "#aria-multiline", + "aria-multiselectable": "#aria-multiselectable", + "aria-orientation": "#aria-orientation", + "aria-owns": "#aria-owns", + "aria-placeholder": "#aria-placeholder", + "aria-posinset": "#aria-posinset", + "aria-pressed": "#aria-pressed", + "aria-readonly": "#aria-readonly", + "aria-relevant": "#aria-relevant", + "aria-required": "#aria-required", + "aria-roledescription": "#aria-roledescription", + "aria-rowcount": "#aria-rowcount", + "aria-rowindex": "#aria-rowindex", + "aria-rowindextext": "#aria-rowindextext", + "aria-rowspan": "#aria-rowspan", + "aria-selected": "#aria-selected", + "aria-setsize": "#aria-setsize", + "aria-sort": "#aria-sort", + "aria-valuemax": "#aria-valuemax", + "aria-valuemin": "#aria-valuemin", + "aria-valuenow": "#aria-valuenow", + "aria-valuetext": "#aria-valuetext" + } + }, + "htmlAam": { + "baseUrl": "https://www.w3.org/TR/html-aam-1.0/", + "linkText": "HTML-AAM Specification", + "fragmentIds": { + "@abbr": "#att-abbr", + "@accept": "#att-accept", + "@acceptCharset": "#att-accept-charset", + "@accesskey": "#att-accesskey", + "@action": "#att-action", + "@allow": "#att-allow", + "@allowfullscreen": "#att-allowfullscreen", + "@alt": "#att-alt", + "@as": "#att-as", + "@async": "#att-async", + "@autocapitalize": "#att-autocapitalize", + "@autocompleteForm": "#att-autocomplete-form", + "@autocomplete": "#att-autocomplete", + "@autofocus": "#att-autofocus", + "@autoplay": "#att-autoplay", + "@blocking": "#att-blocking", + "@charsetMeta": "#att-charset-meta", + "@checked": "#att-checked", + "@checkedAbsent": "#att-checked-absent", + "@cite": "#att-cite", + "@class": "#att-class", + "@color": "#att-color", + "@cols": "#att-cols", + "@colspan": "#att-colspan", + "@commandPopovers": "#att-command-popovers", + "@commandDialogs ": "#att-command-dialogs", + "@commandfor": "#att-commandfor", + "@content": "#att-content", + "@contenteditable": "#att-contenteditable", + "@controls": "#att-controls", + "@coords": "#att-coords", + "@crossorigin": "#att-crossorigin", + "@data": "#att-data", + "@datetimeDelins": "#att-datetime-delins", + "@datetimeTime": "#att-datetime-time", + "@decoding": "#att-decoding", + "@default": "#att-default", + "@defer": "#att-defer", + "@dir": "#att-dir", + "@dirBdo": "#att-dir-bdo", + "@dirname": "#att-dirname", + "@disabled": "#att-disabled", + "@disabledFieldset": "#att-disabled-fieldset", + "@disabledLink": "#att-disabled-link", + "@download": "#att-download", + "@draggable": "#att-draggable", + "@enctype": "#att-enctype", + "@enterkeyhint": "#att-enterkeyhint", + "@fetchpriority": "#att-fetchpriority", + "@forLabel": "#att-for-label", + "@forOutput": "#att-for-output", + "@form": "#att-form", + "@formaction": "#att-formaction", + "@formenctype": "#att-formenctype", + "@formmethod": "#att-formmethod", + "@formnovalidate": "#att-formnovalidate", + "@formtarget": "#att-formtarget", + "@headers": "#att-headers", + "@height": "#att-height", + "@hidden": "#att-hidden", + "@high": "#att-high", + "@href": "#att-href", + "@hrefLink": "#att-href-link", + "@hreflang": "#att-hreflang", + "@httpEquiv": "#att-http-equiv", + "@id": "#att-id", + "@inert": "#att-inert", + "@indeterminate": "#att-indeterminate", + "@ismap": "#att-ismap", + "@itemid": "#att-itemid", + "@itemprop": "#att-itemprop", + "@itemref": "#att-itemref", + "@itemscope": "#att-itemscope", + "@itemtype": "#att-itemtype", + "@kind": "#att-kind", + "@label": "#att-label", + "@lang": "#att-lang", + "@list": "#att-list", + "@loop": "#att-loop", + "@low": "#att-low", + "@maxInput": "#att-max-input", + "@max": "#att-max", + "@maxlength": "#att-maxlength", + "@media": "#att-media", + "@method": "#att-method", + "@minInput": "#att-min-input", + "@min": "#att-min", + "@minlength": "#att-minlength", + "@multipleInput": "#att-multiple-input", + "@multipleSelect": "#att-multiple-select", + "@muted": "#att-muted", + "@name": "#att-name", + "@nameForm": "#att-name-form", + "@nameIframe": "#att-name-iframe", + "@nameMap": "#att-name-map", + "@nameMeta": "#att-name-meta", + "@nameSlot": "#att-name-slot", + "@nomodule": "#att-nomodule", + "@nonce": "#att-nonce", + "@novalidate": "#att-novalidate", + "@openDetails": "#att-open-details", + "@openDialog": "#att-open-dialog", + "@optimum": "#att-optimum", + "@pattern": "#att-pattern", + "@ping": "#att-ping", + "@placeholder": "#att-placeholder", + "@playsinline": "#att-playsinline", + "@popover": "#att-popover", + "@popovertarget": "#att-popovertarget", + "@popovertargetaction": "#att-popovertargetaction", + "@poster": "#att-poster", + "@preload": "#att-preload", + "@readonly": "#att-readonly", + "@referrerpolicy": "#att-referrerpolicy", + "@rel": "#att-rel", + "@required": "#att-required", + "@reversed": "#att-reversed", + "@rows": "#att-rows", + "@rowspan": "#att-rowspan", + "@sandbox": "#att-sandbox", + "@scope": "#att-scope", + "@selected": "#att-selected", + "@shape": "#att-shape", + "@size": "#att-size", + "@sizes": "#att-sizes", + "@sizesImgSource": "#att-sizes-img-source", + "@slot": "#att-slot", + "@span": "#att-span", + "@spellcheck": "#att-spellcheck", + "@srcMedia": "#att-src-media", + "@srcdoc": "#att-srcdoc", + "@srclang": "#att-srclang", + "@srcset": "#att-srcset", + "@start": "#att-start", + "@step": "#att-step", + "@style": "#att-style", + "@tabindex": "#att-tabindex", + "@target": "#att-target", + "@targetBase": "#att-target-base", + "@targetForm": "#att-target-form", + "@title": "#att-title", + "@titleAbbr": "#att-title-abbr", + "@titleLink": "#att-title-link", + "@titleStyle": "#att-title-style", + "@translate": "#att-translate", + "@typeHyperlink": "#att-type-hyperlink", + "@typeButton": "#att-type-button", + "@typeEmbed": "#att-type-embed", + "@typeInput": "#att-type-input", + "@typeOl": "#att-type-ol", + "@usemap": "#att-usemap", + "@valueButton": "#att-value-button", + "@valueData": "#att-value-data", + "@valueInput": "#att-value-input", + "@valueInputButtons": "#att-value-input-buttons", + "@valueInputCheckboxHiddenRadio": "#att-value-input-checkbox-hidden-radio", + "@valueInputColor": "#att-value-input-color", + "@valueInputImage": "#att-value-input-image", + "@valueLi": "#att-value-li", + "@valueMeter": "#att-value-meter", + "@width": "#att-width", + "@wrap": "#att-wrap", + "a": "#el-a", + "aNoHref": "#el-a-no-href", + "abbr": "#el-abbr", + "address": "#el-address", + "area": "#el-area", + "areaNoHref": "#el-area-no-href", + "article": "#el-article", + "asideBodyOrMainScope": "#el-aside-ancestorbodymain", + "asideSectionScope": "#el-aside", + "audio": "#el-audio", + "autonomousCustomElement": "#el-autonomous-custom-element", + "b": "#el-b", + "base": "#el-base", + "bdi": "#el-bdi", + "bdo": "#el-bdo", + "blockquote": "#el-blockquote", + "body": "#el-body", + "br": "#el-br", + "button": "#el-button", + "canvas": "#el-canvas", + "caption": "#el-caption", + "cite": "#el-cite", + "code": "#el-code", + "col": "#el-col", + "colgroup": "#el-colgroup", + "data": "#el-data", + "datalist": "#el-datalist", + "dd": "#el-dd", + "del": "#el-del", + "details": "#el-details", + "dfn": "#el-dfn", + "dialog": "#el-dialog", + "div": "#el-div", + "dl": "#el-dl", + "dt": "#el-dt", + "em": "#el-em", + "embed": "#el-embed", + "fieldset": "#el-fieldset", + "figcaption": "#el-figcaption", + "figure": "#el-figure", + "footerBodyScope": "#el-footer-ancestorbody", + "footerMainScope": "#el-footer", + "form": "#el-form", + "formAssociatedCustomElement": "#el-form-associated-custom-element", + "heading": "#el-h1-h6", + "head": "#el-head", + "headerBodyScope": "#el-header-ancestorbody", + "headerMainScope": "#el-header", + "hgroup": "#el-hgroup", + "hr": "#el-hr", + "html": "#el-html", + "i": "#el-i", + "iframe": "#el-iframe", + "img": "#el-img", + "imgEmptyAlt": "#el-img-empty-alt", + "inputTypeButton": "#el-input-button", + "inputTypeCheckbox": "#el-input-checkbox", + "inputTypeColor": "#el-input-color", + "inputTypeDate": "#el-input-date", + "inputTypeDateTime": "#el-input-datetime-local", + "inputTypeEmail": "#el-input-email", + "inputTypeFile": "#el-input-file", + "inputTypeHidden": "#el-input-hidden", + "inputTypeImage": "#el-input-image", + "inputTypeMonth": "#el-input-month", + "inputTypeNumber": "#el-input-number", + "inputTypePassword": "#el-input-password", + "inputTypeRadio": "#el-input-radio", + "inputTypeRange": "#el-input-range", + "inputTypeReset": "#el-input-reset", + "inputTypeSearch": "#el-input-search", + "inputTypeSubmit": "#el-input-submit", + "inputTypeTelephone": "#el-input-tel", + "inputTypeText": "#el-input-text", + "inputTypeTextAutocomplete": "#el-input-textetc-autocomplete", + "inputTypeTime": "#el-input-time", + "inputTypeUrl": "#el-input-url", + "inputTypeWeek": "#el-input-week", + "ins": "#el-ins", + "kbd": "#el-kbd", + "label": "#el-label", + "legend": "#el-legend", + "li": "#el-li", + "link": "#el-link", + "main": "#el-main", + "map": "#el-map", + "mark": "#el-mark", + "math": "#el-math", + "menu": "#el-menu", + "meta": "#el-meta", + "meter": "#el-meter", + "nav": "#el-nav", + "noscript": "#el-noscript", + "object": "#el-object", + "ol": "#el-ol", + "optgroup": "#el-optgroup", + "option": "#el-option", + "output": "#el-output", + "p": "#el-p", + "param": "#el-param", + "picture": "#el-picture", + "pre": "#el-pre", + "progress": "#el-progress", + "q": "#el-q", + "rb": "#el-rb", + "rp": "#el-rp", + "rt": "#el-rt", + "rtc": "#el-rtc", + "ruby": "#el-ruby", + "s": "#el-s", + "samp": "#el-samp", + "script": "#el-script", + "search": "#el-search", + "section": "#el-section", + "select": "#el-select-listbox", + "selectSize1": "#el-select-combobox", + "slot": "#el-slot", + "small": "#el-small", + "source": "#el-source", + "span": "#el-span", + "strong": "#el-strong", + "style": "#el-style", + "sub": "#el-sub", + "summary": "#el-summary", + "sup": "#el-sup", + "svg": "#el-svg", + "table": "#el-table", + "tbody": "#el-tbody", + "td": "#el-td", + "tdGridcell": "#el-td-gridcell", + "template": "#el-template", + "textarea": "#el-textarea", + "tfoot": "#el-tfoot", + "th": "#el-th", + "thGridcell": "#el-th-gridcell", + "thColgroupHeader": "#el-th-columnheader", + "thRowgroupHeader": "#el-th-rowheader", + "thead": "#el-thead", + "time": "#el-time", + "title": "#el-title", + "tr": "#el-tr", + "track": "#el-track", + "u": "#el-u", + "ul": "#el-ul", + "var": "#el-var", + "video": "#el-video", + "wbr": "#el-wbr" + } + } + } +} diff --git a/server/scripts/import-tests/gitOperations.js b/server/scripts/import-tests/gitOperations.js index 2dab90afc..dbd8b1a2e 100644 --- a/server/scripts/import-tests/gitOperations.js +++ b/server/scripts/import-tests/gitOperations.js @@ -3,7 +3,7 @@ const spawn = require('cross-spawn'); const ariaAtRepo = 'https://github.com/w3c/aria-at.git'; -const ariaAtDefaultBranch = 'tests-sub-folder-support-example'; +const ariaAtDefaultBranch = 'master'; /** * Executes a git command and returns its output. diff --git a/server/scripts/import-tests/testPlanVersionOperations.js b/server/scripts/import-tests/testPlanVersionOperations.js index 5c2397b4c..bbe897570 100644 --- a/server/scripts/import-tests/testPlanVersionOperations.js +++ b/server/scripts/import-tests/testPlanVersionOperations.js @@ -407,20 +407,21 @@ const importHarness = () => { sourceFolder = fse.existsSync(sourceFolder) ? sourceFolder : path.resolve(`${testsDirectory}/resources`); - const targetFolder = path.resolve( + const targetClientFolder = path.resolve( __dirname, '../../../', 'client', 'resources' ); + const targetServerFolder = path.resolve(__dirname, '../../', 'resources'); console.info( - `Updating harness directory, copying from ${sourceFolder} to ${targetFolder} ...` + `Updating harness directory, copying from ${sourceFolder} to ${targetClientFolder} ...` ); - fse.rmSync(targetFolder, { recursive: true, force: true }); + fse.rmSync(targetClientFolder, { recursive: true, force: true }); // Copy source folder console.info('Importing latest harness files ...'); - fse.copySync(sourceFolder, targetFolder, { + fse.copySync(sourceFolder, targetClientFolder, { filter: src => { if (fse.lstatSync(src).isDirectory()) { return true; @@ -437,13 +438,23 @@ const importHarness = () => { if (fse.existsSync(`${testsDirectory}/${commandsJson}`)) { fse.copyFileSync( `${testsDirectory}/${commandsJson}`, - `${targetFolder}/${commandsJson}` + `${targetClientFolder}/${commandsJson}` + ); + } + if (fse.existsSync(`${testsDirectory}/${supportJson}`)) { + fse.copyFileSync( + `${testsDirectory}/${supportJson}`, + `${targetClientFolder}/${supportJson}` + ); + + console.info( + `Updating server/resources/support.json, copying from ${sourceFolder} to ${targetServerFolder} ...` + ); + fse.copyFileSync( + `${testsDirectory}/${supportJson}`, + `${targetServerFolder}/${supportJson}` ); } - fse.copyFileSync( - `${testsDirectory}/${supportJson}`, - `${targetFolder}/${supportJson}` - ); console.info('Harness files update complete.'); }; @@ -507,22 +518,26 @@ const flattenObject = (obj, parentKey = '') => { * @returns {Promise} An object containing the parsed support data. */ const updateJsons = async () => { - // Commands path info for v1 format - let keysMjsPath = pathToFileURL( - path.join(gitCloneDirectory, 'resources', 'keys.mjs') - ); - keysMjsPath = fse.existsSync(keysMjsPath) - ? keysMjsPath - : pathToFileURL(path.join(testsDirectory, 'resources', 'keys.mjs')); - const commands = Object.entries(await import(keysMjsPath)).map( - ([id, text]) => ({ id, text }) - ); + try { + // Commands path info for v1 format + let keysMjsPath = pathToFileURL( + path.join(gitCloneDirectory, 'resources', 'keys.mjs') + ); + keysMjsPath = fse.existsSync(keysMjsPath) + ? keysMjsPath + : pathToFileURL(path.join(testsDirectory, 'resources', 'keys.mjs')); + const commands = Object.entries(await import(keysMjsPath)).map( + ([id, text]) => ({ id, text }) + ); - // Write commands for v1 format - await fse.writeFile( - path.resolve(__dirname, '../../resources/commandsV1.json'), - JSON.stringify(commands, null, 2) + '\n' - ); + // Write commands for v1 format + await fse.writeFile( + path.resolve(__dirname, '../../resources/commandsV1.json'), + JSON.stringify(commands, null, 2) + '\n' + ); + } catch (error) { + console.error('Unable to process keys.mjs for v1 test format'); + } try { // Commands path info for v2 format @@ -538,15 +553,27 @@ const updateJsons = async () => { JSON.stringify(flattenObject(commandsV2Parsed), null, 2) + '\n' ); } catch (error) { - console.error('commands.json for v2 test format may not exist'); + console.error( + 'Unable to process commands.json for v2 test format (file may not exist for aria-at commit)' + ); } - // Path info for support.json - const supportPath = pathToFileURL(path.join(testsDirectory, 'support.json')); - const supportPathString = fse.readFileSync(supportPath, 'utf8'); - const supportParsed = JSON.parse(supportPathString); + try { + // Path info for support.json + const supportPath = pathToFileURL( + path.join(testsDirectory, 'support.json') + ); + const supportPathString = fse.readFileSync(supportPath, 'utf8'); + const supportParsed = JSON.parse(supportPathString); - return { support: supportParsed }; + return { support: supportParsed }; + } catch (error) { + throw new Error( + `Unable to process support.json from ${pathToFileURL( + path.join(testsDirectory, 'support.json') + )}` + ); + } }; /** diff --git a/server/services/extractFeatureAssertionRows.js b/server/services/extractFeatureAssertionRows.js index a01fd18ae..f0a5b649c 100644 --- a/server/services/extractFeatureAssertionRows.js +++ b/server/services/extractFeatureAssertionRows.js @@ -6,6 +6,7 @@ const extractFeatureAssertionRows = ( testPlanReportId, finalizedTestResults, refId, + refType, testIdToResultIdMap = {} ) => { const rows = []; @@ -26,6 +27,7 @@ const extractFeatureAssertionRows = ( assertion.references.forEach(reference => { if (reference.refId !== refId) return; + if (refType && reference.type !== refType) return; if (!featureInfo.refId) { featureInfo.refId = reference.refId; diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index fcf67e70d..0e8c3788f 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -239,7 +239,9 @@ describe('graphql', () => { refId type linkText + rawLinkText value + rawValue total passed failed @@ -252,7 +254,9 @@ describe('graphql', () => { refId type linkText + rawLinkText value + rawValue total passed failed @@ -269,7 +273,9 @@ describe('graphql', () => { refId type linkText + rawLinkText value + rawValue total passed failed @@ -282,7 +288,9 @@ describe('graphql', () => { refId type linkText + rawLinkText value + rawValue total passed failed diff --git a/shared/getMetrics.js b/shared/getMetrics.js index cfb1fc0e5..e4e428543 100644 --- a/shared/getMetrics.js +++ b/shared/getMetrics.js @@ -336,7 +336,9 @@ const calculatePerFeatureCounts = (result, featureType) => { refId: featureRef.refId, type: featureRef.type, linkText: featureRef.linkText, + rawLinkText: featureRef.rawLinkText || featureRef.linkText || '', value: featureRef.value, + rawValue: featureRef.rawValue || featureRef.value || '', total: 0, passed: 0, failed: 0, diff --git a/shared/tests/getMetrics.test.js b/shared/tests/getMetrics.test.js index ba24649f6..f1e1a32ca 100644 --- a/shared/tests/getMetrics.test.js +++ b/shared/tests/getMetrics.test.js @@ -752,6 +752,8 @@ describe('getMetrics', () => { type: 'aria', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 1, failed: 0, @@ -764,6 +766,8 @@ describe('getMetrics', () => { type: 'aria', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 0, failed: 1, @@ -841,6 +845,8 @@ describe('getMetrics', () => { type: 'htmlAam', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 1, failed: 0, @@ -853,6 +859,8 @@ describe('getMetrics', () => { type: 'htmlAam', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 0, failed: 1, @@ -865,6 +873,8 @@ describe('getMetrics', () => { type: 'htmlAam', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 1, failed: 0, @@ -940,6 +950,8 @@ describe('getMetrics', () => { type: 'aria', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 0, failed: 0, @@ -952,6 +964,8 @@ describe('getMetrics', () => { type: 'aria', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 0, failed: 0, @@ -1024,6 +1038,8 @@ describe('getMetrics', () => { type: 'aria', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 1, failed: 0, @@ -1038,6 +1054,8 @@ describe('getMetrics', () => { type: 'htmlAam', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 1, failed: 0, @@ -1050,6 +1068,8 @@ describe('getMetrics', () => { type: 'htmlAam', linkText: undefined, value: undefined, + rawLinkText: '', + rawValue: '', total: 1, passed: 0, failed: 1, From efe4acd5fb1eb06fb7e8d5c64ebd13c735116cb4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Nov 2025 22:33:16 +0000 Subject: [PATCH 6/6] chore(release): v1.25.0 [skip ci] --- CHANGELOG.md | 15 +++++++++++++++ package.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9909f7364..635e088bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## [1.25.0](https://github.com/w3c/aria-at-app/compare/v1.24.0...v1.25.0) (2025-11-06) + + +### Features + +* open new tab, close tab and return to open queue on save ([#1605](https://github.com/w3c/aria-at-app/issues/1605)) ([ed52cfe](https://github.com/w3c/aria-at-app/commit/ed52cfe4c438c0d85ac1f27c379b7e63e5650636)) +* Support for subfolders in `/aria-at/tests/*` ([#1613](https://github.com/w3c/aria-at-app/issues/1613)) ([849301d](https://github.com/w3c/aria-at-app/commit/849301d58ad6f800eeba71427f5c5725b9147f41)) + + +### Bug Fixes + +* Consistent column order for ARIA and HTML Features tabs ([#1620](https://github.com/w3c/aria-at-app/issues/1620)) ([eabc6e0](https://github.com/w3c/aria-at-app/commit/eabc6e04aa250e25e18f03726a8d2232161c1190)) +* Prefer "No Data" instead of "None" on reports pages ([#1622](https://github.com/w3c/aria-at-app/issues/1622)) ([9e89b8a](https://github.com/w3c/aria-at-app/commit/9e89b8ad228ea96cf11422a13ddf254c77f5cf3a)) +* Support dynamic renames of `aria-at/support.json/references` properties ([#1617](https://github.com/w3c/aria-at-app/issues/1617)) ([f5d92fe](https://github.com/w3c/aria-at-app/commit/f5d92fe3fc9d1692af0e3ec5ec86ca9587980696)), closes [#1618](https://github.com/w3c/aria-at-app/issues/1618) + ## [1.24.0](https://github.com/w3c/aria-at-app/compare/v1.23.0...v1.24.0) (2025-11-04) diff --git a/package.json b/package.json index b687038a3..605285d50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aria-at-app", - "version": "1.24.0", + "version": "1.25.0", "description": "Run ARIA-AT tests and report results", "main": "server/index.js", "private": true,