@markuplint/rules 3.7.0 → 3.9.0

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 (60) hide show
  1. package/lib/helpers.d.ts +2 -5
  2. package/lib/index.d.ts +240 -99
  3. package/lib/invalid-attr/index.d.ts +38 -31
  4. package/lib/no-refer-to-non-existent-id/index.d.ts +1 -2
  5. package/lib/no-refer-to-non-existent-id/index.js +2 -1
  6. package/lib/require-accessible-name/index.js +1 -1
  7. package/lib/required-attr/index.d.ts +1 -1
  8. package/lib/required-attr/index.js +1 -1
  9. package/lib/wai-aria/checkings/_.d.ts +15 -0
  10. package/lib/wai-aria/checkings/_.js +27 -0
  11. package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
  12. package/lib/wai-aria/checkings/required-prop copy.js +27 -0
  13. package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
  14. package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
  15. package/lib/wai-aria/index.js +2 -1
  16. package/lib/xxx/index.d.ts +2 -0
  17. package/lib/xxx/index.js +32 -0
  18. package/package.json +11 -13
  19. package/test/attr-check.spec.js +77 -0
  20. package/test/attr-duplication/index.spec.js +159 -0
  21. package/test/attr-value-quotes/index.spec.js +133 -0
  22. package/test/case-sensitive-attr-name/index.spec.js +65 -0
  23. package/test/case-sensitive-tag-name/index.spec.js +80 -0
  24. package/test/character-reference/index.spec.js +57 -0
  25. package/test/class-naming/index.spec.js +470 -0
  26. package/test/create-message.spec.js +497 -0
  27. package/test/deprecated-attr/index.spec.js +48 -0
  28. package/test/deprecated-element/index.spec.js +48 -0
  29. package/test/disallowed-element/index.spec.js +90 -0
  30. package/test/doctype/index.spec.js +50 -0
  31. package/test/end-tag/index.spec.js +162 -0
  32. package/test/id-duplication/index.spec.js +47 -0
  33. package/test/ineffective-attr/index.spec.js +31 -0
  34. package/test/invalid-attr/index.spec.js +1632 -0
  35. package/test/label-has-control/index.spec.js +29 -0
  36. package/test/landmark-roles/index.spec.js +187 -0
  37. package/test/no-boolean-attr-value/index.spec.js +41 -0
  38. package/test/no-default-value/index.spec.js +74 -0
  39. package/test/no-empty-palpable-content/index.spec.js +115 -0
  40. package/test/no-hard-code-id/index.spec.js +100 -0
  41. package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
  42. package/test/no-use-event-handler-attr/index.spec.js +57 -0
  43. package/test/permitted-contents/choice.spec.js +174 -0
  44. package/test/permitted-contents/count-pattern.spec.js +308 -0
  45. package/test/permitted-contents/index.spec.js +1371 -0
  46. package/test/permitted-contents/matches-selector.spec.js +59 -0
  47. package/test/permitted-contents/order.spec.js +351 -0
  48. package/test/permitted-contents/recursive-branch.spec.js +41 -0
  49. package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
  50. package/test/permitted-contents/start.spec.js +67 -0
  51. package/test/placeholder-label-option/index.spec.js +113 -0
  52. package/test/require-accessible-name/index.spec.js +446 -0
  53. package/test/require-datetime/index.spec.js +54 -0
  54. package/test/require-datetime/utils.spec.js +52 -0
  55. package/test/required-attr/index.spec.js +414 -0
  56. package/test/required-element/index.spec.js +188 -0
  57. package/test/required-h1/index.spec.js +69 -0
  58. package/test/use-list/index.spec.js +109 -0
  59. package/test/wai-aria/checkings/value.spec.js +33 -0
  60. package/test/wai-aria/index.spec.js +1173 -0
@@ -0,0 +1,497 @@
1
+ const { translator } = require('@markuplint/i18n');
2
+ const { i18n } = require('markuplint');
3
+
4
+ const { __createMessageValueExpected } = require('../lib/create-message');
5
+
6
+ let t;
7
+
8
+ beforeAll(async () => {
9
+ const locale = await i18n('en');
10
+ t = translator(locale);
11
+ });
12
+
13
+ // TODO: doesnt-exist-in-enum
14
+
15
+ describe('duplicated', () => {
16
+ test('expects: without, partName: without', () => {
17
+ expect(
18
+ __createMessageValueExpected(t, 'A', '', {
19
+ ref: 'REF',
20
+ raw: 'RAW',
21
+ reason: 'duplicated',
22
+ }),
23
+ ).toBe('A is duplicated (REF)');
24
+ });
25
+
26
+ test('expects: without, partName: with', () => {
27
+ expect(
28
+ __createMessageValueExpected(t, 'A', '', {
29
+ ref: 'REF',
30
+ raw: 'RAW',
31
+ reason: 'duplicated',
32
+ partName: 'C',
33
+ }),
34
+ ).toBe('the C part of A is duplicated (REF)');
35
+ });
36
+
37
+ test('expects: with, partName: without', () => {
38
+ expect(
39
+ __createMessageValueExpected(t, 'A', 'B', {
40
+ ref: 'REF',
41
+ raw: 'RAW',
42
+ reason: 'duplicated',
43
+ }),
44
+ ).toBe('A is duplicated. It expects B (REF)');
45
+ });
46
+
47
+ test('expects: with, partName: with', () => {
48
+ expect(
49
+ __createMessageValueExpected(t, 'A', 'B', {
50
+ ref: 'REF',
51
+ raw: 'RAW',
52
+ reason: 'duplicated',
53
+ partName: 'C',
54
+ }),
55
+ ).toBe('the C part of A is duplicated. It expects B (REF)');
56
+ });
57
+ });
58
+
59
+ describe('empty-token', () => {
60
+ test('expects: without, partName: without', () => {
61
+ expect(
62
+ __createMessageValueExpected(t, 'A', '', {
63
+ ref: 'REF',
64
+ raw: 'RAW',
65
+ reason: 'empty-token',
66
+ }),
67
+ ).toBe('A must not be empty (REF)');
68
+ });
69
+
70
+ test('expects: without, partName: with', () => {
71
+ expect(
72
+ __createMessageValueExpected(t, 'A', '', {
73
+ ref: 'REF',
74
+ raw: 'RAW',
75
+ reason: 'empty-token',
76
+ partName: 'C',
77
+ }),
78
+ ).toBe('the C part of A must not be empty (REF)');
79
+ });
80
+
81
+ test('expects: with, partName: without', () => {
82
+ expect(
83
+ __createMessageValueExpected(t, 'A', 'B', {
84
+ ref: 'REF',
85
+ raw: 'RAW',
86
+ reason: 'empty-token',
87
+ }),
88
+ ).toBe('A must not be empty. It expects B (REF)');
89
+ });
90
+
91
+ test('expects: with, partName: with', () => {
92
+ expect(
93
+ __createMessageValueExpected(t, 'A', 'B', {
94
+ ref: 'REF',
95
+ raw: 'RAW',
96
+ reason: 'empty-token',
97
+ partName: 'C',
98
+ }),
99
+ ).toBe('the C part of A must not be empty. It expects B (REF)');
100
+ });
101
+ });
102
+
103
+ describe('extra-token', () => {
104
+ test('expects: without, partName: without', () => {
105
+ expect(
106
+ __createMessageValueExpected(t, 'A', '', {
107
+ ref: 'REF',
108
+ raw: 'RAW',
109
+ reason: 'extra-token',
110
+ }),
111
+ ).toBe('Found extra token "RAW" (REF)');
112
+ });
113
+
114
+ test('expects: without, partName: with', () => {
115
+ expect(
116
+ __createMessageValueExpected(t, 'A', '', {
117
+ ref: 'REF',
118
+ raw: 'RAW',
119
+ reason: 'extra-token',
120
+ partName: 'C',
121
+ }),
122
+ ).toBe('Found extra C "RAW" (REF)');
123
+ });
124
+
125
+ test('expects: with, partName: without', () => {
126
+ expect(
127
+ __createMessageValueExpected(t, 'A', 'B', {
128
+ ref: 'REF',
129
+ raw: 'RAW',
130
+ reason: 'extra-token',
131
+ }),
132
+ ).toBe('Found extra token "RAW". A expects B (REF)');
133
+ });
134
+
135
+ test('expects: with, partName: with', () => {
136
+ expect(
137
+ __createMessageValueExpected(t, 'A', 'B', {
138
+ ref: 'REF',
139
+ raw: 'RAW',
140
+ reason: 'extra-token',
141
+ partName: 'C',
142
+ }),
143
+ ).toBe('Found extra C "RAW". the C part of A expects B (REF)');
144
+ });
145
+ });
146
+
147
+ describe('illegal-combination', () => {
148
+ test('expects: without, partName: without', () => {
149
+ expect(
150
+ __createMessageValueExpected(t, 'A', '', {
151
+ ref: 'REF',
152
+ raw: 'RAW',
153
+ reason: 'illegal-combination',
154
+ }),
155
+ ).toBe('Found an illegal combination (REF)');
156
+ });
157
+
158
+ test('expects: without, partName: with', () => {
159
+ expect(
160
+ __createMessageValueExpected(t, 'A', '', {
161
+ ref: 'REF',
162
+ raw: 'RAW',
163
+ reason: 'illegal-combination',
164
+ partName: 'C',
165
+ }),
166
+ ).toBe('Found an illegal combination (REF)');
167
+ });
168
+
169
+ test('expects: with, partName: without', () => {
170
+ expect(
171
+ __createMessageValueExpected(t, 'A', 'B', {
172
+ ref: 'REF',
173
+ raw: 'RAW',
174
+ reason: 'illegal-combination',
175
+ }),
176
+ ).toBe('Found an illegal combination. A expects B (REF)');
177
+ });
178
+
179
+ test('expects: with, partName: with', () => {
180
+ expect(
181
+ __createMessageValueExpected(t, 'A', 'B', {
182
+ ref: 'REF',
183
+ raw: 'RAW',
184
+ reason: 'illegal-combination',
185
+ partName: 'C',
186
+ }),
187
+ ).toBe('Found an illegal combination. the C part of A expects B (REF)');
188
+ });
189
+ });
190
+
191
+ describe('missing-comma', () => {
192
+ test('expects: without, partName: without', () => {
193
+ expect(
194
+ __createMessageValueExpected(t, 'A', '', {
195
+ ref: 'REF',
196
+ raw: 'RAW',
197
+ reason: 'missing-comma',
198
+ }),
199
+ ).toBe('Missing a comma (REF)');
200
+ });
201
+
202
+ test('expects: without, partName: with', () => {
203
+ expect(
204
+ __createMessageValueExpected(t, 'A', '', {
205
+ ref: 'REF',
206
+ raw: 'RAW',
207
+ reason: 'missing-comma',
208
+ partName: 'C',
209
+ }),
210
+ ).toBe('Missing a comma in the C part (REF)');
211
+ });
212
+
213
+ test('expects: with, partName: without', () => {
214
+ expect(
215
+ __createMessageValueExpected(t, 'A', 'B', {
216
+ ref: 'REF',
217
+ raw: 'RAW',
218
+ reason: 'missing-comma',
219
+ }),
220
+ ).toBe('Missing a comma. A expects B (REF)');
221
+ });
222
+
223
+ test('expects: with, partName: with', () => {
224
+ expect(
225
+ __createMessageValueExpected(t, 'A', 'B', {
226
+ ref: 'REF',
227
+ raw: 'RAW',
228
+ reason: 'missing-comma',
229
+ partName: 'C',
230
+ }),
231
+ ).toBe('Missing a comma in the C part. It expects B (REF)');
232
+ });
233
+ });
234
+
235
+ describe('missing-token', () => {
236
+ test('expects: without, partName: without', () => {
237
+ expect(
238
+ __createMessageValueExpected(t, 'A', '', {
239
+ ref: 'REF',
240
+ raw: 'RAW',
241
+ reason: 'missing-token',
242
+ }),
243
+ ).toBe('Missing a token (REF)');
244
+ });
245
+
246
+ test('expects: without, partName: with', () => {
247
+ expect(
248
+ __createMessageValueExpected(t, 'A', '', {
249
+ ref: 'REF',
250
+ raw: 'RAW',
251
+ reason: 'missing-token',
252
+ partName: 'C',
253
+ }),
254
+ ).toBe('Missing the C part. A needs the C part (REF)');
255
+ });
256
+
257
+ test('expects: with, partName: without', () => {
258
+ expect(
259
+ __createMessageValueExpected(t, 'A', 'B', {
260
+ ref: 'REF',
261
+ raw: 'RAW',
262
+ reason: 'missing-token',
263
+ }),
264
+ ).toBe('Missing a token. A needs B (REF)');
265
+ });
266
+
267
+ test('expects: with, partName: with', () => {
268
+ expect(
269
+ __createMessageValueExpected(t, 'A', 'B', {
270
+ ref: 'REF',
271
+ raw: 'RAW',
272
+ reason: 'missing-token',
273
+ partName: 'C',
274
+ }),
275
+ ).toBe('Missing the C part. the C part of A needs B (REF)');
276
+ });
277
+ });
278
+
279
+ describe('unexpected-comma', () => {
280
+ test('expects: without, partName: without', () => {
281
+ expect(
282
+ __createMessageValueExpected(t, 'A', '', {
283
+ ref: 'REF',
284
+ raw: 'RAW',
285
+ reason: 'unexpected-comma',
286
+ }),
287
+ ).toBe('Found unexpected comma (REF)');
288
+ });
289
+
290
+ test('expects: without, partName: with', () => {
291
+ expect(
292
+ __createMessageValueExpected(t, 'A', '', {
293
+ ref: 'REF',
294
+ raw: 'RAW',
295
+ reason: 'unexpected-comma',
296
+ partName: 'C',
297
+ }),
298
+ ).toBe('Found unexpected comma (REF)');
299
+ });
300
+
301
+ test('expects: with, partName: without', () => {
302
+ expect(
303
+ __createMessageValueExpected(t, 'A', 'B', {
304
+ ref: 'REF',
305
+ raw: 'RAW',
306
+ reason: 'unexpected-comma',
307
+ }),
308
+ ).toBe('Found unexpected comma. A expects B (REF)');
309
+ });
310
+
311
+ test('expects: with, partName: with', () => {
312
+ expect(
313
+ __createMessageValueExpected(t, 'A', 'B', {
314
+ ref: 'REF',
315
+ raw: 'RAW',
316
+ reason: 'unexpected-comma',
317
+ partName: 'C',
318
+ }),
319
+ ).toBe('Found unexpected comma. the C part of A expects B (REF)');
320
+ });
321
+ });
322
+
323
+ describe('unexpected-newline', () => {
324
+ test('expects: without, partName: without', () => {
325
+ expect(
326
+ __createMessageValueExpected(t, 'A', '', {
327
+ ref: 'REF',
328
+ raw: 'RAW',
329
+ reason: 'unexpected-newline',
330
+ }),
331
+ ).toBe('Found unexpected newline (REF)');
332
+ });
333
+
334
+ test('expects: without, partName: with', () => {
335
+ expect(
336
+ __createMessageValueExpected(t, 'A', '', {
337
+ ref: 'REF',
338
+ raw: 'RAW',
339
+ reason: 'unexpected-newline',
340
+ partName: 'C',
341
+ }),
342
+ ).toBe('Found unexpected newline (REF)');
343
+ });
344
+
345
+ test('expects: with, partName: without', () => {
346
+ expect(
347
+ __createMessageValueExpected(t, 'A', 'B', {
348
+ ref: 'REF',
349
+ raw: 'RAW',
350
+ reason: 'unexpected-newline',
351
+ }),
352
+ ).toBe('Found unexpected newline. A expects B (REF)');
353
+ });
354
+
355
+ test('expects: with, partName: with', () => {
356
+ expect(
357
+ __createMessageValueExpected(t, 'A', 'B', {
358
+ ref: 'REF',
359
+ raw: 'RAW',
360
+ reason: 'unexpected-newline',
361
+ partName: 'C',
362
+ }),
363
+ ).toBe('Found unexpected newline. the C part of A expects B (REF)');
364
+ });
365
+ });
366
+
367
+ describe('unexpected-space', () => {
368
+ test('expects: without, partName: without', () => {
369
+ expect(
370
+ __createMessageValueExpected(t, 'A', '', {
371
+ ref: 'REF',
372
+ raw: 'RAW',
373
+ reason: 'unexpected-space',
374
+ }),
375
+ ).toBe('Found unexpected whitespace (REF)');
376
+ });
377
+
378
+ test('expects: without, partName: with', () => {
379
+ expect(
380
+ __createMessageValueExpected(t, 'A', '', {
381
+ ref: 'REF',
382
+ raw: 'RAW',
383
+ reason: 'unexpected-space',
384
+ partName: 'C',
385
+ }),
386
+ ).toBe('Found unexpected whitespace (REF)');
387
+ });
388
+
389
+ test('expects: with, partName: without', () => {
390
+ expect(
391
+ __createMessageValueExpected(t, 'A', 'B', {
392
+ ref: 'REF',
393
+ raw: 'RAW',
394
+ reason: 'unexpected-space',
395
+ }),
396
+ ).toBe('Found unexpected whitespace. A expects B (REF)');
397
+ });
398
+
399
+ test('expects: with, partName: with', () => {
400
+ expect(
401
+ __createMessageValueExpected(t, 'A', 'B', {
402
+ ref: 'REF',
403
+ raw: 'RAW',
404
+ reason: 'unexpected-space',
405
+ partName: 'C',
406
+ }),
407
+ ).toBe('Found unexpected whitespace. the C part of A expects B (REF)');
408
+ });
409
+ });
410
+
411
+ describe('unexpected-token', () => {
412
+ test('expects: without, partName: without', () => {
413
+ expect(
414
+ __createMessageValueExpected(t, 'A', '', {
415
+ ref: 'REF',
416
+ raw: 'RAW',
417
+ reason: 'unexpected-token',
418
+ }),
419
+ ).toBe('It includes unexpected characters (REF)');
420
+ });
421
+
422
+ test('expects: without, partName: with', () => {
423
+ expect(
424
+ __createMessageValueExpected(t, 'A', '', {
425
+ ref: 'REF',
426
+ raw: 'RAW',
427
+ reason: 'unexpected-token',
428
+ partName: 'C',
429
+ }),
430
+ ).toBe('the C part includes unexpected characters (REF)');
431
+ });
432
+
433
+ test('expects: with, partName: without', () => {
434
+ expect(
435
+ __createMessageValueExpected(t, 'A', 'B', {
436
+ ref: 'REF',
437
+ raw: 'RAW',
438
+ reason: 'unexpected-token',
439
+ }),
440
+ ).toBe('It includes unexpected characters. A expects B (REF)');
441
+ });
442
+
443
+ test('expects: with, partName: with', () => {
444
+ expect(
445
+ __createMessageValueExpected(t, 'A', 'B', {
446
+ ref: 'REF',
447
+ raw: 'RAW',
448
+ reason: 'unexpected-token',
449
+ partName: 'C',
450
+ }),
451
+ ).toBe('the C part includes unexpected characters. It expects B (REF)');
452
+ });
453
+ });
454
+
455
+ describe('out-of-range-length-digit', () => {
456
+ test('expects: without, partName: without', () => {
457
+ expect(
458
+ __createMessageValueExpected(t, 'A', '', {
459
+ ref: 'REF',
460
+ raw: 'RAW',
461
+ reason: { type: 'out-of-range-length-digit', gte: 4 },
462
+ }),
463
+ ).toBe('A expects four or more digits (REF)');
464
+ });
465
+
466
+ test('expects: without, partName: with', () => {
467
+ expect(
468
+ __createMessageValueExpected(t, 'A', '', {
469
+ ref: 'REF',
470
+ raw: 'RAW',
471
+ reason: { type: 'out-of-range-length-digit', gte: 4 },
472
+ partName: 'C',
473
+ }),
474
+ ).toBe('the C part of A expects four or more digits (REF)');
475
+ });
476
+
477
+ test('expects: with, partName: without', () => {
478
+ expect(
479
+ __createMessageValueExpected(t, 'A', 'B', {
480
+ ref: 'REF',
481
+ raw: 'RAW',
482
+ reason: { type: 'out-of-range-length-digit', gte: 4 },
483
+ }),
484
+ ).toBe('A expects four or more digits and B (REF)');
485
+ });
486
+
487
+ test('expects: with, partName: with', () => {
488
+ expect(
489
+ __createMessageValueExpected(t, 'A', 'B', {
490
+ ref: 'REF',
491
+ raw: 'RAW',
492
+ reason: { type: 'out-of-range-length-digit', gte: 4 },
493
+ partName: 'C',
494
+ }),
495
+ ).toBe('the C part of A expects four or more digits and B (REF)');
496
+ });
497
+ });
@@ -0,0 +1,48 @@
1
+ const { mlRuleTest } = require('markuplint');
2
+
3
+ const rule = require('../../lib/deprecated-attr').default;
4
+
5
+ test('deprecated attribute', async () => {
6
+ const { violations } = await mlRuleTest(rule, '<img align="top">');
7
+ expect(violations).toStrictEqual([
8
+ {
9
+ severity: 'error',
10
+ line: 1,
11
+ col: 6,
12
+ raw: 'align',
13
+ message: 'The "align" attribute is deprecated',
14
+ },
15
+ ]);
16
+ });
17
+
18
+ test('deprecated global attribute', async () => {
19
+ const { violations } = await mlRuleTest(rule, '<img xml:lang="en-US">');
20
+ expect(violations).toStrictEqual([
21
+ {
22
+ severity: 'error',
23
+ line: 1,
24
+ col: 6,
25
+ raw: 'xml:lang',
26
+ message: 'The "xml:lang" attribute is deprecated',
27
+ },
28
+ ]);
29
+ });
30
+
31
+ test('svg', async () => {
32
+ const { violations } = await mlRuleTest(
33
+ rule,
34
+ `<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg">
35
+ <a xlink:href="https://developer.mozilla.org/">
36
+ <text x="10" y="25">MDN Web Docs</text></a>
37
+ </svg>`,
38
+ );
39
+ expect(violations).toStrictEqual([
40
+ {
41
+ severity: 'error',
42
+ line: 2,
43
+ col: 14,
44
+ message: 'The "xlink:href" attribute is deprecated',
45
+ raw: 'xlink:href',
46
+ },
47
+ ]);
48
+ });
@@ -0,0 +1,48 @@
1
+ const { mlRuleTest } = require('markuplint');
2
+
3
+ const rule = require('../../lib/deprecated-element').default;
4
+
5
+ test('normal', async () => {
6
+ const { violations } = await mlRuleTest(rule, '<div></div><p><span></span></p>');
7
+ expect(violations).toStrictEqual([]);
8
+ });
9
+
10
+ test('deprecated', async () => {
11
+ const { violations } = await mlRuleTest(rule, '<font></font><big><blink></blink></big>');
12
+ expect(violations).toStrictEqual([
13
+ {
14
+ severity: 'error',
15
+ message: 'The "font" element is obsolete',
16
+ line: 1,
17
+ col: 1,
18
+ raw: '<font>',
19
+ },
20
+ {
21
+ severity: 'error',
22
+ message: 'The "big" element is obsolete',
23
+ line: 1,
24
+ col: 14,
25
+ raw: '<big>',
26
+ },
27
+ {
28
+ severity: 'error',
29
+ message: 'The "blink" element is obsolete',
30
+ line: 1,
31
+ col: 19,
32
+ raw: '<blink>',
33
+ },
34
+ ]);
35
+ });
36
+
37
+ test('svg', async () => {
38
+ const { violations } = await mlRuleTest(rule, '<svg><altGlyph>text</altGlyph></svg>');
39
+ expect(violations).toStrictEqual([
40
+ {
41
+ severity: 'error',
42
+ message: 'The "altGlyph" element is obsolete',
43
+ line: 1,
44
+ col: 6,
45
+ raw: '<altGlyph>',
46
+ },
47
+ ]);
48
+ });
@@ -0,0 +1,90 @@
1
+ const { mlRuleTest } = require('markuplint');
2
+
3
+ const rule = require('../../lib/disallowed-element').default;
4
+
5
+ it('specifies to global rule', async () => {
6
+ const { violations } = await mlRuleTest(rule, '<div><hgroup><h1>Heading</h1></hgroup></div>', {
7
+ rule: ['hgroup'],
8
+ });
9
+ expect(violations).toStrictEqual([
10
+ {
11
+ severity: 'error',
12
+ line: 1,
13
+ col: 6,
14
+ raw: '<hgroup>',
15
+ message: 'The "hgroup" element is disallowed',
16
+ },
17
+ ]);
18
+ });
19
+
20
+ it('specifies to node rule', async () => {
21
+ const { violations } = await mlRuleTest(rule, '<h1><span>Title</span><small>Sub-title</small></h1>', {
22
+ nodeRule: [
23
+ {
24
+ selector: 'h1, h2, h3, h4, h5, h6',
25
+ rule: ['small'],
26
+ },
27
+ ],
28
+ });
29
+ expect(violations).toStrictEqual([
30
+ {
31
+ severity: 'error',
32
+ line: 1,
33
+ col: 23,
34
+ raw: '<small>',
35
+ message: 'The "small" element is disallowed',
36
+ },
37
+ ]);
38
+ });
39
+
40
+ it('Recommend', async () => {
41
+ expect(
42
+ (
43
+ await mlRuleTest(
44
+ rule,
45
+ '<details><summary><label id="foo">foo</label></summary><input id="foo"/></details>',
46
+ {
47
+ nodeRule: [
48
+ {
49
+ selector: 'summary',
50
+ rule: ['label'],
51
+ },
52
+ ],
53
+ },
54
+ )
55
+ ).violations,
56
+ ).toStrictEqual([
57
+ {
58
+ severity: 'error',
59
+ line: 1,
60
+ col: 19,
61
+ raw: '<label id="foo">',
62
+ message: 'The "label" element is disallowed',
63
+ },
64
+ ]);
65
+
66
+ expect(
67
+ (
68
+ await mlRuleTest(
69
+ rule,
70
+ '<details><summary><label id="foo">foo</label></summary><input id="foo"/></details>',
71
+ {
72
+ nodeRule: [
73
+ {
74
+ selector: 'summary',
75
+ rule: [':model(interactive)'],
76
+ },
77
+ ],
78
+ },
79
+ )
80
+ ).violations,
81
+ ).toStrictEqual([
82
+ {
83
+ severity: 'error',
84
+ line: 1,
85
+ col: 19,
86
+ raw: '<label id="foo">',
87
+ message: 'The ":model(interactive)" element is disallowed',
88
+ },
89
+ ]);
90
+ });