Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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