Skip to content

Commit f99300c

Browse files
committed
build: update to eslint v9
This change adds support for eslint v9. All three example projects have been updated to use the latest eslint, and the root package's dev and peer deps have been updated. In order to make this work with both v9 and older versions, I had to update the parser options helper to adjust the config passed into the `RuleTester`. It was also necessary update jest to a newer version, in order to resolve eslint's use of `node:fs/promises`. Note: the removed test cases are exact duplicates of other tests. v9 fails tests when its determined to be an exact duplicate.
1 parent 05a5e49 commit f99300c

21 files changed

+174
-88
lines changed

.flowconfig

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<PROJECT_ROOT>/lib/.*
44
<PROJECT_ROOT>/docs/.*
55
<PROJECT_ROOT>/reports/.*
6+
<PROJECT_ROOT>/examples/.*
67
[options]
78
suppress_type=$FlowFixMe

.github/workflows/node-4+.yml

+18-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,30 @@ jobs:
2525
matrix:
2626
node-version: ${{ fromJson(needs.matrix.outputs.latest) }}
2727
eslint:
28+
- 9
2829
- 8
2930
- 7
3031
- 6
3132
- 5
3233
- 4
3334
- 3
3435
exclude:
36+
- node-version: 16
37+
eslint: 9
38+
- node-version: 15
39+
eslint: 9
40+
- node-version: 14
41+
eslint: 9
42+
- node-version: 13
43+
eslint: 9
44+
- node-version: 12
45+
eslint: 9
46+
- node-version: 11
47+
eslint: 9
48+
- node-version: 10
49+
eslint: 9
50+
- node-version: 9
51+
eslint: 9
3552
- node-version: 15
3653
eslint: 8
3754
- node-version: 13
@@ -90,7 +107,7 @@ jobs:
90107
steps:
91108
- uses: actions/checkout@v4
92109
with:
93-
fetch-depth: 0
110+
fetch-depth: 0
94111
- uses: ljharb/actions/node/install@main
95112
name: 'nvm install ${{ matrix.node-version }} && npm install'
96113
env:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import assert from 'assert';
2+
3+
export default assert;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import fs from 'fs/promises';
2+
3+
export default fs;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import fs from 'fs';
2+
3+
export default fs;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import path from 'path';
2+
3+
export default path;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import url from 'url';
2+
3+
export default url;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import util from 'util';
2+
3+
export default util;
+40-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,53 @@
1+
import { version as eslintVersion } from 'eslint/package.json';
2+
import semver from 'semver';
3+
4+
const usingLegacy = semver.major(eslintVersion) < 9;
5+
16
const defaultParserOptions = {
2-
ecmaVersion: 2018,
37
ecmaFeatures: {
48
experimentalObjectRestSpread: true,
59
jsx: true,
610
},
711
};
812

13+
const defaultLegacyParserOptions = {
14+
...defaultParserOptions,
15+
ecmaVersion: 2018,
16+
};
17+
18+
const defaultLanguageOptions = {
19+
ecmaVersion: 'latest',
20+
parserOptions: {
21+
...defaultParserOptions,
22+
},
23+
};
24+
925
export default function parserOptionsMapper({
1026
code,
1127
errors,
1228
options = [],
13-
parserOptions = {},
14-
settings,
29+
languageOptions = {},
30+
settings = {},
1531
}) {
16-
return {
17-
code,
18-
errors,
19-
options,
20-
parserOptions: {
21-
...defaultParserOptions,
22-
...parserOptions,
23-
},
24-
settings,
25-
};
32+
return usingLegacy
33+
? {
34+
code,
35+
errors,
36+
options,
37+
parserOptions: {
38+
...defaultLegacyParserOptions,
39+
...languageOptions,
40+
},
41+
settings,
42+
}
43+
: {
44+
code,
45+
errors,
46+
options,
47+
languageOptions: {
48+
...defaultLanguageOptions,
49+
...languageOptions,
50+
},
51+
settings,
52+
};
2653
}

__tests__/src/rules/anchor-is-valid-test.js

+3-28
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,9 @@ ruleTester.run('anchor-is-valid', rule, {
272272
options: noHrefAspect,
273273
},
274274

275-
// CUSTOM COMPONENTS AND SPECIALLINK AND ASPECT
275+
// CUSTOM COMPONENTS AND SPECIAL LINK AND ASPECT
276276
{ code: '<Anchor hrefLeft={undefined} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
277277
{ code: '<Anchor hrefLeft={null} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
278-
{ code: '<Anchor hrefLeft={undefined} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
279-
{ code: '<Anchor hrefLeft={null} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
280-
{ code: '<Anchor hrefLeft={undefined} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
281-
{ code: '<Anchor hrefLeft={null} />', options: componentsAndSpecialLinkAndInvalidHrefAspect },
282-
283278
)).map(parserOptionsMapper),
284279
invalid: parsers.all([].concat(
285280
// DEFAULT ELEMENT 'a' TESTS
@@ -372,7 +367,7 @@ ruleTester.run('anchor-is-valid', rule, {
372367
options: specialLink,
373368
},
374369

375-
// CUSTOM BOTH COMPONENTS AND SPECIALLINK TESTS
370+
// CUSTOM BOTH COMPONENTS AND SPECIAL LINK TESTS
376371
// NO HREF
377372
{ code: '<Anchor Anchor={undefined} />', errors: [noHrefexpectedError], options: componentsAndSpecialLink },
378373
{ code: '<Anchor hrefLeft={null} />', errors: [noHrefexpectedError], options: componentsAndSpecialLink },
@@ -522,27 +517,7 @@ ruleTester.run('anchor-is-valid', rule, {
522517
errors: [invalidHrefexpectedError],
523518
},
524519

525-
// CUSTOM COMPONENTS AND SPECIALLINK AND ASPECT
526-
{
527-
code: '<Anchor hrefLeft={undefined} />',
528-
options: componentsAndSpecialLinkAndNoHrefAspect,
529-
errors: [noHrefexpectedError],
530-
},
531-
{
532-
code: '<Anchor hrefLeft={null} />',
533-
options: componentsAndSpecialLinkAndNoHrefAspect,
534-
errors: [noHrefexpectedError],
535-
},
536-
{
537-
code: '<Anchor hrefLeft={undefined} />',
538-
options: componentsAndSpecialLinkAndNoHrefAspect,
539-
errors: [noHrefexpectedError],
540-
},
541-
{
542-
code: '<Anchor hrefLeft={null} />',
543-
options: componentsAndSpecialLinkAndNoHrefAspect,
544-
errors: [noHrefexpectedError],
545-
},
520+
// CUSTOM COMPONENTS AND SPECIAL LINK AND ASPECT
546521
{
547522
code: '<Anchor hrefLeft={undefined} />',
548523
options: componentsAndSpecialLinkAndNoHrefAspect,

__tests__/src/rules/img-redundant-alt-test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ ruleTester.run('img-redundant-alt', rule, {
6767
{ code: '<img alt={imageAlt} />' },
6868
{ code: '<img alt={imageAlt.name} />' },
6969
semver.satisfies(eslintVersion, '>= 6') ? [
70-
{ code: '<img alt={imageAlt?.name} />', parserOptions: { ecmaVersion: 2020 } },
71-
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', parserOptions: { ecmaVersion: 2020 } },
70+
{ code: '<img alt={imageAlt?.name} />', languageOptions: { ecmaVersion: 2020 } },
71+
{ code: '<img alt="Doing cool things" aria-hidden={foo?.bar}/>', languageOptions: { ecmaVersion: 2020 } },
7272
] : [],
7373
{ code: '<img alt="Photography" />;' },
7474
{ code: '<img alt="ImageMagick" />;' },

__tests__/src/rules/no-noninteractive-element-interactions-test.js

-2
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ const neverValid = [
336336
{ code: '<tfoot onClick={() => {}} />;', errors: [expectedError] },
337337
{ code: '<thead onClick={() => {}} />;', errors: [expectedError] },
338338
{ code: '<time onClick={() => {}} />;', errors: [expectedError] },
339-
{ code: '<ol onClick={() => {}} />;', errors: [expectedError] },
340339
{ code: '<ul onClick={() => {}} />;', errors: [expectedError] },
341340
{ code: '<ul contentEditable="false" onClick={() => {}} />;', errors: [expectedError] },
342341
{ code: '<article contentEditable onClick={() => {}} />;', errors: [expectedError] },
@@ -345,7 +344,6 @@ const neverValid = [
345344
{ code: '<div role="alert" onClick={() => {}} />;', errors: [expectedError] },
346345
{ code: '<div role="alertdialog" onClick={() => {}} />;', errors: [expectedError] },
347346
{ code: '<div role="application" onClick={() => {}} />;', errors: [expectedError] },
348-
{ code: '<div role="article" onClick={() => {}} />;', errors: [expectedError] },
349347
{ code: '<div role="banner" onClick={() => {}} />;', errors: [expectedError] },
350348
{ code: '<div role="cell" onClick={() => {}} />;', errors: [expectedError] },
351349
{ code: '<div role="complementary" onClick={() => {}} />;', errors: [expectedError] },

__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js

-2
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,6 @@ const neverValid = [
360360
* interactive role. */
361361
{ code: '<main role="button" />;', errors: [expectedError] },
362362
{ code: '<article role="button" />;', errors: [expectedError] },
363-
{ code: '<article role="button" />;', errors: [expectedError] },
364363
{ code: '<aside role="button" />;', errors: [expectedError] },
365364
{ code: '<blockquote role="button" />;', errors: [expectedError] },
366365
{ code: '<body role="button" />;', errors: [expectedError] },
@@ -412,7 +411,6 @@ const neverValid = [
412411
* interactive role. */
413412
{ code: '<main role="menuitem" />;', errors: [expectedError] },
414413
{ code: '<article role="menuitem" />;', errors: [expectedError] },
415-
{ code: '<article role="menuitem" />;', errors: [expectedError] },
416414
{ code: '<dd role="menuitem" />;', errors: [expectedError] },
417415
{ code: '<dfn role="menuitem" />;', errors: [expectedError] },
418416
{ code: '<dt role="menuitem" />;', errors: [expectedError] },

__tests__/src/rules/no-static-element-interactions-test.js

-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ const neverValid = [
304304
{ code: '<content onClick={() => {}} />;', errors: [expectedError] },
305305
{ code: '<data onClick={() => {}} />;', errors: [expectedError] },
306306
{ code: '<del onClick={() => {}} />;', errors: [expectedError] },
307-
{ code: '<div onClick={() => {}} />;', errors: [expectedError] },
308307
{ code: '<em onClick={() => {}} />;', errors: [expectedError] },
309308
{ code: '<font onClick={() => {}} />;', errors: [expectedError] },
310309
{ code: '<frameset onClick={() => {}} />;', errors: [expectedError] },

__tests__/src/rules/prefer-tag-over-role-test.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const expectedError = (role, tag) => ({
1010
type: 'JSXOpeningElement',
1111
});
1212

13-
ruleTester.run('element-role', rule, {
13+
ruleTester.run('prefer-tag-over-role', rule, {
1414
valid: parsers.all([].concat(
1515
{ code: '<div />;' },
1616
{ code: '<div role="unknown" />;' },
@@ -55,10 +55,6 @@ ruleTester.run('element-role', rule, {
5555
code: '<other role="checkbox" />',
5656
errors: [expectedError('checkbox', '<input type="checkbox">')],
5757
},
58-
{
59-
code: '<other role="checkbox" />',
60-
errors: [expectedError('checkbox', '<input type="checkbox">')],
61-
},
6258
{
6359
code: '<div role="banner" />',
6460
errors: [expectedError('banner', '<header>')],
+65-23
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,88 @@
1+
import { version as eslintVersion } from 'eslint/package.json';
12
import expect from 'expect';
3+
import semver from 'semver';
24
import parserOptionsMapper from '../../__util__/parserOptionsMapper';
35

6+
const usingLegacy = semver.major(eslintVersion) < 9;
7+
48
describe('parserOptionsMapper', () => {
59
it('should return an test case object', () => {
610
const testCase = {
711
code: '<div />',
812
errors: [],
913
options: {},
1014
};
11-
expect(parserOptionsMapper(testCase)).toEqual({
12-
code: '<div />',
13-
errors: [],
14-
options: {},
15-
parserOptions: {
16-
ecmaVersion: 2018,
17-
ecmaFeatures: {
18-
experimentalObjectRestSpread: true,
19-
jsx: true,
15+
16+
const expectedResult = usingLegacy
17+
? {
18+
code: '<div />',
19+
errors: [],
20+
options: {},
21+
parserOptions: {
22+
ecmaVersion: 2018,
23+
ecmaFeatures: {
24+
experimentalObjectRestSpread: true,
25+
jsx: true,
26+
},
2027
},
21-
},
22-
});
28+
settings: {},
29+
}
30+
: {
31+
code: '<div />',
32+
errors: [],
33+
options: {},
34+
languageOptions: {
35+
ecmaVersion: 'latest',
36+
parserOptions: {
37+
ecmaFeatures: {
38+
experimentalObjectRestSpread: true,
39+
jsx: true,
40+
},
41+
},
42+
},
43+
settings: {},
44+
};
45+
expect(parserOptionsMapper(testCase)).toEqual(expectedResult);
2346
});
2447
it('should allow for overriding parserOptions', () => {
2548
const testCase = {
2649
code: '<div />',
2750
errors: [],
2851
options: {},
29-
parserOptions: {
52+
languageOptions: {
3053
ecmaVersion: 5,
3154
},
3255
};
33-
expect(parserOptionsMapper(testCase)).toEqual({
34-
code: '<div />',
35-
errors: [],
36-
options: {},
37-
parserOptions: {
38-
ecmaVersion: 5,
39-
ecmaFeatures: {
40-
experimentalObjectRestSpread: true,
41-
jsx: true,
56+
57+
const expectedResult = usingLegacy
58+
? {
59+
code: '<div />',
60+
errors: [],
61+
options: {},
62+
parserOptions: {
63+
ecmaVersion: 5,
64+
ecmaFeatures: {
65+
experimentalObjectRestSpread: true,
66+
jsx: true,
67+
},
4268
},
43-
},
44-
});
69+
settings: {},
70+
}
71+
: {
72+
code: '<div />',
73+
errors: [],
74+
options: {},
75+
languageOptions: {
76+
ecmaVersion: 5,
77+
parserOptions: {
78+
ecmaFeatures: {
79+
experimentalObjectRestSpread: true,
80+
jsx: true,
81+
},
82+
},
83+
},
84+
settings: {},
85+
};
86+
expect(parserOptionsMapper(testCase)).toEqual(expectedResult);
4587
});
4688
});

examples/flat-cjs/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"react-dom": "^18.2.0"
1212
},
1313
"devDependencies": {
14-
"@eslint/js": "^9.5.0",
14+
"@eslint/js": "^9.9.1",
1515
"cross-env": "^7.0.3",
16-
"eslint": "^8.57.0",
16+
"eslint": "^9.9.1",
1717
"eslint-plugin-jsx-a11y": "file:../..",
1818
"globals": "^15.6.0"
1919
}

examples/flat-esm/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"react-dom": "^18.2.0"
1212
},
1313
"devDependencies": {
14-
"@eslint/js": "^9.5.0",
14+
"@eslint/js": "^9.9.1",
1515
"cross-env": "^7.0.3",
16-
"eslint": "^8.57.0",
16+
"eslint": "^9.9.1",
1717
"eslint-plugin-jsx-a11y": "file:../..",
1818
"globals": "^15.6.0"
1919
}

0 commit comments

Comments
 (0)