Skip to content

Commit ffc9392

Browse files
authored
feat(valid-title): allow custom matcher messages (#913)
1 parent 14a2d13 commit ffc9392

File tree

3 files changed

+252
-43
lines changed

3 files changed

+252
-43
lines changed

docs/rules/valid-title.md

+30-2
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,9 @@ describe('the proper way to handle things', () => {});
198198
Defaults: `{}`
199199

200200
Allows enforcing that titles must match or must not match a given Regular
201-
Expression. An object can be provided to apply different Regular Expressions to
202-
specific Jest test function groups (`describe`, `test`, and `it`).
201+
Expression, with an optional message. An object can be provided to apply
202+
different Regular Expressions (with optional messages) to specific Jest test
203+
function groups (`describe`, `test`, and `it`).
203204

204205
Examples of **incorrect** code when using `mustMatch`:
205206

@@ -226,3 +227,30 @@ describe('the tests that will be run', () => {});
226227
test('that the stuff works', () => {});
227228
xtest('that errors that thrown have messages', () => {});
228229
```
230+
231+
Optionally you can provide a custom message to show for a particular matcher by
232+
using a tuple at any level where you can provide a matcher:
233+
234+
```js
235+
const prefixes = ['when', 'with', 'without', 'if', 'unless', 'for'];
236+
const prefixesList = prefixes.join(' - \n');
237+
238+
module.exports = {
239+
rules: {
240+
'jest/valid-title': [
241+
'error',
242+
{
243+
mustNotMatch: ['\\.$', 'Titles should not end with a full-stop'],
244+
mustMatch: {
245+
describe: [
246+
new RegExp(`^(?:[A-Z]|\\b(${prefixes.join('|')})\\b`, 'u').source,
247+
`Describe titles should either start with a capital letter or one of the following prefixes: ${prefixesList}`,
248+
],
249+
test: [/[^A-Z]/u.source],
250+
it: /[^A-Z]/u.source,
251+
},
252+
},
253+
],
254+
},
255+
};
256+
```

src/rules/__tests__/valid-title.test.ts

+146-2
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,16 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
107107
'test("that all is as it should be", () => {});',
108108
{
109109
code: 'it("correctly sets the value", () => {});',
110-
options: [{ mustMatch: undefined }],
110+
options: [{ mustMatch: {} }],
111111
},
112112
{
113113
code: 'it("correctly sets the value", () => {});',
114114
options: [{ mustMatch: / /u.source }],
115115
},
116+
{
117+
code: 'it("correctly sets the value", () => {});',
118+
options: [{ mustMatch: [/ /u.source] }],
119+
},
116120
{
117121
code: 'it("correctly sets the value #unit", () => {});',
118122
options: [{ mustMatch: /#(?:unit|integration|e2e)/u.source }],
@@ -200,7 +204,56 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
200204
`,
201205
options: [
202206
{
203-
mustNotMatch: { describe: /(?:#(?!unit|e2e))\w+/u.source },
207+
mustNotMatch: [
208+
/(?:#(?!unit|e2e))\w+/u.source,
209+
'Please include "#unit" or "#e2e" in titles',
210+
],
211+
mustMatch: [
212+
/^[^#]+$|(?:#(?:unit|e2e))/u.source,
213+
'Please include "#unit" or "#e2e" in titles',
214+
],
215+
},
216+
],
217+
errors: [
218+
{
219+
messageId: 'mustNotMatchCustom',
220+
data: {
221+
jestFunctionName: 'describe',
222+
pattern: /(?:#(?!unit|e2e))\w+/u,
223+
message: 'Please include "#unit" or "#e2e" in titles',
224+
},
225+
column: 12,
226+
line: 8,
227+
},
228+
{
229+
messageId: 'mustNotMatchCustom',
230+
data: {
231+
jestFunctionName: 'it',
232+
pattern: /(?:#(?!unit|e2e))\w+/u,
233+
message: 'Please include "#unit" or "#e2e" in titles',
234+
},
235+
column: 8,
236+
line: 9,
237+
},
238+
],
239+
},
240+
{
241+
code: dedent`
242+
describe('things to test', () => {
243+
describe('unit tests #unit', () => {
244+
it('is true', () => {
245+
expect(true).toBe(true);
246+
});
247+
});
248+
249+
describe('e2e tests #e4e', () => {
250+
it('is another test #e2e #jest4life', () => {});
251+
});
252+
});
253+
`,
254+
options: [
255+
{
256+
mustNotMatch: { describe: [/(?:#(?!unit|e2e))\w+/u.source] },
204257
mustMatch: { describe: /^[^#]+$|(?:#(?:unit|e2e))/u.source },
205258
},
206259
],
@@ -230,6 +283,44 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
230283
});
231284
});
232285
`,
286+
options: [
287+
{
288+
mustNotMatch: {
289+
describe: [
290+
/(?:#(?!unit|e2e))\w+/u.source,
291+
'Please include "#unit" or "#e2e" in describe titles',
292+
],
293+
},
294+
mustMatch: { describe: /^[^#]+$|(?:#(?:unit|e2e))/u.source },
295+
},
296+
],
297+
errors: [
298+
{
299+
messageId: 'mustNotMatchCustom',
300+
data: {
301+
jestFunctionName: 'describe',
302+
pattern: /(?:#(?!unit|e2e))\w+/u,
303+
message: 'Please include "#unit" or "#e2e" in describe titles',
304+
},
305+
column: 12,
306+
line: 8,
307+
},
308+
],
309+
},
310+
{
311+
code: dedent`
312+
describe('things to test', () => {
313+
describe('unit tests #unit', () => {
314+
it('is true', () => {
315+
expect(true).toBe(true);
316+
});
317+
});
318+
319+
describe('e2e tests #e4e', () => {
320+
it('is another test #e2e #jest4life', () => {});
321+
});
322+
});
323+
`,
233324
options: [
234325
{
235326
mustNotMatch: { describe: /(?:#(?!unit|e2e))\w+/u.source },
@@ -248,6 +339,59 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
248339
},
249340
],
250341
},
342+
{
343+
code: dedent`
344+
describe('things to test', () => {
345+
describe('unit tests #unit', () => {
346+
it('is true #jest4life', () => {
347+
expect(true).toBe(true);
348+
});
349+
});
350+
351+
describe('e2e tests #e4e', () => {
352+
it('is another test #e2e #jest4life', () => {});
353+
});
354+
});
355+
`,
356+
options: [
357+
{
358+
mustNotMatch: {
359+
describe: [
360+
/(?:#(?!unit|e2e))\w+/u.source,
361+
'Please include "#unit" or "#e2e" in describe titles',
362+
],
363+
},
364+
mustMatch: {
365+
it: [
366+
/^[^#]+$|(?:#(?:unit|e2e))/u.source,
367+
'Please include "#unit" or "#e2e" in it titles',
368+
],
369+
},
370+
},
371+
],
372+
errors: [
373+
{
374+
messageId: 'mustMatchCustom',
375+
data: {
376+
jestFunctionName: 'it',
377+
pattern: /^[^#]+$|(?:#(?:unit|e2e))/u,
378+
message: 'Please include "#unit" or "#e2e" in it titles',
379+
},
380+
column: 8,
381+
line: 3,
382+
},
383+
{
384+
messageId: 'mustNotMatchCustom',
385+
data: {
386+
jestFunctionName: 'describe',
387+
pattern: /(?:#(?!unit|e2e))\w+/u,
388+
message: 'Please include "#unit" or "#e2e" in describe titles',
389+
},
390+
column: 12,
391+
line: 8,
392+
},
393+
],
394+
},
251395
{
252396
code: 'test("the correct way to properly handle all things", () => {});',
253397
options: [{ mustMatch: /#(?:unit|integration|e2e)/u.source }],

0 commit comments

Comments
 (0)