@markuplint/rules 3.0.0-alpha.66 → 3.0.0-dev.176

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 (211) hide show
  1. package/README.md +10 -44
  2. package/lib/attr-check.d.ts +22 -10
  3. package/lib/attr-check.js +32 -23
  4. package/lib/attr-duplication/index.d.ts +3 -1
  5. package/lib/attr-duplication/index.js +3 -2
  6. package/lib/attr-value-quotes/index.d.ts +5 -5
  7. package/lib/attr-value-quotes/index.js +1 -1
  8. package/lib/case-sensitive-attr-name/index.d.ts +2 -2
  9. package/lib/case-sensitive-attr-name/index.js +3 -3
  10. package/lib/case-sensitive-tag-name/index.d.ts +2 -2
  11. package/lib/case-sensitive-tag-name/index.js +3 -3
  12. package/lib/character-reference/index.d.ts +1 -1
  13. package/lib/character-reference/index.js +1 -1
  14. package/lib/class-naming/index.d.ts +2 -2
  15. package/lib/class-naming/index.js +3 -5
  16. package/lib/create-message.d.ts +13 -2
  17. package/lib/create-message.js +9 -8
  18. package/lib/debug.d.ts +1 -1
  19. package/lib/debug.js +1 -1
  20. package/lib/deprecated-attr/index.d.ts +3 -1
  21. package/lib/deprecated-element/index.d.ts +3 -1
  22. package/lib/deprecated-element/index.js +4 -4
  23. package/lib/disallowed-element/index.d.ts +1 -1
  24. package/lib/doctype/index.d.ts +3 -3
  25. package/lib/doctype/index.js +2 -2
  26. package/lib/end-tag/index.d.ts +1 -1
  27. package/lib/end-tag/index.js +3 -18
  28. package/lib/helpers.d.ts +38 -47
  29. package/lib/helpers.js +42 -93
  30. package/lib/id-duplication/index.d.ts +3 -1
  31. package/lib/index.d.ts +242 -62
  32. package/lib/index.js +10 -1
  33. package/lib/ineffective-attr/index.d.ts +3 -1
  34. package/lib/ineffective-attr/index.js +3 -6
  35. package/lib/invalid-attr/index.d.ts +40 -12
  36. package/lib/invalid-attr/index.js +159 -28
  37. package/lib/label-has-control/index.d.ts +4 -0
  38. package/lib/label-has-control/index.js +28 -0
  39. package/lib/landmark-roles/index.d.ts +6 -6
  40. package/lib/landmark-roles/index.js +10 -6
  41. package/lib/no-boolean-attr-value/index.d.ts +3 -1
  42. package/lib/no-boolean-attr-value/index.js +1 -1
  43. package/lib/no-default-value/index.d.ts +3 -1
  44. package/lib/no-default-value/index.js +1 -1
  45. package/lib/no-empty-palpable-content/index.d.ts +6 -0
  46. package/lib/no-empty-palpable-content/index.js +42 -0
  47. package/lib/no-hard-code-id/index.d.ts +3 -1
  48. package/lib/no-hard-code-id/index.js +1 -1
  49. package/lib/no-refer-to-non-existent-id/index.d.ts +9 -4
  50. package/lib/no-refer-to-non-existent-id/index.js +65 -5
  51. package/lib/no-use-event-handler-attr/index.d.ts +3 -3
  52. package/lib/no-use-event-handler-attr/index.js +6 -6
  53. package/lib/permitted-contents/choice.d.ts +10 -0
  54. package/lib/permitted-contents/choice.js +72 -0
  55. package/lib/permitted-contents/complex-branch.d.ts +20 -0
  56. package/lib/permitted-contents/complex-branch.js +29 -0
  57. package/lib/permitted-contents/content-model.d.ts +2 -0
  58. package/lib/permitted-contents/content-model.js +53 -0
  59. package/lib/permitted-contents/count-pattern.d.ts +29 -0
  60. package/lib/permitted-contents/count-pattern.js +162 -0
  61. package/lib/permitted-contents/debug.browser.d.ts +30 -0
  62. package/lib/permitted-contents/debug.browser.js +14 -0
  63. package/lib/permitted-contents/debug.d.ts +3 -0
  64. package/lib/permitted-contents/debug.js +13 -0
  65. package/lib/permitted-contents/index.d.ts +2 -8
  66. package/lib/permitted-contents/index.js +76 -249
  67. package/lib/permitted-contents/matches-selector.d.ts +8 -0
  68. package/lib/permitted-contents/matches-selector.js +187 -0
  69. package/lib/permitted-contents/order.d.ts +20 -0
  70. package/lib/permitted-contents/order.js +99 -0
  71. package/lib/permitted-contents/recursive-branch.d.ts +11 -0
  72. package/lib/permitted-contents/recursive-branch.js +45 -0
  73. package/lib/permitted-contents/represent-transparent-nodes.d.ts +10 -0
  74. package/lib/permitted-contents/represent-transparent-nodes.js +78 -0
  75. package/lib/permitted-contents/start.d.ts +18 -0
  76. package/lib/permitted-contents/start.js +73 -0
  77. package/lib/permitted-contents/transparent.d.ts +2 -0
  78. package/lib/permitted-contents/transparent.js +31 -0
  79. package/lib/permitted-contents/types.d.ts +52 -0
  80. package/lib/permitted-contents/types.js +2 -0
  81. package/lib/permitted-contents/utils.d.ts +100 -0
  82. package/lib/permitted-contents/utils.js +302 -0
  83. package/lib/placeholder-label-option/index.d.ts +2 -0
  84. package/lib/placeholder-label-option/index.js +88 -0
  85. package/lib/require-accessible-name/index.d.ts +3 -3
  86. package/lib/require-accessible-name/index.js +12 -4
  87. package/lib/require-datetime/index.d.ts +6 -0
  88. package/lib/require-datetime/index.js +34 -0
  89. package/lib/require-datetime/types.d.ts +10 -0
  90. package/lib/require-datetime/types.js +2 -0
  91. package/lib/require-datetime/utils.d.ts +11 -0
  92. package/lib/require-datetime/utils.js +137 -0
  93. package/lib/required-attr/index.d.ts +5 -5
  94. package/lib/required-attr/index.js +20 -17
  95. package/lib/required-element/index.d.ts +3 -3
  96. package/lib/required-element/index.js +3 -2
  97. package/lib/required-h1/index.d.ts +3 -3
  98. package/lib/required-h1/index.js +4 -3
  99. package/lib/use-list/index.d.ts +4 -4
  100. package/lib/use-list/index.js +9 -7
  101. package/lib/wai-aria/checkings/_.d.ts +15 -0
  102. package/lib/wai-aria/checkings/_.js +27 -0
  103. package/lib/wai-aria/checkings/abstract-role.js +1 -1
  104. package/lib/wai-aria/checkings/default-value.d.ts +7 -3
  105. package/lib/wai-aria/checkings/deprecated-props.d.ts +8 -4
  106. package/lib/wai-aria/checkings/disallowed-prop.d.ts +8 -4
  107. package/lib/wai-aria/checkings/disallowed-prop.js +27 -3
  108. package/lib/wai-aria/checkings/implicit-props.d.ts +8 -4
  109. package/lib/wai-aria/checkings/implicit-props.js +3 -2
  110. package/lib/wai-aria/checkings/implicit-role.js +2 -2
  111. package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +11 -0
  112. package/lib/wai-aria/checkings/interaction-in-hidden.js +49 -0
  113. package/lib/wai-aria/checkings/no-global-prop.d.ts +7 -3
  114. package/lib/wai-aria/checkings/{non-existant-role.d.ts → non-existent-role.d.ts} +1 -1
  115. package/lib/wai-aria/checkings/{non-existant-role.js → non-existent-role.js} +4 -4
  116. package/lib/wai-aria/checkings/permitted-roles.js +1 -1
  117. package/lib/wai-aria/checkings/presentational-children.d.ts +29 -0
  118. package/lib/wai-aria/checkings/presentational-children.js +62 -0
  119. package/lib/wai-aria/checkings/{checking-required-owned-elements.d.ts → required-owned-elements.d.ts} +7 -3
  120. package/lib/wai-aria/checkings/required-owned-elements.js +103 -0
  121. package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
  122. package/lib/wai-aria/checkings/required-prop copy.js +27 -0
  123. package/lib/wai-aria/checkings/required-prop.d.ts +12 -6
  124. package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
  125. package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
  126. package/lib/wai-aria/checkings/value.d.ts +19 -4
  127. package/lib/wai-aria/checkings/value.js +77 -5
  128. package/lib/wai-aria/index.d.ts +1 -1
  129. package/lib/wai-aria/index.js +27 -16
  130. package/lib/wai-aria/types.d.ts +11 -9
  131. package/lib/xxx/index.d.ts +2 -0
  132. package/lib/xxx/index.js +32 -0
  133. package/package.json +18 -12
  134. package/schema.json +12 -0
  135. package/test/attr-check.spec.js +77 -0
  136. package/test/attr-duplication/index.spec.js +159 -0
  137. package/test/attr-value-quotes/index.spec.js +133 -0
  138. package/test/case-sensitive-attr-name/index.spec.js +65 -0
  139. package/test/case-sensitive-tag-name/index.spec.js +80 -0
  140. package/test/character-reference/index.spec.js +57 -0
  141. package/test/class-naming/index.spec.js +470 -0
  142. package/test/create-message.spec.js +497 -0
  143. package/test/deprecated-attr/index.spec.js +48 -0
  144. package/test/deprecated-element/index.spec.js +48 -0
  145. package/test/disallowed-element/index.spec.js +90 -0
  146. package/test/doctype/index.spec.js +50 -0
  147. package/test/end-tag/index.spec.js +162 -0
  148. package/test/id-duplication/index.spec.js +47 -0
  149. package/test/ineffective-attr/index.spec.js +31 -0
  150. package/test/invalid-attr/index.spec.js +1632 -0
  151. package/test/label-has-control/index.spec.js +29 -0
  152. package/test/landmark-roles/index.spec.js +187 -0
  153. package/test/no-boolean-attr-value/index.spec.js +41 -0
  154. package/test/no-default-value/index.spec.js +74 -0
  155. package/test/no-empty-palpable-content/index.spec.js +115 -0
  156. package/test/no-hard-code-id/index.spec.js +100 -0
  157. package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
  158. package/test/no-use-event-handler-attr/index.spec.js +57 -0
  159. package/test/permitted-contents/choice.spec.js +174 -0
  160. package/test/permitted-contents/count-pattern.spec.js +308 -0
  161. package/test/permitted-contents/index.spec.js +1371 -0
  162. package/test/permitted-contents/matches-selector.spec.js +59 -0
  163. package/test/permitted-contents/order.spec.js +351 -0
  164. package/test/permitted-contents/recursive-branch.spec.js +41 -0
  165. package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
  166. package/test/permitted-contents/start.spec.js +67 -0
  167. package/test/placeholder-label-option/index.spec.js +113 -0
  168. package/test/require-accessible-name/index.spec.js +446 -0
  169. package/test/require-datetime/index.spec.js +54 -0
  170. package/test/require-datetime/utils.spec.js +52 -0
  171. package/test/required-attr/index.spec.js +414 -0
  172. package/test/required-element/index.spec.js +188 -0
  173. package/test/required-h1/index.spec.js +69 -0
  174. package/test/use-list/index.spec.js +109 -0
  175. package/test/wai-aria/checkings/value.spec.js +33 -0
  176. package/test/wai-aria/index.spec.js +1173 -0
  177. package/lib/__foo/index.d.ts +0 -2
  178. package/lib/__foo/index.js +0 -46
  179. package/lib/attr-equal-space-after/index.d.ts +0 -3
  180. package/lib/attr-equal-space-after/index.js +0 -90
  181. package/lib/attr-equal-space-before/index.d.ts +0 -3
  182. package/lib/attr-equal-space-before/index.js +0 -90
  183. package/lib/attr-spacing/index.d.ts +0 -6
  184. package/lib/attr-spacing/index.js +0 -100
  185. package/lib/helper/aria/get-aria.d.ts +0 -7
  186. package/lib/helper/aria/get-aria.js +0 -53
  187. package/lib/helper/aria/get-computed-role.d.ts +0 -10
  188. package/lib/helper/aria/get-computed-role.js +0 -24
  189. package/lib/helper/aria/get-implicit-role.d.ts +0 -7
  190. package/lib/helper/aria/get-implicit-role.js +0 -12
  191. package/lib/helper/aria/get-permitted-roles.d.ts +0 -14
  192. package/lib/helper/aria/get-permitted-roles.js +0 -26
  193. package/lib/helper/aria/resolve-version.d.ts +0 -2
  194. package/lib/helper/aria/resolve-version.js +0 -21
  195. package/lib/helper/spec/aria-spec.d.ts +0 -5
  196. package/lib/helper/spec/aria-spec.js +0 -12
  197. package/lib/helper/spec/get-role-spec.d.ts +0 -11
  198. package/lib/helper/spec/get-role-spec.js +0 -39
  199. package/lib/helper/spec/html-spec.d.ts +0 -2
  200. package/lib/helper/spec/html-spec.js +0 -14
  201. package/lib/indentation/index.d.ts +0 -7
  202. package/lib/indentation/index.js +0 -208
  203. package/lib/permitted-contents/array.combination.d.ts +0 -1
  204. package/lib/permitted-contents/array.combination.js +0 -33
  205. package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +0 -11
  206. package/lib/permitted-contents/permitted-content.spec-to-regexp.js +0 -230
  207. package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +0 -2
  208. package/lib/permitted-contents/unfold-content-models-to-tags.js +0 -8
  209. package/lib/wai-aria/checkings/checking-required-owned-elements.js +0 -63
  210. package/tsconfig.test.json +0 -3
  211. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,446 @@
1
+ const { mlRuleTest } = require('markuplint');
2
+
3
+ const rule = require('../../lib/require-accessible-name').default;
4
+
5
+ it('has accessible name', async () => {
6
+ const { violations } = await mlRuleTest(rule, '<button>Label</button>');
7
+ expect(violations.length).toBe(0);
8
+ });
9
+
10
+ it('has accessible name', async () => {
11
+ const { violations } = await mlRuleTest(rule, '<button aria-label="Label"></button>');
12
+ expect(violations.length).toBe(0);
13
+ });
14
+
15
+ it("does'nt have accessible name", async () => {
16
+ const { violations } = await mlRuleTest(rule, '<button></button>');
17
+ expect(violations).toStrictEqual([
18
+ {
19
+ severity: 'error',
20
+ col: 1,
21
+ line: 1,
22
+ message: 'Require accessible name',
23
+ raw: '<button>',
24
+ },
25
+ ]);
26
+ });
27
+
28
+ it("does'nt have accessible name", async () => {
29
+ const { violations } = await mlRuleTest(rule, '<input type="text">');
30
+ expect(violations).toStrictEqual([
31
+ {
32
+ severity: 'error',
33
+ col: 1,
34
+ line: 1,
35
+ message: 'Require accessible name',
36
+ raw: '<input type="text">',
37
+ },
38
+ ]);
39
+ });
40
+
41
+ it('has accessible name', async () => {
42
+ const { violations } = await mlRuleTest(rule, '<input type="text" aria-label="Label">');
43
+ expect(violations.length).toBe(0);
44
+ });
45
+
46
+ it('has accessible name', async () => {
47
+ const { violations } = await mlRuleTest(rule, '<input type="text" id="foo"><label for="foo">Label</label>');
48
+ expect(violations.length).toBe(0);
49
+ });
50
+
51
+ it("does'nt have accessible name", async () => {
52
+ const { violations } = await mlRuleTest(rule, '<input type="text" id="foo"><label for="foo2">Label</label>');
53
+ expect(violations).toStrictEqual([
54
+ {
55
+ severity: 'error',
56
+ col: 1,
57
+ line: 1,
58
+ message: 'Require accessible name',
59
+ raw: '<input type="text" id="foo">',
60
+ },
61
+ ]);
62
+ });
63
+
64
+ it('has accessible name', async () => {
65
+ const { violations } = await mlRuleTest(rule, '<label><input type="text">Label</label>');
66
+ expect(violations.length).toBe(0);
67
+ });
68
+
69
+ it("does'nt have accessible name", async () => {
70
+ const { violations } = await mlRuleTest(
71
+ rule,
72
+ `
73
+ <button>
74
+ <span></span>
75
+ <span></span>
76
+ <span></span>
77
+ </button>`,
78
+ );
79
+ expect(violations).toStrictEqual([
80
+ {
81
+ severity: 'error',
82
+ col: 1,
83
+ line: 2,
84
+ message: 'Require accessible name',
85
+ raw: '<button>',
86
+ },
87
+ ]);
88
+ });
89
+
90
+ it('has accessible name', async () => {
91
+ const { violations } = await mlRuleTest(
92
+ rule,
93
+ `
94
+ <button>
95
+ <span class="visually-hidden">Menu</span>
96
+ <span></span>
97
+ <span></span>
98
+ <span></span>
99
+ </button>`,
100
+ );
101
+ expect(violations.length).toBe(0);
102
+ });
103
+
104
+ it('needs no accessible name', async () => {
105
+ const { violations } = await mlRuleTest(rule, '<link rel="stylesheet" href="path/to" />');
106
+ expect(violations.length).toBe(0);
107
+ });
108
+
109
+ it("does'nt have accessible name", async () => {
110
+ const { violations: v1 } = await mlRuleTest(rule, '<form>text</form>', {
111
+ rule: { options: { ariaVersion: '1.1' } },
112
+ });
113
+ expect(v1.length).toBe(0);
114
+ const { violations: v2 } = await mlRuleTest(rule, '<form>text</form>', {
115
+ rule: { options: { ariaVersion: '1.2' } },
116
+ });
117
+ expect(v2.length).toBe(0);
118
+ });
119
+
120
+ test('The accessible name may be mutable', async () => {
121
+ expect(
122
+ (
123
+ await mlRuleTest(rule, '<input type="text" aria-label={label} />', {
124
+ parser: {
125
+ '.*': '@markuplint/jsx-parser',
126
+ },
127
+ })
128
+ ).violations,
129
+ ).toStrictEqual([]);
130
+ });
131
+
132
+ test('The accessible name may be mutable', async () => {
133
+ expect(
134
+ (
135
+ await mlRuleTest(rule, '<button>{label}</button>', {
136
+ parser: {
137
+ '.*': '@markuplint/jsx-parser',
138
+ },
139
+ })
140
+ ).violations,
141
+ ).toStrictEqual([]);
142
+ });
143
+
144
+ test('The accessible name may be mutable', async () => {
145
+ expect(
146
+ (
147
+ await mlRuleTest(rule, '<button><span>{label}</span></button>', {
148
+ parser: {
149
+ '.*': '@markuplint/jsx-parser',
150
+ },
151
+ })
152
+ ).violations,
153
+ ).toStrictEqual([]);
154
+ });
155
+
156
+ test('The accessible name may be mutable', async () => {
157
+ expect(
158
+ (
159
+ await mlRuleTest(rule, '<template><button>{{label}}</button></template>', {
160
+ parser: {
161
+ '.*': '@markuplint/vue-parser',
162
+ },
163
+ })
164
+ ).violations,
165
+ ).toStrictEqual([]);
166
+ });
167
+
168
+ test('has comment', async () => {
169
+ expect((await mlRuleTest(rule, '<button>label<!-- comment --></button>')).violations).toStrictEqual([]);
170
+ });
171
+
172
+ test('The accessible name may be mutable (Svelte)', async () => {
173
+ expect(
174
+ (
175
+ await mlRuleTest(rule, '<button>{label}</button>', {
176
+ parser: {
177
+ '.*': '@markuplint/svelte-parser',
178
+ },
179
+ })
180
+ ).violations,
181
+ ).toStrictEqual([]);
182
+ });
183
+
184
+ test('The accessible name may be mutable', async () => {
185
+ expect(
186
+ (
187
+ await mlRuleTest(rule, '<button><img alt={alt} /></button>', {
188
+ parser: {
189
+ '.*': '@markuplint/jsx-parser',
190
+ },
191
+ })
192
+ ).violations,
193
+ ).toStrictEqual([]);
194
+ });
195
+
196
+ test('The accessible name may be mutable', async () => {
197
+ expect(
198
+ (
199
+ await mlRuleTest(rule, '<label><input type="text" /><span>{label}</span></label>', {
200
+ parser: {
201
+ '.*': '@markuplint/jsx-parser',
202
+ },
203
+ })
204
+ ).violations,
205
+ ).toStrictEqual([]);
206
+ });
207
+
208
+ test('The accessible name may be mutable', async () => {
209
+ expect(
210
+ (
211
+ await mlRuleTest(rule, '<><label for="foo">{label}</label><input type="text" id="foo" /></>', {
212
+ parser: {
213
+ '.*': '@markuplint/jsx-parser',
214
+ },
215
+ })
216
+ ).violations,
217
+ ).toStrictEqual([]);
218
+ });
219
+
220
+ test('Pretenders Option', async () => {
221
+ expect(
222
+ (
223
+ await mlRuleTest(rule, '<button><MyComponent/></button>', {
224
+ parser: {
225
+ '.*': '@markuplint/jsx-parser',
226
+ },
227
+ pretenders: [
228
+ {
229
+ selector: 'MyComponent',
230
+ as: {
231
+ element: 'img',
232
+ },
233
+ },
234
+ ],
235
+ })
236
+ ).violations,
237
+ ).toStrictEqual([
238
+ {
239
+ severity: 'error',
240
+ line: 1,
241
+ col: 1,
242
+ message: 'Require accessible name',
243
+ raw: '<button>',
244
+ },
245
+ ]);
246
+ expect(
247
+ (
248
+ await mlRuleTest(rule, '<button><MyComponent/></button>', {
249
+ parser: {
250
+ '.*': '@markuplint/jsx-parser',
251
+ },
252
+ pretenders: [
253
+ {
254
+ selector: 'MyComponent',
255
+ as: {
256
+ element: 'img',
257
+ attrs: [
258
+ {
259
+ name: 'alt',
260
+ value: 'some text',
261
+ },
262
+ ],
263
+ },
264
+ },
265
+ ],
266
+ })
267
+ ).violations,
268
+ ).toStrictEqual([]);
269
+ expect(
270
+ (
271
+ await mlRuleTest(rule, '<button><MyComponent/></button>', {
272
+ parser: {
273
+ '.*': '@markuplint/jsx-parser',
274
+ },
275
+ pretenders: [
276
+ {
277
+ selector: 'MyComponent',
278
+ as: {
279
+ element: 'img',
280
+ attrs: [
281
+ {
282
+ name: 'alt',
283
+ value: '',
284
+ },
285
+ ],
286
+ },
287
+ },
288
+ ],
289
+ })
290
+ ).violations,
291
+ ).toStrictEqual([
292
+ {
293
+ severity: 'error',
294
+ line: 1,
295
+ col: 1,
296
+ message: 'Require accessible name',
297
+ raw: '<button>',
298
+ },
299
+ ]);
300
+ expect(
301
+ (
302
+ await mlRuleTest(rule, '<button><MyComponent/></button>', {
303
+ parser: {
304
+ '.*': '@markuplint/jsx-parser',
305
+ },
306
+ pretenders: [
307
+ {
308
+ selector: 'MyComponent',
309
+ as: {
310
+ element: 'img',
311
+ aria: {
312
+ name: true,
313
+ },
314
+ },
315
+ },
316
+ ],
317
+ })
318
+ ).violations,
319
+ ).toStrictEqual([]);
320
+ expect(
321
+ (
322
+ await mlRuleTest(rule, '<button><MyComponent label="accname"/></button>', {
323
+ parser: {
324
+ '.*': '@markuplint/jsx-parser',
325
+ },
326
+ pretenders: [
327
+ {
328
+ selector: 'MyComponent',
329
+ as: {
330
+ element: 'img',
331
+ aria: {
332
+ name: {
333
+ fromAttr: 'label',
334
+ },
335
+ },
336
+ },
337
+ },
338
+ ],
339
+ })
340
+ ).violations,
341
+ ).toStrictEqual([]);
342
+ expect(
343
+ (
344
+ await mlRuleTest(rule, '<button><MyComponent label=""/></button>', {
345
+ parser: {
346
+ '.*': '@markuplint/jsx-parser',
347
+ },
348
+ pretenders: [
349
+ {
350
+ selector: 'MyComponent',
351
+ as: {
352
+ element: 'img',
353
+ aria: {
354
+ name: {
355
+ fromAttr: 'label',
356
+ },
357
+ },
358
+ },
359
+ },
360
+ ],
361
+ })
362
+ ).violations,
363
+ ).toStrictEqual([
364
+ {
365
+ severity: 'error',
366
+ line: 1,
367
+ col: 1,
368
+ message: 'Require accessible name',
369
+ raw: '<button>',
370
+ },
371
+ ]);
372
+ });
373
+
374
+ describe('Issues', () => {
375
+ // https://github.com/markuplint/markuplint/issues/536
376
+ test('#536', async () => {
377
+ expect(
378
+ (await mlRuleTest(rule, '<h2 id="h">Heading</h2><div role="region" aria-labelledby="h">...</div>'))
379
+ .violations,
380
+ ).toStrictEqual([]);
381
+ expect(
382
+ (
383
+ await mlRuleTest(
384
+ rule,
385
+ '<h2 id="h">Heading</h2><div role="region" aria-labelledby="h" aria-hidden="true">...</div>',
386
+ )
387
+ ).violations,
388
+ ).toStrictEqual([]);
389
+ });
390
+
391
+ // https://github.com/markuplint/markuplint/issues/592
392
+ test('#592', async () => {
393
+ expect(
394
+ (await mlRuleTest(rule, '<svg aria-label="i-have-name"><path /><rect><path /></rect></svg>')).violations,
395
+ ).toStrictEqual([
396
+ {
397
+ col: 31,
398
+ line: 1,
399
+ message: 'Require accessible name',
400
+ raw: '<path />',
401
+ severity: 'error',
402
+ },
403
+ {
404
+ col: 39,
405
+ line: 1,
406
+ message: 'Require accessible name',
407
+ raw: '<rect>',
408
+ severity: 'error',
409
+ },
410
+ ]);
411
+ expect(
412
+ (await mlRuleTest(rule, '<svg role="img" aria-label="i-have-name"><path /><rect><path /></rect></svg>'))
413
+ .violations,
414
+ ).toStrictEqual([]);
415
+ expect(
416
+ (
417
+ await mlRuleTest(
418
+ rule,
419
+ '<svg aria-label="i-have-name"><path aria-label="i-have-name" /><rect><path /></rect></svg>',
420
+ )
421
+ ).violations,
422
+ ).toStrictEqual([
423
+ {
424
+ col: 64,
425
+ line: 1,
426
+ message: 'Require accessible name',
427
+ raw: '<rect>',
428
+ severity: 'error',
429
+ },
430
+ ]);
431
+ expect(
432
+ (
433
+ await mlRuleTest(
434
+ rule,
435
+ '<svg aria-label="i-have-name"><path aria-label="i-have-name" /><rect aria-label="i-have-name"><path /></rect></svg>',
436
+ )
437
+ ).violations,
438
+ ).toStrictEqual([]);
439
+ });
440
+
441
+ // https://github.com/markuplint/markuplint/issues/658
442
+ test('#658', async () => {
443
+ expect((await mlRuleTest(rule, '<dialog></dialog>')).violations.length).toBe(1);
444
+ expect((await mlRuleTest(rule, '<div role="dialog"></div>')).violations.length).toBe(1);
445
+ });
446
+ });
@@ -0,0 +1,54 @@
1
+ const { mlRuleTest } = require('markuplint');
2
+
3
+ const rule = require('../../lib/require-datetime').default;
4
+
5
+ test('Valid', async () => {
6
+ expect((await mlRuleTest(rule, '<time>2000-01-01</time>')).violations).toStrictEqual([]);
7
+ expect((await mlRuleTest(rule, '<time datetime="2000-01-01">2000/01/01</time>')).violations).toStrictEqual([]);
8
+ });
9
+
10
+ test('Mutable', async () => {
11
+ expect(
12
+ (
13
+ await mlRuleTest(rule, '<time>{foo}</time>', {
14
+ parser: {
15
+ '.*': '@markuplint/jsx-parser',
16
+ },
17
+ })
18
+ ).violations,
19
+ ).toStrictEqual([]);
20
+ });
21
+
22
+ test('Need', async () => {
23
+ expect((await mlRuleTest(rule, '<time>Content</time>')).violations).toStrictEqual([
24
+ {
25
+ severity: 'error',
26
+ line: 1,
27
+ col: 1,
28
+ raw: '<time>',
29
+ message: 'Need the "datetime" attribute',
30
+ },
31
+ ]);
32
+ });
33
+
34
+ test('Candidates', async () => {
35
+ expect((await mlRuleTest(rule, '<time>2000/01/01</time>')).violations).toStrictEqual([
36
+ {
37
+ severity: 'error',
38
+ line: 1,
39
+ col: 1,
40
+ raw: '<time>',
41
+ message: 'Need datetime="2000-01-01"',
42
+ },
43
+ ]);
44
+
45
+ expect((await mlRuleTest(rule, '<time>令和5年1月3日</time>')).violations).toStrictEqual([
46
+ {
47
+ severity: 'error',
48
+ line: 1,
49
+ col: 1,
50
+ raw: '<time>',
51
+ message: 'Need datetime="2023-01-03"',
52
+ },
53
+ ]);
54
+ });
@@ -0,0 +1,52 @@
1
+ const { parseADatetime, getCandidateDatetimeString } = require('../../lib/require-datetime/utils');
2
+
3
+ test('parseADatetime', () => {
4
+ expect(parseADatetime('2000/1/1', ['en'])).toStrictEqual({
5
+ datetime: {
6
+ year: 2000,
7
+ month: 1,
8
+ day: 1,
9
+ },
10
+ });
11
+ expect(parseADatetime('3:00PM', ['en'])).toStrictEqual({
12
+ datetime: {
13
+ hour: 15,
14
+ minute: 0,
15
+ },
16
+ });
17
+ expect(parseADatetime('5 days ago', ['en'], new Date(2023, 1 - 1, 20))).toStrictEqual({
18
+ datetime: {
19
+ day: 15,
20
+ month: 1,
21
+ year: 2023,
22
+ },
23
+ });
24
+ expect(parseADatetime('Sat Aug 17 2013 18:40:39 GMT+0900 (JST)', ['en'])).toStrictEqual({
25
+ datetime: {
26
+ day: 17,
27
+ hour: 18,
28
+ minute: 40,
29
+ month: 8,
30
+ second: 39,
31
+ year: 2013,
32
+ },
33
+ zone: 540,
34
+ });
35
+
36
+ // attributable to chrono
37
+ expect(parseADatetime('2015', ['en'])).toStrictEqual(null);
38
+ expect(parseADatetime('令和5年', ['ja'])).toStrictEqual(null);
39
+ expect(parseADatetime('午後2時', ['en', 'ja'])).toStrictEqual(null);
40
+ });
41
+
42
+ test('getCandidateDatetimeString', () => {
43
+ expect(getCandidateDatetimeString('2000/1/1')).toBe('2000-01-01');
44
+ expect(getCandidateDatetimeString('1/2/2011')).toBe('2011-01-02');
45
+ expect(getCandidateDatetimeString('2000/1/2 12:15')).toBe('2000-01-02T12:15');
46
+ expect(getCandidateDatetimeString('3000/12/31 23:59:59.999')).toBe('3000-12-31T23:59:59.999');
47
+ expect(getCandidateDatetimeString('Sat Aug 17 2013 18:40:39 GMT+0900 (JST)')).toBe('2013-08-17T18:40:39+0900');
48
+ expect(getCandidateDatetimeString('2014-11-30T08:15:30-05:30')).toBe('2014-11-30T08:15:30-0530');
49
+ expect(getCandidateDatetimeString('6:15PM, June 13, 2022')).toBe('2022-06-13T18:15');
50
+ expect(getCandidateDatetimeString('昭和60年7月9日')).toBe('1985-07-09');
51
+ expect(getCandidateDatetimeString('Le 5 juin 2001')).toBe('2001-06-05'); // cspell:disable-line
52
+ });