Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(valid-title): allow custom matcher messages #913

Merged
merged 7 commits into from
Sep 29, 2021
32 changes: 30 additions & 2 deletions docs/rules/valid-title.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ describe('the proper way to handle things', () => {});
Defaults: `{}`

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

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

Expand All @@ -226,3 +227,30 @@ describe('the tests that will be run', () => {});
test('that the stuff works', () => {});
xtest('that errors that thrown have messages', () => {});
```

Optionally you can provide a custom message to show for a particular matcher by
using a tuple at any level where you can provide a matcher:

```js
const prefixes = ['when', 'with', 'without', 'if', 'unless', 'for'];
const prefixesList = prefixes.join(' - \n');

module.exports = {
rules: {
'jest/valid-title': [
'error',
{
mustNotMatch: ['\\.$', 'Titles should not end with a full-stop'],
mustMatch: {
describe: [
new RegExp(`^(?:[A-Z]|\\b(${prefixes.join('|')})\\b`, 'u').source,
`Describe titles should either start with a capital letter or one of the following prefixes: ${prefixesList}`,
],
test: [/[^A-Z]/u.source],
it: /[^A-Z]/u.source,
},
},
],
},
};
```
148 changes: 146 additions & 2 deletions src/rules/__tests__/valid-title.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
'test("that all is as it should be", () => {});',
{
code: 'it("correctly sets the value", () => {});',
options: [{ mustMatch: undefined }],
options: [{ mustMatch: {} }],
},
{
code: 'it("correctly sets the value", () => {});',
options: [{ mustMatch: / /u.source }],
},
{
code: 'it("correctly sets the value", () => {});',
options: [{ mustMatch: [/ /u.source] }],
},
{
code: 'it("correctly sets the value #unit", () => {});',
options: [{ mustMatch: /#(?:unit|integration|e2e)/u.source }],
Expand Down Expand Up @@ -200,7 +204,56 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
`,
options: [
{
mustNotMatch: { describe: /(?:#(?!unit|e2e))\w+/u.source },
mustNotMatch: [
/(?:#(?!unit|e2e))\w+/u.source,
'Please include "#unit" or "#e2e" in titles',
],
mustMatch: [
/^[^#]+$|(?:#(?:unit|e2e))/u.source,
'Please include "#unit" or "#e2e" in titles',
],
},
],
errors: [
{
messageId: 'mustNotMatchCustom',
data: {
jestFunctionName: 'describe',
pattern: /(?:#(?!unit|e2e))\w+/u,
message: 'Please include "#unit" or "#e2e" in titles',
},
column: 12,
line: 8,
},
{
messageId: 'mustNotMatchCustom',
data: {
jestFunctionName: 'it',
pattern: /(?:#(?!unit|e2e))\w+/u,
message: 'Please include "#unit" or "#e2e" in titles',
},
column: 8,
line: 9,
},
],
},
{
code: dedent`
describe('things to test', () => {
describe('unit tests #unit', () => {
it('is true', () => {
expect(true).toBe(true);
});
});

describe('e2e tests #e4e', () => {
it('is another test #e2e #jest4life', () => {});
});
});
`,
options: [
{
mustNotMatch: { describe: [/(?:#(?!unit|e2e))\w+/u.source] },
mustMatch: { describe: /^[^#]+$|(?:#(?:unit|e2e))/u.source },
},
],
Expand Down Expand Up @@ -230,6 +283,44 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
});
});
`,
options: [
{
mustNotMatch: {
describe: [
/(?:#(?!unit|e2e))\w+/u.source,
'Please include "#unit" or "#e2e" in describe titles',
],
},
mustMatch: { describe: /^[^#]+$|(?:#(?:unit|e2e))/u.source },
},
],
errors: [
{
messageId: 'mustNotMatchCustom',
data: {
jestFunctionName: 'describe',
pattern: /(?:#(?!unit|e2e))\w+/u,
message: 'Please include "#unit" or "#e2e" in describe titles',
},
column: 12,
line: 8,
},
],
},
{
code: dedent`
describe('things to test', () => {
describe('unit tests #unit', () => {
it('is true', () => {
expect(true).toBe(true);
});
});

describe('e2e tests #e4e', () => {
it('is another test #e2e #jest4life', () => {});
});
});
`,
options: [
{
mustNotMatch: { describe: /(?:#(?!unit|e2e))\w+/u.source },
Expand All @@ -248,6 +339,59 @@ ruleTester.run('mustMatch & mustNotMatch options', rule, {
},
],
},
{
code: dedent`
describe('things to test', () => {
describe('unit tests #unit', () => {
it('is true #jest4life', () => {
expect(true).toBe(true);
});
});

describe('e2e tests #e4e', () => {
it('is another test #e2e #jest4life', () => {});
});
});
`,
options: [
{
mustNotMatch: {
describe: [
/(?:#(?!unit|e2e))\w+/u.source,
'Please include "#unit" or "#e2e" in describe titles',
],
},
mustMatch: {
it: [
/^[^#]+$|(?:#(?:unit|e2e))/u.source,
'Please include "#unit" or "#e2e" in it titles',
],
},
},
],
errors: [
{
messageId: 'mustMatchCustom',
data: {
jestFunctionName: 'it',
pattern: /^[^#]+$|(?:#(?:unit|e2e))/u,
message: 'Please include "#unit" or "#e2e" in it titles',
},
column: 8,
line: 3,
},
{
messageId: 'mustNotMatchCustom',
data: {
jestFunctionName: 'describe',
pattern: /(?:#(?!unit|e2e))\w+/u,
message: 'Please include "#unit" or "#e2e" in describe titles',
},
column: 12,
line: 8,
},
],
},
{
code: 'test("the correct way to properly handle all things", () => {});',
options: [{ mustMatch: /#(?:unit|integration|e2e)/u.source }],
Expand Down
Loading