@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.
- package/lib/helpers.d.ts +2 -5
- package/lib/index.d.ts +240 -99
- package/lib/invalid-attr/index.d.ts +38 -31
- package/lib/no-refer-to-non-existent-id/index.d.ts +1 -2
- package/lib/no-refer-to-non-existent-id/index.js +2 -1
- package/lib/require-accessible-name/index.js +1 -1
- package/lib/required-attr/index.d.ts +1 -1
- package/lib/required-attr/index.js +1 -1
- package/lib/wai-aria/checkings/_.d.ts +15 -0
- package/lib/wai-aria/checkings/_.js +27 -0
- package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
- package/lib/wai-aria/checkings/required-prop copy.js +27 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
- package/lib/wai-aria/index.js +2 -1
- package/lib/xxx/index.d.ts +2 -0
- package/lib/xxx/index.js +32 -0
- package/package.json +11 -13
- package/test/attr-check.spec.js +77 -0
- package/test/attr-duplication/index.spec.js +159 -0
- package/test/attr-value-quotes/index.spec.js +133 -0
- package/test/case-sensitive-attr-name/index.spec.js +65 -0
- package/test/case-sensitive-tag-name/index.spec.js +80 -0
- package/test/character-reference/index.spec.js +57 -0
- package/test/class-naming/index.spec.js +470 -0
- package/test/create-message.spec.js +497 -0
- package/test/deprecated-attr/index.spec.js +48 -0
- package/test/deprecated-element/index.spec.js +48 -0
- package/test/disallowed-element/index.spec.js +90 -0
- package/test/doctype/index.spec.js +50 -0
- package/test/end-tag/index.spec.js +162 -0
- package/test/id-duplication/index.spec.js +47 -0
- package/test/ineffective-attr/index.spec.js +31 -0
- package/test/invalid-attr/index.spec.js +1632 -0
- package/test/label-has-control/index.spec.js +29 -0
- package/test/landmark-roles/index.spec.js +187 -0
- package/test/no-boolean-attr-value/index.spec.js +41 -0
- package/test/no-default-value/index.spec.js +74 -0
- package/test/no-empty-palpable-content/index.spec.js +115 -0
- package/test/no-hard-code-id/index.spec.js +100 -0
- package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
- package/test/no-use-event-handler-attr/index.spec.js +57 -0
- package/test/permitted-contents/choice.spec.js +174 -0
- package/test/permitted-contents/count-pattern.spec.js +308 -0
- package/test/permitted-contents/index.spec.js +1371 -0
- package/test/permitted-contents/matches-selector.spec.js +59 -0
- package/test/permitted-contents/order.spec.js +351 -0
- package/test/permitted-contents/recursive-branch.spec.js +41 -0
- package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
- package/test/permitted-contents/start.spec.js +67 -0
- package/test/placeholder-label-option/index.spec.js +113 -0
- package/test/require-accessible-name/index.spec.js +446 -0
- package/test/require-datetime/index.spec.js +54 -0
- package/test/require-datetime/utils.spec.js +52 -0
- package/test/required-attr/index.spec.js +414 -0
- package/test/required-element/index.spec.js +188 -0
- package/test/required-h1/index.spec.js +69 -0
- package/test/use-list/index.spec.js +109 -0
- package/test/wai-aria/checkings/value.spec.js +33 -0
- package/test/wai-aria/index.spec.js +1173 -0
|
@@ -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
|
+
});
|