/
test.js
329 lines (298 loc) · 9.83 KB
/
test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
'use strict'
const test = require('tape')
const remark = require('remark')
const lint = require('remark-lint')
const vfile = require('vfile')
const noProhibitedStrings = require('./')
const processorWithOptions =
(options) => remark().use(lint).use(noProhibitedStrings, options)
test('remark-lint-prohibited-strings', (t) => {
const path = 'fhqwhgads.md'
{
const contents = 'the v8 javascript engine'
t.deepEqual(
processorWithOptions([])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should not flag anything if no options set'
)
}
{
const contents = 'the v8 javascript engine'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:5-1:7: Use "V8" instead of "v8"'],
'should flag string if option set'
)
}
{
const contents = 'the V8 JavaScript engine'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should not flag string if it is not prohibited'
)
}
{
const contents = '# fhqwhgads.v8'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore prohibited string if it is in code (preceded by .)'
)
}
{
const contents = '# v8.fhqwhgads'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore prohibited string if it is in code (followed by .word)'
)
}
{
const contents = 'The name of this band is v8.'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:26-1:28: Use "V8" instead of "v8"'],
'should flag prohibited string if it is followed by . alone'
)
}
{
const contents = 'The gatsby-specific way to do this is as follows:'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: 'gatsby(?!-)\\b' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should allow negative lookaheads with custom regular expression config'
)
}
{
const contents = 'word-gatsby gatsby-word word-gatsby-word'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: '\\b(?<!-)gatsby(?!-)\\b' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should allow negative lookaheads and lookbehinds'
)
}
{
const contents = 'word-gatsby gatsby-word word-gatsby-word gatsby'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: '\\b(?<!-)gatsby(?!-)\\b' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:42-1:48: Use "Gatsby" instead of "gatsby"'],
'should still find things that do not match lookahead/lookbehind'
)
}
{
const contents = 'gatsbyfoo foogatsby foogatsbyfoo'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: '\\b(?<!-)gatsby(?!-)\\b' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should still match on word boundaries with lookahead/lookbehind'
)
}
{
const contents = 'The fhqwhgads.v8 page for the band v8 rocks.'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:36-1:38: Use "V8" instead of "v8"'],
'should flag prohibited string even if an allowed usage precedes it'
)
}
{
const contents = '@nodejs/v8-inspector'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore prohibited string if it is part of an @-mention'
)
}
{
const contents = '@Nodejs/v8-inspector'
t.deepEqual(
processorWithOptions([{ yes: 'V8', no: 'v8' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore prohibited string if it is part of an @-Mention'
)
}
{
const contents = 'RfC123'
t.deepEqual(
processorWithOptions([{ yes: 'RFC <number>', no: '[Rr][Ff][Cc]\\d+' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:1-1:7: Use "RFC <number>" instead of "RfC123"'],
'should provide reasonable output from regexp-y things'
)
}
{
const contents = 'denote that'
t.deepEqual(
processorWithOptions([{ no: 'note that', yes: '<nothing>' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should assume word breaks'
)
}
{
const contents = '`the-gatsby-kebab-in-code`'
t.deepEqual(
processorWithOptions([{ no: 'gatsby', yes: 'Gatsby' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore strings in backticks'
)
}
{
const contents = '```\nthe-gatsby-kebab-in-code\n```'
t.deepEqual(
processorWithOptions([{ no: 'gatsby', yes: 'Gatsby' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should ignore strings in code fences'
)
}
{
const contents = "for Node.js' stuff\n\nand Node.js's stuff too"
t.deepEqual(
processorWithOptions([{ no: "Node\\.js's?", yes: 'the Node.js' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[
'fhqwhgads.md:1:5-1:13: Use "the Node.js" instead of "Node.js\'"',
'fhqwhgads.md:3:5-3:14: Use "the Node.js" instead of "Node.js\'s"'
],
'should allow flagging of apostrophes as final characters in "no" string'
)
}
{
const contents = 'gatsby Gatsby gatsby'
t.deepEqual(
processorWithOptions([{ no: 'gatsby', yes: 'Gatsby' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[
'fhqwhgads.md:1:1-1:7: Use "Gatsby" instead of "gatsby"',
'fhqwhgads.md:1:15-1:21: Use "Gatsby" instead of "gatsby"'
],
'should flag multiple violations in a single node'
)
}
{
const contents = 'The gatsby-specific way to do this is as follows:'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: 'gatsby', ignoreNextTo: '-' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should respect ignoreNextTo'
)
}
{
const contents = 'word-gatsby gatsby-word word-gatsby-word'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: 'gatsby', ignoreNextTo: '-' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should respect multiple ignoreNextTo occurrences'
)
}
{
const contents = 'word-gatsby gatsby-word word-gatsby-word gatsby'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: 'gatsby', ignoreNextTo: '-' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:42-1:48: Use "Gatsby" instead of "gatsby"'],
'should still find things that do not match ignoreNextTo'
)
}
{
const contents = 'gatsbyfoo foogatsby foogatsbyfoo'
t.deepEqual(
processorWithOptions([{ yes: 'Gatsby', no: 'gatsby', ignoreNextTo: '-' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should still match on word boundaries with ignoreNextTo'
)
}
{
const contents = 'You got Sblounchsked!'
t.deepEqual(
processorWithOptions([{ no: 'Sblounchsked' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:9-1:21: Do not use "Sblounchsked"'],
'should permit omitting the yes option'
)
}
{
const contents = 'strong bad'
t.deepEqual(
processorWithOptions([{ yes: 'Strong Bad' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:1-1:11: Use "Strong Bad" instead of "strong bad"'],
'should flag when there is a `yes` option but no `no` option'
)
}
{
const contents = 'Strong Bad'
t.deepEqual(
processorWithOptions([{ yes: 'Strong Bad' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
[],
'should allow identical case with `yes` option but no `no` option'
)
}
{
const contents = 'end-of-life nodefjs version'
t.deepEqual(
processorWithOptions([{ yes: 'End-of-Life' }, { yes: 'Node.js' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:1:1-1:12: Use "End-of-Life" instead of "end-of-life"'],
'should escape regexp special chars with `yes` option but no `no` option'
)
}
{
const contents = 'Fhqwhgads\n\nType: End-of-life'
t.deepEqual(
processorWithOptions([{ yes: 'End-of-Life' }])
.processSync(vfile({ path: path, contents: contents }))
.messages.map(String),
['fhqwhgads.md:3:7-3:18: Use "End-of-Life" instead of "End-of-life"'],
'should flag yes-only violations on lines other than the first line'
)
}
t.end()
})