From 452097b35a207341f5328b997dfc901461a4e9d9 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Sun, 10 Sep 2023 09:28:52 +0300 Subject: [PATCH 1/3] feat: Drop support for Node.js 14.x and Node.js 16.x and add support for Node 20.x (#1255) * feat: Drop support for Node.js 14.x and add support for Node 20.x BREAKING CHANGE: Minimum supported Node.js version is now 14.x * update node version in codesandbox * drop support for node 16 too --- .codesandbox/ci.json | 2 +- .github/workflows/validate.yml | 4 ++-- package.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index e650cd6f..c66df417 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "installCommand": "install:csb", "sandboxes": ["github/kentcdodds/react-testing-library-examples"], - "node": "14" + "node": "18" } diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 77ae2f42..2a938d48 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -29,7 +29,7 @@ jobs: # Otherwise we would not know if the problem is tied to the Node.js version fail-fast: false matrix: - node: [14, 16, 18] + node: [18, 20] runs-on: ubuntu-latest steps: - name: ⬇️ Checkout repo @@ -78,7 +78,7 @@ jobs: - name: ⎔ Setup node uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 18 - name: 📥 Download deps uses: bahmutov/npm-install@v1 diff --git a/package.json b/package.json index 40a17db0..83d2ab26 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" }, "browserslist": [ "and_chr 103", @@ -40,7 +40,7 @@ "safari 15.5", "samsung 17.0", "samsung 16.0", - "node 14.0" + "node 18.0" ], "scripts": { "build": "kcd-scripts build --no-ts-defs --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --no-ts-defs --bundle --no-clean", From 2c570553d8f31b008451398152a9bd30bce362b3 Mon Sep 17 00:00:00 2001 From: Craig Morten <124147726+jlp-craigmorten@users.noreply.github.com> Date: Thu, 14 Sep 2023 06:10:01 +0100 Subject: [PATCH 2/3] feat: upgrade aria-query to 5.3.0 (#1241) * feat: upgrade aria-query to 5.3.0 * fix: correctly handle img with empty alt * feat: pin `aria-query` version * chore: add accessibility-alt-text-bot (#1240) * chore: add accessibility-alt-text-bot * fix formatting issues * test: add coverage for footer to confirm it's expected implicit role as contentinfo --------- Co-authored-by: Sebastian Silbermann Co-authored-by: Matan Borenkraout --- .github/workflows/accessibility-alt-text.yml | 28 ++++++++++ package.json | 2 +- .../__snapshots__/role-helpers.js.snap | 52 +++++++++---------- src/__tests__/role-helpers.js | 44 +++++++++------- src/__tests__/role.js | 18 +++++++ src/__tests__/suggestions.js | 6 +-- src/role-helpers.js | 15 ++++-- 7 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 .github/workflows/accessibility-alt-text.yml diff --git a/.github/workflows/accessibility-alt-text.yml b/.github/workflows/accessibility-alt-text.yml new file mode 100644 index 00000000..2b8ea3f1 --- /dev/null +++ b/.github/workflows/accessibility-alt-text.yml @@ -0,0 +1,28 @@ +name: Accessibility-alt-text-bot +on: + issues: + types: [opened, edited] + pull_request: + types: [opened, edited] + issue_comment: + types: [created, edited] + discussion: + types: [created, edited] + discussion_comment: + types: [created, edited] + +permissions: + issues: write + pull-requests: write + discussions: write + +jobs: + accessibility_alt_text_bot: + name: Check alt text is set on issue or pull requests + runs-on: ubuntu-latest + if: + ${{ github.event.issue || github.event.pull_request || + github.event.discussion }} + steps: + - name: Get action 'github/accessibility-alt-text-bot' + uses: github/accessibility-alt-text-bot@v1.2.0 # Set to latest diff --git a/package.json b/package.json index 83d2ab26..b186a6cb 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", + "aria-query": "5.3.0", "chalk": "^4.1.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", diff --git a/src/__tests__/__snapshots__/role-helpers.js.snap b/src/__tests__/__snapshots__/role-helpers.js.snap index 4a8a1f2f..75bbed7f 100644 --- a/src/__tests__/__snapshots__/role-helpers.js.snap +++ b/src/__tests__/__snapshots__/role-helpers.js.snap @@ -52,32 +52,6 @@ Name "": data-testid="a-article" /> --------------------------------------------------- -command: - -Name "": - - -Name "": - - --------------------------------------------------- -menuitem: - -Name "": - - -Name "": - - -------------------------------------------------- list: @@ -216,5 +190,31 @@ Name "": data-testid="a-dd" /> +-------------------------------------------------- +img: + +Name "": + + +Name "a meaningful description": +a meaningful description + +-------------------------------------------------- +presentation: + +Name "": + + -------------------------------------------------- `; diff --git a/src/__tests__/role-helpers.js b/src/__tests__/role-helpers.js index aadc1dc2..1ed32464 100644 --- a/src/__tests__/role-helpers.js +++ b/src/__tests__/role-helpers.js @@ -19,7 +19,7 @@ function setup() {
Banner header
link - invalid link + invalid link
+
Contentinfo footer
`) return { @@ -83,8 +80,6 @@ function setup() { h3: getByTestId('a-h3'), nav: getByTestId('a-nav'), article: getByTestId('a-article'), - menuItem: getByTestId('a-menuitem-1'), - menuItem2: getByTestId('a-menuitem-2'), aUl: getByTestId('a-list'), aLi1: getByTestId('a-list-item-1'), aLi2: getByTestId('a-list-item-2'), @@ -107,6 +102,11 @@ function setup() { dt: getByTestId('a-dt'), dd: getByTestId('a-dd'), header: getByTestId('a-header'), + invalidAnchor: getByTestId('invalid-link'), + unnamedImg: getByTestId('a-img-1'), + presentationImg: getByTestId('a-img-2'), + namedImg: getByTestId('a-img-3'), + footer: getByTestId('a-footer'), } } @@ -118,8 +118,6 @@ test('getRoles returns expected roles for various dom nodes', () => { h3, nav, article, - menuItem, - menuItem2, aUl, aLi1, aLi2, @@ -142,6 +140,12 @@ test('getRoles returns expected roles for various dom nodes', () => { dd, dt, header, + invalidAnchor, + unnamedSection, + unnamedImg, + presentationImg, + namedImg, + footer, } = setup() expect(getRoles(namedSection)).toEqual({ @@ -157,16 +161,20 @@ test('getRoles returns expected roles for various dom nodes', () => { cell: [td1, td2, td3], textbox: [input, input2, textarea], rowgroup: [tbody], - command: [menuItem, menuItem2], - menuitem: [menuItem, menuItem2], form: [namedForm], region: [namedSection], term: [dt], definition: [dd], + generic: [invalidAnchor, unnamedSection], + img: [unnamedImg, namedImg], + presentation: [presentationImg], }) expect(getRoles(header)).toEqual({ banner: [header], }) + expect(getRoles(footer)).toEqual({ + contentinfo: [footer], + }) }) test('logRoles calls console.log with output from prettyRoles', () => { diff --git a/src/__tests__/role.js b/src/__tests__/role.js index 63872cda..fe31c2ea 100644 --- a/src/__tests__/role.js +++ b/src/__tests__/role.js @@ -248,6 +248,12 @@ test('accessible name comparison is case sensitive', () => {

-------------------------------------------------- + emphasis: + + Name "": + + + -------------------------------------------------- Ignored nodes: comments, script, style
@@ -296,6 +302,12 @@ test('TextMatch serialization in error message', () => {

-------------------------------------------------- + emphasis: + + Name "": + + + -------------------------------------------------- Ignored nodes: comments, script, style
@@ -320,6 +332,12 @@ test('TextMatch serialization in error message', () => {

-------------------------------------------------- + emphasis: + + Name "": + + + -------------------------------------------------- Ignored nodes: comments, script, style
diff --git a/src/__tests__/suggestions.js b/src/__tests__/suggestions.js index 9d248ae6..160f7ee5 100644 --- a/src/__tests__/suggestions.js +++ b/src/__tests__/suggestions.js @@ -196,9 +196,9 @@ test('escapes regular expressions in suggestion', () => { const {container} = renderIntoDocument(` -

+ Loading ... (1) -

+ The Problem (picture of a question mark) `) @@ -214,7 +214,7 @@ test('escapes regular expressions in suggestion', () => { ).toString(), ).toEqual(`getByAltText(/the problem \\(picture of a question mark\\)/i)`) - expect(getSuggestedQuery(container.querySelector('p')).toString()).toEqual( + expect(getSuggestedQuery(container.querySelector('span')).toString()).toEqual( `getByText(/loading \\.\\.\\. \\(1\\)/i)`, ) diff --git a/src/role-helpers.js b/src/role-helpers.js index bc134f27..8d7e7cb0 100644 --- a/src/role-helpers.js +++ b/src/role-helpers.js @@ -82,13 +82,18 @@ function buildElementRoleList(elementRolesMap) { return `${name}${attributes .map(({name: attributeName, value, constraints = []}) => { const shouldNotExist = constraints.indexOf('undefined') !== -1 - if (shouldNotExist) { - return `:not([${attributeName}])` - } else if (value) { + const shouldBeNonEmpty = constraints.indexOf('set') !== -1 + const hasExplicitValue = typeof value !== 'undefined' + + if (hasExplicitValue) { return `[${attributeName}="${value}"]` - } else { - return `[${attributeName}]` + } else if (shouldNotExist) { + return `:not([${attributeName}])` + } else if (shouldBeNonEmpty) { + return `[${attributeName}]:not([${attributeName}=""])` } + + return `[${attributeName}]` }) .join('')}` } From 3580f25bd765cedb70889b2cf716085023d8c314 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 3 Oct 2023 11:32:23 +0200 Subject: [PATCH 3/3] fix: use defineProperty on the error object instead of setting the message directly (#1268) Co-authored-by: Julien Wajsberg Fixes #1259 --- src/__tests__/wait-for.js | 25 +++++++++++++++++++++++++ src/wait-for.js | 7 +++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/__tests__/wait-for.js b/src/__tests__/wait-for.js index 03814020..d956525d 100644 --- a/src/__tests__/wait-for.js +++ b/src/__tests__/wait-for.js @@ -148,6 +148,31 @@ test('timeout logs a pretty DOM', async () => { `) }) +test("timeout doesn't error on DOMExceptions", async () => { + renderIntoDocument(`
how pretty
`) + const error = await waitFor( + () => { + throw new DOMException('nooooooo!') + }, + {timeout: 1}, + ).catch(e => e) + expect(error.message).toMatchInlineSnapshot(` + nooooooo! + + Ignored nodes: comments, script, style + + + +
+ how pretty +
+ + + `) +}) + test('should delegate to config.getElementError', async () => { const elementError = new Error('Custom element error') const getElementError = jest.fn().mockImplementation(() => elementError) diff --git a/src/wait-for.js b/src/wait-for.js index 79c53a38..ab2c9989 100644 --- a/src/wait-for.js +++ b/src/wait-for.js @@ -24,10 +24,9 @@ function waitFor( stackTraceError, interval = 50, onTimeout = error => { - error.message = getConfig().getElementError( - error.message, - container, - ).message + Object.defineProperty(error, 'message', { + value: getConfig().getElementError(error.message, container).message, + }) return error }, mutationObserverOptions = {