Skip to content

Commit ab2e0de

Browse files
authored
Merge branch 'master' into alt-text
2 parents 7f1cc69 + f1b61e3 commit ab2e0de

33 files changed

+213
-77
lines changed

.babelrc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
{
2-
"presets": ["es2015"],
3-
"plugins": [
4-
"transform-object-rest-spread",
5-
"transform-flow-strip-types",
6-
]
2+
"presets": [
3+
[
4+
"airbnb",
5+
{
6+
"targets": {
7+
"node": 4
8+
}
9+
}
10+
]
11+
],
12+
"plugins": ["@babel/plugin-transform-flow-strip-types"]
713
}

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ script:
2121
after_success:
2222
- if [ "${TEST-}" = true ]; then npm run coveralls; fi
2323
sudo: false
24+
branches:
25+
only:
26+
- master
2427
env:
2528
global:
2629
- TEST=true
@@ -46,3 +49,5 @@ matrix:
4649
- node_js: "5"
4750
- node_js: "4" # not sure why this is failing; probably something in jest
4851
env: ESLINT=4
52+
- node_js: "4"
53+
env: ESLINT=3

__mocks__/JSXElementMock.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@
44

55
import JSXAttributeMock from './JSXAttributeMock';
66

7+
export type TJSXElementMock = {
8+
type: 'JSXElement',
9+
openingElement: {
10+
type: 'JSXOpeningElement',
11+
name: {
12+
type: 'JSXIdentifier',
13+
name: string,
14+
},
15+
attributes: Array<JSXAttributeMock>,
16+
},
17+
children: Array<Node>,
18+
};
19+
720
export default function JSXElementMock(
821
tagName: string,
922
attributes: Array<JSXAttributeMock> = [],
1023
children: Array<Node> = [],
11-
) {
24+
): TJSXElementMock {
1225
return {
1326
type: 'JSXElement',
1427
openingElement: {

__mocks__/genInteractives.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import includes from 'array-includes';
77
import JSXAttributeMock from './JSXAttributeMock';
88
import JSXElementMock from './JSXElementMock';
99

10+
import type { TJSXElementMock } from './JSXElementMock';
11+
1012
const domElements = [...dom.keys()];
1113
const roleNames = [...roles.keys()];
1214

@@ -149,8 +151,8 @@ export function genElementSymbol(openingElement: Object) {
149151
);
150152
}
151153

152-
export function genInteractiveElements() {
153-
return Object.keys(interactiveElementsMap).map((elementSymbol) => {
154+
export function genInteractiveElements(): Array<TJSXElementMock> {
155+
return Object.keys(interactiveElementsMap).map((elementSymbol: string): TJSXElementMock => {
154156
const bracketIndex = elementSymbol.indexOf('[');
155157
let name = elementSymbol;
156158
if (bracketIndex > -1) {
@@ -161,15 +163,15 @@ export function genInteractiveElements() {
161163
});
162164
}
163165

164-
export function genInteractiveRoleElements() {
165-
return [...interactiveRoles, 'button article', 'fakerole button article'].map(value => JSXElementMock(
166+
export function genInteractiveRoleElements(): Array<TJSXElementMock> {
167+
return [...interactiveRoles, 'button article', 'fakerole button article'].map((value): TJSXElementMock => JSXElementMock(
166168
'div',
167169
[JSXAttributeMock('role', value)],
168170
));
169171
}
170172

171-
export function genNonInteractiveElements() {
172-
return Object.keys(nonInteractiveElementsMap).map((elementSymbol) => {
173+
export function genNonInteractiveElements(): Array<TJSXElementMock> {
174+
return Object.keys(nonInteractiveElementsMap).map((elementSymbol): TJSXElementMock => {
173175
const bracketIndex = elementSymbol.indexOf('[');
174176
let name = elementSymbol;
175177
if (bracketIndex > -1) {
@@ -196,9 +198,9 @@ export function genNonAbstractRoleElements() {
196198
return nonAbstractRoles.map(value => JSXElementMock('div', [JSXAttributeMock('role', value)]));
197199
}
198200

199-
export function genIndeterminantInteractiveElements() {
201+
export function genIndeterminantInteractiveElements(): Array<TJSXElementMock> {
200202
return Object.keys(indeterminantInteractiveElementsMap).map((name) => {
201-
const attributes = indeterminantInteractiveElementsMap[name].map(({ prop, value }) => JSXAttributeMock(prop, value));
203+
const attributes = indeterminantInteractiveElementsMap[name].map(({ prop, value }): TJSXElementMock => JSXAttributeMock(prop, value));
202204
return JSXElementMock(name, attributes);
203205
});
204206
}

__tests__/__util__/parserOptionsMapper.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const defaultParserOptions = {
2-
ecmaVersion: 6,
2+
ecmaVersion: 2018,
33
ecmaFeatures: {
4+
experimentalObjectRestSpread: true,
45
jsx: true,
56
},
67
};

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,15 @@ ruleTester.run('anchor-is-valid', rule, {
8989
{ code: '<a href="/foo" />' },
9090
{ code: '<a href="https://foo.bar.com" />' },
9191
{ code: '<div href="foo" />' },
92+
{ code: '<a href="javascript" />' },
93+
{ code: '<a href="javascriptFoo" />' },
9294
{ code: '<a href={`#foo`}/>' },
9395
{ code: '<a href={"foo"}/>' },
96+
{ code: '<a href={"javascript"}/>' },
97+
{ code: '<a href={`#javascript`}/>' },
9498
{ code: '<a href="#foo" />' },
99+
{ code: '<a href="#javascript" />' },
100+
{ code: '<a href="#javascriptFoo" />' },
95101
{ code: '<UX.Layout>test</UX.Layout>' },
96102
{ code: '<a href={this} />' },
97103

__tests__/src/rules/aria-proptypes-test.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,17 @@ ruleTester.run('aria-proptypes', rule, {
7474
{ code: '<div aria-hidden={!"yes"} />' },
7575
{ code: '<div aria-hidden={foo} />' },
7676
{ code: '<div aria-hidden={foo.bar} />' },
77+
{ code: '<div aria-hidden={null} />' },
78+
{ code: '<div aria-hidden={undefined} />' },
7779
{ code: '<div aria-hidden={<div />} />' },
7880

7981
// STRING
8082
{ code: '<div aria-label="Close" />' },
8183
{ code: '<div aria-label={`Close`} />' },
8284
{ code: '<div aria-label={foo} />' },
8385
{ code: '<div aria-label={foo.bar} />' },
86+
{ code: '<div aria-label={null} />' },
87+
{ code: '<div aria-label={undefined} />' },
8488
{ code: '<input aria-invalid={error ? "true" : "false"} />' },
8589
{ code: '<input aria-invalid={undefined ? "true" : "false"} />' },
8690

@@ -97,6 +101,8 @@ ruleTester.run('aria-proptypes', rule, {
97101
{ code: '<div aria-checked={foo.bar} />' },
98102
{ code: '<div aria-checked="mixed" />' },
99103
{ code: '<div aria-checked={`mixed`} />' },
104+
{ code: '<div aria-checked={null} />' },
105+
{ code: '<div aria-checked={undefined} />' },
100106

101107
// INTEGER
102108
{ code: '<div aria-level={123} />' },
@@ -108,6 +114,8 @@ ruleTester.run('aria-proptypes', rule, {
108114
{ code: '<div aria-level="123" />' },
109115
{ code: '<div aria-level={foo} />' },
110116
{ code: '<div aria-level={foo.bar} />' },
117+
{ code: '<div aria-level={null} />' },
118+
{ code: '<div aria-level={undefined} />' },
111119

112120
// NUMBER
113121
{ code: '<div aria-valuemax={123} />' },
@@ -119,6 +127,8 @@ ruleTester.run('aria-proptypes', rule, {
119127
{ code: '<div aria-valuemax="123" />' },
120128
{ code: '<div aria-valuemax={foo} />' },
121129
{ code: '<div aria-valuemax={foo.bar} />' },
130+
{ code: '<div aria-valuemax={null} />' },
131+
{ code: '<div aria-valuemax={undefined} />' },
122132

123133
// TOKEN
124134
{ code: '<div aria-sort="ascending" />' },
@@ -142,6 +152,8 @@ ruleTester.run('aria-proptypes', rule, {
142152
{ code: '<div aria-invalid="false" />' },
143153
{ code: '<div aria-invalid="grammar" />' },
144154
{ code: '<div aria-invalid="spelling" />' },
155+
{ code: '<div aria-invalid={null} />' },
156+
{ code: '<div aria-invalid={undefined} />' },
145157

146158
// TOKENLIST
147159
{ code: '<div aria-relevant="additions" />' },
@@ -159,6 +171,8 @@ ruleTester.run('aria-proptypes', rule, {
159171
{ code: '<div aria-relevant={`removals additions text all`} />' },
160172
{ code: '<div aria-relevant={foo} />' },
161173
{ code: '<div aria-relevant={foo.bar} />' },
174+
{ code: '<div aria-relevant={null} />' },
175+
{ code: '<div aria-relevant={undefined} />' },
162176

163177
// ID
164178
{ code: '<div aria-activedescendant="ascending" />' },
@@ -176,6 +190,8 @@ ruleTester.run('aria-proptypes', rule, {
176190
{ code: '<div aria-activedescendant={`other`} />' },
177191
{ code: '<div aria-activedescendant={foo} />' },
178192
{ code: '<div aria-activedescendant={foo.bar} />' },
193+
{ code: '<div aria-activedescendant={null} />' },
194+
{ code: '<div aria-activedescendant={undefined} />' },
179195

180196
// IDLIST
181197
{ code: '<div aria-labelledby="additions" />' },
@@ -193,13 +209,11 @@ ruleTester.run('aria-proptypes', rule, {
193209
{ code: '<div aria-labelledby={`removals additions text all`} />' },
194210
{ code: '<div aria-labelledby={foo} />' },
195211
{ code: '<div aria-labelledby={foo.bar} />' },
212+
{ code: '<div aria-labelledby={null} />' },
213+
{ code: '<div aria-labelledby={undefined} />' },
196214
].map(parserOptionsMapper),
197215
invalid: [
198216
// BOOLEAN
199-
{
200-
code: '<div aria-hidden={undefined} />',
201-
errors: [errorMessage('aria-hidden')],
202-
},
203217
{ code: '<div aria-hidden="yes" />', errors: [errorMessage('aria-hidden')] },
204218
{ code: '<div aria-hidden="no" />', errors: [errorMessage('aria-hidden')] },
205219
{ code: '<div aria-hidden={1234} />', errors: [errorMessage('aria-hidden')] },
@@ -209,18 +223,13 @@ ruleTester.run('aria-proptypes', rule, {
209223
},
210224

211225
// STRING
212-
{ code: '<div aria-label={undefined} />', errors: [errorMessage('aria-label')] },
213226
{ code: '<div aria-label />', errors: [errorMessage('aria-label')] },
214227
{ code: '<div aria-label={true} />', errors: [errorMessage('aria-label')] },
215228
{ code: '<div aria-label={false} />', errors: [errorMessage('aria-label')] },
216229
{ code: '<div aria-label={1234} />', errors: [errorMessage('aria-label')] },
217230
{ code: '<div aria-label={!true} />', errors: [errorMessage('aria-label')] },
218231

219232
// TRISTATE
220-
{
221-
code: '<div aria-checked={undefined} />',
222-
errors: [errorMessage('aria-checked')],
223-
},
224233
{ code: '<div aria-checked="yes" />', errors: [errorMessage('aria-checked')] },
225234
{ code: '<div aria-checked="no" />', errors: [errorMessage('aria-checked')] },
226235
{ code: '<div aria-checked={1234} />', errors: [errorMessage('aria-checked')] },
@@ -230,7 +239,6 @@ ruleTester.run('aria-proptypes', rule, {
230239
},
231240

232241
// INTEGER
233-
{ code: '<div aria-level={undefined} />', errors: [errorMessage('aria-level')] },
234242
{ code: '<div aria-level="yes" />', errors: [errorMessage('aria-level')] },
235243
{ code: '<div aria-level="no" />', errors: [errorMessage('aria-level')] },
236244
{ code: '<div aria-level={`abc`} />', errors: [errorMessage('aria-level')] },
@@ -240,10 +248,6 @@ ruleTester.run('aria-proptypes', rule, {
240248
{ code: '<div aria-level={!"false"} />', errors: [errorMessage('aria-level')] },
241249

242250
// NUMBER
243-
{
244-
code: '<div aria-valuemax={undefined} />',
245-
errors: [errorMessage('aria-valuemax')],
246-
},
247251
{ code: '<div aria-valuemax="yes" />', errors: [errorMessage('aria-valuemax')] },
248252
{ code: '<div aria-valuemax="no" />', errors: [errorMessage('aria-valuemax')] },
249253
{
@@ -268,7 +272,6 @@ ruleTester.run('aria-proptypes', rule, {
268272
{ code: '<div aria-sort="" />', errors: [errorMessage('aria-sort')] },
269273
{ code: '<div aria-sort="descnding" />', errors: [errorMessage('aria-sort')] },
270274
{ code: '<div aria-sort />', errors: [errorMessage('aria-sort')] },
271-
{ code: '<div aria-sort={undefined} />', errors: [errorMessage('aria-sort')] },
272275
{ code: '<div aria-sort={true} />', errors: [errorMessage('aria-sort')] },
273276
{ code: '<div aria-sort={"false"} />', errors: [errorMessage('aria-sort')] },
274277
{
@@ -283,10 +286,6 @@ ruleTester.run('aria-proptypes', rule, {
283286
errors: [errorMessage('aria-relevant')],
284287
},
285288
{ code: '<div aria-relevant />', errors: [errorMessage('aria-relevant')] },
286-
{
287-
code: '<div aria-relevant={undefined} />',
288-
errors: [errorMessage('aria-relevant')],
289-
},
290289
{
291290
code: '<div aria-relevant={true} />',
292291
errors: [errorMessage('aria-relevant')],

__tests__/src/rules/control-has-associated-label-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const alwaysValid = [
141141
{ code: '<img />' },
142142
{ code: '<legend />' },
143143
{ code: '<li />' },
144+
{ code: '<link />' },
144145
{ code: '<main />' },
145146
{ code: '<mark />' },
146147
{ code: '<marquee />' },
@@ -254,7 +255,6 @@ const neverValid = [
254255
{ code: '<a href="#" />', errors: [expectedError] },
255256
{ code: '<area href="#" />', errors: [expectedError] },
256257
{ code: '<label />', errors: [expectedError] },
257-
{ code: '<link />', errors: [expectedError] },
258258
{ code: '<menuitem />', errors: [expectedError] },
259259
{ code: '<option />', errors: [expectedError] },
260260
{ code: '<th />', errors: [expectedError] },

__tests__/src/rules/no-access-key-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ ruleTester.run('no-access-key', rule, {
2828
{ code: '<div />;' },
2929
{ code: '<div {...props} />' },
3030
{ code: '<div accessKey={undefined} />' },
31-
{ code: '<div accessKey={`${undefined}`} />' },
32-
{ code: '<div accessKey={`${undefined}${undefined}`} />' },
3331
].map(parserOptionsMapper),
3432
invalid: [
3533
{ code: '<div accesskey="h" />', errors: [expectedError] },
@@ -44,5 +42,7 @@ ruleTester.run('no-access-key', rule, {
4442
},
4543
{ code: '<div accessKey={`This is ${bad}`} />', errors: [expectedError] },
4644
{ code: '<div accessKey={accessKey} />', errors: [expectedError] },
45+
{ code: '<div accessKey={`${undefined}`} />', errors: [expectedError] },
46+
{ code: '<div accessKey={`${undefined}${undefined}`} />', errors: [expectedError] },
4747
].map(parserOptionsMapper),
4848
});

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ const alwaysValid = [
345345
{ code: '<div role="term" />;' },
346346
{ code: '<div role="timer" />;' },
347347
{ code: '<div role="tooltip" />;' },
348+
{ code: '<ul role="list" />;' },
348349
];
349350

350351
const neverValid = [

0 commit comments

Comments
 (0)