@arcaauth/eslint-plugin-jsx-a11y 6.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/.babelrc +17 -0
  2. package/.eslintrc +44 -0
  3. package/CHANGELOG.md +774 -0
  4. package/LICENSE.md +8 -0
  5. package/README.md +423 -0
  6. package/__mocks__/IdentifierMock.js +15 -0
  7. package/__mocks__/JSXAttributeMock.js +39 -0
  8. package/__mocks__/JSXElementMock.js +37 -0
  9. package/__mocks__/JSXExpressionContainerMock.js +15 -0
  10. package/__mocks__/JSXSpreadAttributeMock.js +18 -0
  11. package/__mocks__/JSXTextMock.js +17 -0
  12. package/__mocks__/LiteralMock.js +17 -0
  13. package/__mocks__/genInteractives.js +218 -0
  14. package/__tests__/__util__/axeMapping.js +6 -0
  15. package/__tests__/__util__/helpers/getESLintCoreRule.js +9 -0
  16. package/__tests__/__util__/helpers/parsers.js +186 -0
  17. package/__tests__/__util__/parserOptionsMapper.js +53 -0
  18. package/__tests__/__util__/ruleOptionsMapperFactory.js +33 -0
  19. package/__tests__/index-test.js +40 -0
  20. package/__tests__/src/rules/accessible-emoji-test.js +66 -0
  21. package/__tests__/src/rules/alt-text-test.js +291 -0
  22. package/__tests__/src/rules/anchor-ambiguous-text-test.js +117 -0
  23. package/__tests__/src/rules/anchor-has-content-test.js +54 -0
  24. package/__tests__/src/rules/anchor-is-valid-test.js +532 -0
  25. package/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js +95 -0
  26. package/__tests__/src/rules/aria-props-test.js +69 -0
  27. package/__tests__/src/rules/aria-proptypes-test.js +311 -0
  28. package/__tests__/src/rules/aria-role-test.js +118 -0
  29. package/__tests__/src/rules/aria-unsupported-elements-test.js +75 -0
  30. package/__tests__/src/rules/autocomplete-valid-test.js +77 -0
  31. package/__tests__/src/rules/click-events-have-key-events-test.js +77 -0
  32. package/__tests__/src/rules/control-has-associated-label-test.js +327 -0
  33. package/__tests__/src/rules/heading-has-content-test.js +85 -0
  34. package/__tests__/src/rules/html-has-lang-test.js +42 -0
  35. package/__tests__/src/rules/iframe-has-title-test.js +55 -0
  36. package/__tests__/src/rules/img-redundant-alt-test.js +137 -0
  37. package/__tests__/src/rules/interactive-supports-focus-test.js +267 -0
  38. package/__tests__/src/rules/label-has-associated-control-test.js +243 -0
  39. package/__tests__/src/rules/label-has-for-test.js +235 -0
  40. package/__tests__/src/rules/lang-test.js +59 -0
  41. package/__tests__/src/rules/media-has-caption-test.js +220 -0
  42. package/__tests__/src/rules/mouse-events-have-key-events-test.js +154 -0
  43. package/__tests__/src/rules/no-access-key-test.js +48 -0
  44. package/__tests__/src/rules/no-aria-hidden-on-focusable-test.js +44 -0
  45. package/__tests__/src/rules/no-autofocus-test.js +68 -0
  46. package/__tests__/src/rules/no-distracting-elements-test.js +51 -0
  47. package/__tests__/src/rules/no-interactive-element-to-noninteractive-role-test.js +405 -0
  48. package/__tests__/src/rules/no-noninteractive-element-interactions-test.js +502 -0
  49. package/__tests__/src/rules/no-noninteractive-element-to-interactive-role-test.js +500 -0
  50. package/__tests__/src/rules/no-noninteractive-tabindex-test.js +123 -0
  51. package/__tests__/src/rules/no-onchange-test.js +57 -0
  52. package/__tests__/src/rules/no-redundant-roles-test.js +98 -0
  53. package/__tests__/src/rules/no-static-element-interactions-test.js +501 -0
  54. package/__tests__/src/rules/prefer-tag-over-role-test.js +63 -0
  55. package/__tests__/src/rules/role-has-required-aria-props-test.js +134 -0
  56. package/__tests__/src/rules/role-supports-aria-props-test.js +570 -0
  57. package/__tests__/src/rules/scope-test.js +50 -0
  58. package/__tests__/src/rules/tabindex-no-positive-test.js +55 -0
  59. package/__tests__/src/util/attributesComparator-test.js +91 -0
  60. package/__tests__/src/util/getAccessibleChildText-test.js +174 -0
  61. package/__tests__/src/util/getComputedRole-test.js +71 -0
  62. package/__tests__/src/util/getElementType-test.js +154 -0
  63. package/__tests__/src/util/getExplicitRole-test.js +35 -0
  64. package/__tests__/src/util/getImplicitRole-test.js +25 -0
  65. package/__tests__/src/util/getSuggestion-test.js +33 -0
  66. package/__tests__/src/util/getTabIndex-test.js +85 -0
  67. package/__tests__/src/util/hasAccessibleChild-test.js +157 -0
  68. package/__tests__/src/util/implicitRoles/input-test.js +87 -0
  69. package/__tests__/src/util/implicitRoles/menu-test.js +20 -0
  70. package/__tests__/src/util/implicitRoles/menuitem-test.js +38 -0
  71. package/__tests__/src/util/isAbstractRole-test.js +51 -0
  72. package/__tests__/src/util/isContentEditable-test.js +52 -0
  73. package/__tests__/src/util/isDOMElement-test.js +30 -0
  74. package/__tests__/src/util/isDisabledElement-test.js +88 -0
  75. package/__tests__/src/util/isFocusable-test.js +111 -0
  76. package/__tests__/src/util/isInteractiveElement-test.js +104 -0
  77. package/__tests__/src/util/isInteractiveRole-test.js +59 -0
  78. package/__tests__/src/util/isNonInteractiveElement-test.js +97 -0
  79. package/__tests__/src/util/isNonInteractiveRole-test.js +59 -0
  80. package/__tests__/src/util/isNonLiteralProperty-test.js +52 -0
  81. package/__tests__/src/util/isSemanticRoleElement-test.js +72 -0
  82. package/__tests__/src/util/mayContainChildComponent-test.js +219 -0
  83. package/__tests__/src/util/mayHaveAccessibleLabel-test.js +256 -0
  84. package/__tests__/src/util/parserOptionsMapper-test.js +93 -0
  85. package/__tests__/src/util/schemas-test.js +35 -0
  86. package/docs/rules/accessible-emoji.md +30 -0
  87. package/docs/rules/alt-text.md +168 -0
  88. package/docs/rules/anchor-ambiguous-text.md +91 -0
  89. package/docs/rules/anchor-has-content.md +64 -0
  90. package/docs/rules/anchor-is-valid.md +270 -0
  91. package/docs/rules/aria-activedescendant-has-tabindex.md +52 -0
  92. package/docs/rules/aria-props.md +29 -0
  93. package/docs/rules/aria-proptypes.md +30 -0
  94. package/docs/rules/aria-role.md +51 -0
  95. package/docs/rules/aria-unsupported-elements.md +30 -0
  96. package/docs/rules/autocomplete-valid.md +49 -0
  97. package/docs/rules/click-events-have-key-events.md +28 -0
  98. package/docs/rules/control-has-associated-label.md +113 -0
  99. package/docs/rules/heading-has-content.md +67 -0
  100. package/docs/rules/html-has-lang.md +31 -0
  101. package/docs/rules/iframe-has-title.md +37 -0
  102. package/docs/rules/img-redundant-alt.md +48 -0
  103. package/docs/rules/interactive-supports-focus.md +156 -0
  104. package/docs/rules/label-has-associated-control.md +152 -0
  105. package/docs/rules/label-has-for.md +130 -0
  106. package/docs/rules/lang.md +31 -0
  107. package/docs/rules/media-has-caption.md +48 -0
  108. package/docs/rules/mouse-events-have-key-events.md +58 -0
  109. package/docs/rules/no-access-key.md +30 -0
  110. package/docs/rules/no-aria-hidden-on-focusable.md +37 -0
  111. package/docs/rules/no-autofocus.md +43 -0
  112. package/docs/rules/no-distracting-elements.md +41 -0
  113. package/docs/rules/no-interactive-element-to-noninteractive-role.md +73 -0
  114. package/docs/rules/no-noninteractive-element-interactions.md +145 -0
  115. package/docs/rules/no-noninteractive-element-to-interactive-role.md +76 -0
  116. package/docs/rules/no-noninteractive-tabindex.md +115 -0
  117. package/docs/rules/no-onchange.md +36 -0
  118. package/docs/rules/no-redundant-roles.md +46 -0
  119. package/docs/rules/no-static-element-interactions.md +114 -0
  120. package/docs/rules/prefer-tag-over-role.md +32 -0
  121. package/docs/rules/role-has-required-aria-props.md +31 -0
  122. package/docs/rules/role-supports-aria-props.md +39 -0
  123. package/docs/rules/scope.md +30 -0
  124. package/docs/rules/tabindex-no-positive.md +32 -0
  125. package/lib/configs/flat-config-base.js +11 -0
  126. package/lib/configs/legacy-config-base.js +9 -0
  127. package/lib/index.js +209 -0
  128. package/lib/rules/accessible-emoji.js +63 -0
  129. package/lib/rules/alt-text.js +218 -0
  130. package/lib/rules/anchor-ambiguous-text.js +64 -0
  131. package/lib/rules/anchor-has-content.js +60 -0
  132. package/lib/rules/anchor-is-valid.js +122 -0
  133. package/lib/rules/aria-activedescendant-has-tabindex.js +66 -0
  134. package/lib/rules/aria-props.js +59 -0
  135. package/lib/rules/aria-proptypes.js +114 -0
  136. package/lib/rules/aria-role.js +89 -0
  137. package/lib/rules/aria-unsupported-elements.js +64 -0
  138. package/lib/rules/autocomplete-valid.js +67 -0
  139. package/lib/rules/click-events-have-key-events.js +68 -0
  140. package/lib/rules/control-has-associated-label.js +103 -0
  141. package/lib/rules/heading-has-content.js +61 -0
  142. package/lib/rules/html-has-lang.js +50 -0
  143. package/lib/rules/iframe-has-title.js +50 -0
  144. package/lib/rules/img-redundant-alt.js +88 -0
  145. package/lib/rules/interactive-supports-focus.js +87 -0
  146. package/lib/rules/label-has-associated-control.js +127 -0
  147. package/lib/rules/label-has-for.js +150 -0
  148. package/lib/rules/lang.js +68 -0
  149. package/lib/rules/media-has-caption.js +96 -0
  150. package/lib/rules/mouse-events-have-key-events.js +94 -0
  151. package/lib/rules/no-access-key.js +43 -0
  152. package/lib/rules/no-aria-hidden-on-focusable.js +47 -0
  153. package/lib/rules/no-autofocus.js +62 -0
  154. package/lib/rules/no-distracting-elements.js +54 -0
  155. package/lib/rules/no-interactive-element-to-noninteractive-role.js +81 -0
  156. package/lib/rules/no-noninteractive-element-interactions.js +95 -0
  157. package/lib/rules/no-noninteractive-element-to-interactive-role.js +80 -0
  158. package/lib/rules/no-noninteractive-tabindex.js +109 -0
  159. package/lib/rules/no-onchange.js +52 -0
  160. package/lib/rules/no-redundant-roles.js +86 -0
  161. package/lib/rules/no-static-element-interactions.js +102 -0
  162. package/lib/rules/prefer-tag-over-role.js +75 -0
  163. package/lib/rules/role-has-required-aria-props.js +88 -0
  164. package/lib/rules/role-supports-aria-props.js +78 -0
  165. package/lib/rules/scope.js +58 -0
  166. package/lib/rules/tabindex-no-positive.js +53 -0
  167. package/lib/util/attributesComparator.js +34 -0
  168. package/lib/util/getAccessibleChildText.js +55 -0
  169. package/lib/util/getComputedRole.js +19 -0
  170. package/lib/util/getElementType.js +30 -0
  171. package/lib/util/getExplicitRole.js +27 -0
  172. package/lib/util/getImplicitRole.js +24 -0
  173. package/lib/util/getSuggestion.js +32 -0
  174. package/lib/util/getTabIndex.js +34 -0
  175. package/lib/util/hasAccessibleChild.js +30 -0
  176. package/lib/util/implicitRoles/a.js +17 -0
  177. package/lib/util/implicitRoles/area.js +17 -0
  178. package/lib/util/implicitRoles/article.js +13 -0
  179. package/lib/util/implicitRoles/aside.js +13 -0
  180. package/lib/util/implicitRoles/body.js +13 -0
  181. package/lib/util/implicitRoles/button.js +13 -0
  182. package/lib/util/implicitRoles/datalist.js +13 -0
  183. package/lib/util/implicitRoles/details.js +13 -0
  184. package/lib/util/implicitRoles/dialog.js +13 -0
  185. package/lib/util/implicitRoles/form.js +13 -0
  186. package/lib/util/implicitRoles/h1.js +13 -0
  187. package/lib/util/implicitRoles/h2.js +13 -0
  188. package/lib/util/implicitRoles/h3.js +13 -0
  189. package/lib/util/implicitRoles/h4.js +13 -0
  190. package/lib/util/implicitRoles/h5.js +13 -0
  191. package/lib/util/implicitRoles/h6.js +13 -0
  192. package/lib/util/implicitRoles/hr.js +13 -0
  193. package/lib/util/implicitRoles/img.js +31 -0
  194. package/lib/util/implicitRoles/index.js +82 -0
  195. package/lib/util/implicitRoles/input.js +38 -0
  196. package/lib/util/implicitRoles/li.js +13 -0
  197. package/lib/util/implicitRoles/link.js +17 -0
  198. package/lib/util/implicitRoles/menu.js +19 -0
  199. package/lib/util/implicitRoles/menuitem.js +28 -0
  200. package/lib/util/implicitRoles/meter.js +13 -0
  201. package/lib/util/implicitRoles/nav.js +13 -0
  202. package/lib/util/implicitRoles/ol.js +13 -0
  203. package/lib/util/implicitRoles/option.js +13 -0
  204. package/lib/util/implicitRoles/output.js +13 -0
  205. package/lib/util/implicitRoles/progress.js +13 -0
  206. package/lib/util/implicitRoles/section.js +13 -0
  207. package/lib/util/implicitRoles/select.js +13 -0
  208. package/lib/util/implicitRoles/tbody.js +13 -0
  209. package/lib/util/implicitRoles/textarea.js +13 -0
  210. package/lib/util/implicitRoles/tfoot.js +13 -0
  211. package/lib/util/implicitRoles/thead.js +13 -0
  212. package/lib/util/implicitRoles/ul.js +13 -0
  213. package/lib/util/isAbstractRole.js +23 -0
  214. package/lib/util/isContentEditable.js +13 -0
  215. package/lib/util/isDOMElement.js +15 -0
  216. package/lib/util/isDisabledElement.js +23 -0
  217. package/lib/util/isFocusable.js +23 -0
  218. package/lib/util/isHiddenFromScreenReader.js +26 -0
  219. package/lib/util/isInteractiveElement.js +116 -0
  220. package/lib/util/isInteractiveRole.js +54 -0
  221. package/lib/util/isNonInteractiveElement.js +131 -0
  222. package/lib/util/isNonInteractiveRole.js +55 -0
  223. package/lib/util/isNonLiteralProperty.js +29 -0
  224. package/lib/util/isPresentationRole.js +13 -0
  225. package/lib/util/isSemanticRoleElement.js +54 -0
  226. package/lib/util/mayContainChildComponent.js +50 -0
  227. package/lib/util/mayHaveAccessibleLabel.js +95 -0
  228. package/lib/util/schemas.js +52 -0
  229. package/package.json +120 -0
@@ -0,0 +1,111 @@
1
+ import test from 'tape';
2
+ import { elementType } from 'jsx-ast-utils';
3
+
4
+ import isFocusable from '../../../src/util/isFocusable';
5
+ import {
6
+ genElementSymbol,
7
+ genInteractiveElements,
8
+ genNonInteractiveElements,
9
+ } from '../../../__mocks__/genInteractives';
10
+ import JSXAttributeMock from '../../../__mocks__/JSXAttributeMock';
11
+
12
+ function mergeTabIndex(index, attributes) {
13
+ return [].concat(attributes, JSXAttributeMock('tabIndex', index));
14
+ }
15
+
16
+ test('isFocusable', (t) => {
17
+ t.test('interactive elements', (st) => {
18
+ genInteractiveElements().forEach(({ openingElement }) => {
19
+ st.equal(
20
+ isFocusable(
21
+ elementType(openingElement),
22
+ openingElement.attributes,
23
+ ),
24
+ true,
25
+ `identifies \`${genElementSymbol(openingElement)}\` as a focusable element`,
26
+ );
27
+
28
+ st.equal(
29
+ isFocusable(
30
+ elementType(openingElement),
31
+ mergeTabIndex(-1, openingElement.attributes),
32
+ ),
33
+ false,
34
+ `does NOT identify \`${genElementSymbol(openingElement)}\` with tabIndex of -1 as a focusable element`,
35
+ );
36
+
37
+ st.equal(
38
+ isFocusable(
39
+ elementType(openingElement),
40
+ mergeTabIndex(0, openingElement.attributes),
41
+ ),
42
+ true,
43
+ `identifies \`${genElementSymbol(openingElement)}\` with tabIndex of 0 as a focusable element`,
44
+ );
45
+
46
+ st.equal(
47
+ isFocusable(
48
+ elementType(openingElement),
49
+ mergeTabIndex(1, openingElement.attributes),
50
+ ),
51
+ true,
52
+ `identifies \`${genElementSymbol(openingElement)}\` with tabIndex of 1 as a focusable element`,
53
+ );
54
+ });
55
+
56
+ st.end();
57
+ });
58
+
59
+ t.test('non-interactive elements', (st) => {
60
+ genNonInteractiveElements().forEach(({ openingElement }) => {
61
+ st.equal(
62
+ isFocusable(
63
+ elementType(openingElement),
64
+ openingElement.attributes,
65
+ ),
66
+ false,
67
+ `does NOT identify \`${genElementSymbol(openingElement)}\` as a focusable element`,
68
+ );
69
+
70
+ st.equal(
71
+ isFocusable(
72
+ elementType(openingElement),
73
+ mergeTabIndex(-1, openingElement.attributes),
74
+ ),
75
+ false,
76
+ `does NOT identify \`${genElementSymbol(openingElement)}\` with tabIndex of -1 as a focusable element`,
77
+ );
78
+
79
+ st.equal(
80
+ isFocusable(
81
+ elementType(openingElement),
82
+ mergeTabIndex(0, openingElement.attributes),
83
+ ),
84
+ true,
85
+ `identifies \`${genElementSymbol(openingElement)}\` with tabIndex of 0 as a focusable element`,
86
+ );
87
+
88
+ st.equal(
89
+ isFocusable(
90
+ elementType(openingElement),
91
+ mergeTabIndex(1, openingElement.attributes),
92
+ ),
93
+ true,
94
+ `identifies \`${genElementSymbol(openingElement)}\` with tabIndex of 1 as a focusable element`,
95
+ );
96
+
97
+ st.equal(
98
+ isFocusable(
99
+ elementType(openingElement),
100
+ mergeTabIndex('bogus', openingElement.attributes),
101
+ ),
102
+ false,
103
+ `does NOT identify \`${genElementSymbol(openingElement)}\` with tabIndex of 'bogus' as a focusable element`,
104
+ );
105
+ });
106
+
107
+ st.end();
108
+ });
109
+
110
+ t.end();
111
+ });
@@ -0,0 +1,104 @@
1
+ import test from 'tape';
2
+ import { elementType } from 'jsx-ast-utils';
3
+
4
+ import isInteractiveElement from '../../../src/util/isInteractiveElement';
5
+ import JSXElementMock from '../../../__mocks__/JSXElementMock';
6
+ import {
7
+ genElementSymbol,
8
+ genIndeterminantInteractiveElements,
9
+ genInteractiveElements,
10
+ genInteractiveRoleElements,
11
+ genNonInteractiveElements,
12
+ genNonInteractiveRoleElements,
13
+ } from '../../../__mocks__/genInteractives';
14
+
15
+ test('isInteractiveElement', (t) => {
16
+ t.equal(
17
+ isInteractiveElement(undefined, []),
18
+ false,
19
+ 'identifies them as interactive elements',
20
+ );
21
+
22
+ t.test('interactive elements', (st) => {
23
+ genInteractiveElements().forEach(({ openingElement }) => {
24
+ st.equal(
25
+ isInteractiveElement(
26
+ elementType(openingElement),
27
+ openingElement.attributes,
28
+ ),
29
+ true,
30
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive element`,
31
+ );
32
+ });
33
+
34
+ st.end();
35
+ });
36
+
37
+ t.test('interactive role elements', (st) => {
38
+ genInteractiveRoleElements().forEach(({ openingElement }) => {
39
+ st.equal(
40
+ isInteractiveElement(
41
+ elementType(openingElement),
42
+ openingElement.attributes,
43
+ ),
44
+ false,
45
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive element`,
46
+ );
47
+ });
48
+
49
+ st.end();
50
+ });
51
+
52
+ t.test('non-interactive elements', (st) => {
53
+ genNonInteractiveElements().forEach(({ openingElement }) => {
54
+ st.equal(
55
+ isInteractiveElement(
56
+ elementType(openingElement),
57
+ openingElement.attributes,
58
+ ),
59
+ false,
60
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive element`,
61
+ );
62
+ });
63
+
64
+ st.end();
65
+ });
66
+
67
+ t.test('non-interactive role elements', (st) => {
68
+ genNonInteractiveRoleElements().forEach(({ openingElement }) => {
69
+ st.equal(
70
+ isInteractiveElement(
71
+ elementType(openingElement),
72
+ openingElement.attributes,
73
+ ),
74
+ false,
75
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive element`,
76
+ );
77
+ });
78
+
79
+ st.end();
80
+ });
81
+
82
+ t.test('indeterminate elements', (st) => {
83
+ genIndeterminantInteractiveElements().forEach(({ openingElement }) => {
84
+ st.equal(
85
+ isInteractiveElement(
86
+ elementType(openingElement),
87
+ openingElement.attributes,
88
+ ),
89
+ false,
90
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive element`,
91
+ );
92
+ });
93
+
94
+ st.end();
95
+ });
96
+
97
+ t.equal(
98
+ isInteractiveElement('CustomComponent', JSXElementMock()),
99
+ false,
100
+ 'JSX elements are not interactive',
101
+ );
102
+
103
+ t.end();
104
+ });
@@ -0,0 +1,59 @@
1
+ import test from 'tape';
2
+ import { elementType } from 'jsx-ast-utils';
3
+
4
+ import isInteractiveRole from '../../../src/util/isInteractiveRole';
5
+ import {
6
+ genElementSymbol,
7
+ genInteractiveRoleElements,
8
+ genNonInteractiveRoleElements,
9
+ } from '../../../__mocks__/genInteractives';
10
+
11
+ test('isInteractiveRole', (t) => {
12
+ t.equal(
13
+ isInteractiveRole(undefined, []),
14
+ false,
15
+ 'identifies JSX Components (no tagName) as interactive role elements',
16
+ );
17
+
18
+ t.test('elements with a non-interactive role', (st) => {
19
+ genNonInteractiveRoleElements().forEach(({ openingElement }) => {
20
+ const { attributes } = openingElement;
21
+
22
+ st.equal(
23
+ isInteractiveRole(
24
+ elementType(openingElement),
25
+ attributes,
26
+ ),
27
+ false,
28
+ `does NOT identify \`${genElementSymbol(openingElement)}\` as an interactive role element`,
29
+ );
30
+ });
31
+
32
+ st.end();
33
+ });
34
+
35
+ t.equal(
36
+ isInteractiveRole('div', []),
37
+ false,
38
+ 'does NOT identify elements without a role as interactive role elements',
39
+ );
40
+
41
+ t.test('elements with an interactive role', (st) => {
42
+ genInteractiveRoleElements().forEach(({ openingElement }) => {
43
+ const { attributes } = openingElement;
44
+
45
+ st.equal(
46
+ isInteractiveRole(
47
+ elementType(openingElement),
48
+ attributes,
49
+ ),
50
+ true,
51
+ `identifies \`${genElementSymbol(openingElement)}\` as an interactive role element`,
52
+ );
53
+ });
54
+
55
+ st.end();
56
+ });
57
+
58
+ t.end();
59
+ });
@@ -0,0 +1,97 @@
1
+ import test from 'tape';
2
+ import { elementType } from 'jsx-ast-utils';
3
+
4
+ import isNonInteractiveElement from '../../../src/util/isNonInteractiveElement';
5
+ import {
6
+ genElementSymbol,
7
+ genIndeterminantInteractiveElements,
8
+ genInteractiveElements,
9
+ genInteractiveRoleElements,
10
+ genNonInteractiveElements,
11
+ genNonInteractiveRoleElements,
12
+ } from '../../../__mocks__/genInteractives';
13
+
14
+ test('isNonInteractiveElement', (t) => {
15
+ t.equal(
16
+ isNonInteractiveElement(undefined, []),
17
+ false,
18
+ 'identifies JSX Components (no tagName) as non-interactive elements',
19
+ );
20
+
21
+ t.test('non-interactive elements', (st) => {
22
+ genNonInteractiveElements().forEach(({ openingElement }) => {
23
+ st.equal(
24
+ isNonInteractiveElement(
25
+ elementType(openingElement),
26
+ openingElement.attributes,
27
+ ),
28
+ true,
29
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive element`,
30
+ );
31
+ });
32
+
33
+ st.end();
34
+ });
35
+
36
+ t.test('non-interactive role elements', (st) => {
37
+ genNonInteractiveRoleElements().forEach(({ openingElement }) => {
38
+ st.equal(
39
+ isNonInteractiveElement(
40
+ elementType(openingElement),
41
+ openingElement.attributes,
42
+ ),
43
+ false,
44
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive element`,
45
+ );
46
+ });
47
+
48
+ st.end();
49
+ });
50
+
51
+ t.test('interactive elements', (st) => {
52
+ genInteractiveElements().forEach(({ openingElement }) => {
53
+ st.equal(
54
+ isNonInteractiveElement(
55
+ elementType(openingElement),
56
+ openingElement.attributes,
57
+ ),
58
+ false,
59
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive element`,
60
+ );
61
+ });
62
+
63
+ st.end();
64
+ });
65
+
66
+ t.test('interactive role elements', (st) => {
67
+ genInteractiveRoleElements().forEach(({ openingElement }) => {
68
+ st.equal(
69
+ isNonInteractiveElement(
70
+ elementType(openingElement),
71
+ openingElement.attributes,
72
+ ),
73
+ false,
74
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive element`,
75
+ );
76
+ });
77
+
78
+ st.end();
79
+ });
80
+
81
+ t.test('indeterminate elements', (st) => {
82
+ genIndeterminantInteractiveElements().forEach(({ openingElement }) => {
83
+ st.equal(
84
+ isNonInteractiveElement(
85
+ elementType(openingElement),
86
+ openingElement.attributes,
87
+ ),
88
+ false,
89
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive element`,
90
+ );
91
+ });
92
+
93
+ st.end();
94
+ });
95
+
96
+ t.end();
97
+ });
@@ -0,0 +1,59 @@
1
+ import test from 'tape';
2
+ import { elementType } from 'jsx-ast-utils';
3
+
4
+ import isNonInteractiveRole from '../../../src/util/isNonInteractiveRole';
5
+ import {
6
+ genElementSymbol,
7
+ genInteractiveRoleElements,
8
+ genNonInteractiveRoleElements,
9
+ } from '../../../__mocks__/genInteractives';
10
+
11
+ test('isNonInteractiveRole', (t) => {
12
+ t.equal(
13
+ isNonInteractiveRole(undefined, []),
14
+ false,
15
+ 'identifies JSX Components (no tagName) as non-interactive elements',
16
+ );
17
+
18
+ t.test('elements with a non-interactive role', (st) => {
19
+ genNonInteractiveRoleElements().forEach(({ openingElement }) => {
20
+ const { attributes } = openingElement;
21
+
22
+ st.equal(
23
+ isNonInteractiveRole(
24
+ elementType(openingElement),
25
+ attributes,
26
+ ),
27
+ true,
28
+ `identifies \`${genElementSymbol(openingElement)}\` as a non-interactive role element`,
29
+ );
30
+ });
31
+
32
+ st.end();
33
+ });
34
+
35
+ t.equal(
36
+ isNonInteractiveRole('div', []),
37
+ false,
38
+ 'does NOT identify elements without a role as non-interactive role elements',
39
+ );
40
+
41
+ t.test('elements with an interactive role', (st) => {
42
+ genInteractiveRoleElements().forEach(({ openingElement }) => {
43
+ const { attributes } = openingElement;
44
+
45
+ st.equal(
46
+ isNonInteractiveRole(
47
+ elementType(openingElement),
48
+ attributes,
49
+ ),
50
+ false,
51
+ `does NOT identify \`${genElementSymbol(openingElement)}\` as a non-interactive role element`,
52
+ );
53
+ });
54
+
55
+ st.end();
56
+ });
57
+
58
+ t.end();
59
+ });
@@ -0,0 +1,52 @@
1
+ import test from 'tape';
2
+
3
+ import isNonLiteralProperty from '../../../src/util/isNonLiteralProperty';
4
+ import IdentifierMock from '../../../__mocks__/IdentifierMock';
5
+ import JSXAttributeMock from '../../../__mocks__/JSXAttributeMock';
6
+ import JSXSpreadAttributeMock from '../../../__mocks__/JSXSpreadAttributeMock';
7
+ import JSXTextMock from '../../../__mocks__/JSXTextMock';
8
+ import LiteralMock from '../../../__mocks__/LiteralMock';
9
+
10
+ const theProp = 'theProp';
11
+
12
+ const spread = JSXSpreadAttributeMock('theSpread');
13
+
14
+ test('isNonLiteralProperty', (t) => {
15
+ t.equal(
16
+ isNonLiteralProperty([], theProp),
17
+ false,
18
+ 'does not identify them as non-literal role elements',
19
+ );
20
+
21
+ t.equal(
22
+ isNonLiteralProperty([JSXAttributeMock(theProp, LiteralMock('theRole'))], theProp),
23
+ false,
24
+ 'does not identify elements with a literal property as non-literal role elements without spread operator',
25
+ );
26
+
27
+ t.equal(
28
+ isNonLiteralProperty([spread, JSXAttributeMock(theProp, LiteralMock('theRole'))], theProp),
29
+ false,
30
+ 'does not identify elements with a literal property as non-literal role elements with spread operator',
31
+ );
32
+
33
+ t.equal(
34
+ isNonLiteralProperty([JSXAttributeMock(theProp, JSXTextMock('theRole'))], theProp),
35
+ false,
36
+ 'identifies elements with a JSXText property as non-literal role elements',
37
+ );
38
+
39
+ t.equal(
40
+ isNonLiteralProperty([JSXAttributeMock(theProp, IdentifierMock('undefined'))], theProp),
41
+ false,
42
+ 'does not identify elements with a property of undefined as non-literal role elements',
43
+ );
44
+
45
+ t.equal(
46
+ isNonLiteralProperty([JSXAttributeMock(theProp, IdentifierMock('theIdentifier'))], theProp),
47
+ true,
48
+ 'identifies elements with an expression property as non-literal role elements',
49
+ );
50
+
51
+ t.end();
52
+ });
@@ -0,0 +1,72 @@
1
+ import test from 'tape';
2
+
3
+ import isSemanticRoleElement from '../../../src/util/isSemanticRoleElement';
4
+ import JSXAttributeMock from '../../../__mocks__/JSXAttributeMock';
5
+
6
+ test('isSemanticRoleElement', (t) => {
7
+ t.equal(
8
+ isSemanticRoleElement('input', [
9
+ JSXAttributeMock('type', 'checkbox'),
10
+ JSXAttributeMock('role', 'switch'),
11
+ ]),
12
+ true,
13
+ 'identifies semantic role elements',
14
+ );
15
+
16
+ t.test('rejects non-semantics role elements', (st) => {
17
+ st.equal(
18
+ isSemanticRoleElement('input', [
19
+ JSXAttributeMock('type', 'radio'),
20
+ JSXAttributeMock('role', 'switch'),
21
+ ]),
22
+ false,
23
+ );
24
+
25
+ st.equal(
26
+ isSemanticRoleElement('input', [
27
+ JSXAttributeMock('type', 'text'),
28
+ JSXAttributeMock('role', 'combobox'),
29
+ ]),
30
+ false,
31
+ );
32
+
33
+ st.equal(
34
+ isSemanticRoleElement('button', [
35
+ JSXAttributeMock('role', 'switch'),
36
+ JSXAttributeMock('aria-pressed', 'true'),
37
+ ]),
38
+ false,
39
+ );
40
+
41
+ st.equal(
42
+ isSemanticRoleElement('input', [
43
+ JSXAttributeMock('role', 'switch'),
44
+ ]),
45
+ false,
46
+ );
47
+
48
+ st.end();
49
+ });
50
+
51
+ t.doesNotThrow(
52
+ () => {
53
+ isSemanticRoleElement('input', [
54
+ JSXAttributeMock('type', 'checkbox'),
55
+ JSXAttributeMock('role', 'checkbox'),
56
+ JSXAttributeMock('aria-checked', 'false'),
57
+ JSXAttributeMock('aria-labelledby', 'foo'),
58
+ JSXAttributeMock('tabindex', '0'),
59
+ {
60
+ type: 'JSXSpreadAttribute',
61
+ argument: {
62
+ type: 'Identifier',
63
+ name: 'props',
64
+ },
65
+ },
66
+ ]);
67
+ },
68
+ 'does not throw on JSXSpreadAttribute',
69
+ );
70
+
71
+ t.end();
72
+ });