Skip to content

Commit 4658638

Browse files
hainenberG-Rath
andauthored
feat(prefer-lowercase-title): allow ignoring todos (#1843)
* feat(rule): allow ignoring test.todo Jest functions for `prefer-lowercase-title` rule Signed-off-by: hainenber <dotronghai96@gmail.com> * fix: remove wrong conditionals Signed-off-by: hainenber <dotronghai96@gmail.com> * Apply suggestion from @G-Rath Co-authored-by: Gareth Jones <3151613+G-Rath@users.noreply.github.com> * chore: add tests to cover more invalid cases Signed-off-by: hainenber <dotronghai96@gmail.com> * test: add a few more cases --------- Signed-off-by: hainenber <dotronghai96@gmail.com> Co-authored-by: Gareth Jones <3151613+G-Rath@users.noreply.github.com>
1 parent 5842ea3 commit 4658638

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

docs/rules/prefer-lowercase-title.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,18 @@ describe('MyClass', () => {
109109
});
110110
});
111111
```
112+
113+
### `ignoreTodos`
114+
115+
This option is used to control whether
116+
[`todo`](https://jestjs.io/docs/api#testtodoname) Jest functions to be checked
117+
by this rule. By the default, the option is set to false.
118+
119+
Example of **correct** code for the `{ "ignoreTodos": true }` option:
120+
121+
```js
122+
/* eslint jest/prefer-lowercase-title: ["error", { "ignoreTodos": true }] */
123+
test.todo('Uppercase description');
124+
125+
it.todo('Uppercase description');
126+
```

src/rules/__tests__/prefer-lowercase-title.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,3 +646,95 @@ ruleTester.run('prefer-lowercase-title with ignoreTopLevelDescribe', rule, {
646646
},
647647
],
648648
});
649+
650+
ruleTester.run('prefer-lowercase-title with ignoreTodos', rule, {
651+
valid: [
652+
{
653+
code: 'test.todo(`Foo`, function () {})',
654+
options: [{ ignoreTodos: true }],
655+
},
656+
{
657+
code: 'it.todo(`Foo`, function () {})',
658+
options: [{ ignoreTodos: true }],
659+
},
660+
{
661+
code: 'it.todo("Foo", () => {})',
662+
options: [{ ignoreTodos: true }],
663+
},
664+
{
665+
code: 'it.only.todo("Foo", () => {})',
666+
options: [{ ignoreTodos: true }],
667+
},
668+
{
669+
code: 'it.todo.only("Foo", () => {})',
670+
options: [{ ignoreTodos: true }],
671+
},
672+
],
673+
invalid: [
674+
{
675+
code: "describe('Foo', function () {})",
676+
output: "describe('foo', function () {})",
677+
options: [{ ignoreTodos: true }],
678+
errors: [
679+
{
680+
messageId: 'unexpectedCase',
681+
data: { method: DescribeAlias.describe },
682+
column: 10,
683+
line: 1,
684+
},
685+
],
686+
},
687+
{
688+
code: "it('Foo', function () {})",
689+
output: "it('foo', function () {})",
690+
options: [{ ignoreTodos: true }],
691+
errors: [
692+
{
693+
messageId: 'unexpectedCase',
694+
data: { method: TestCaseName.it },
695+
column: 4,
696+
line: 1,
697+
},
698+
],
699+
},
700+
{
701+
code: "test('Foo', function () {})",
702+
output: "test('foo', function () {})",
703+
options: [{ ignoreTodos: true }],
704+
errors: [
705+
{
706+
messageId: 'unexpectedCase',
707+
data: { method: TestCaseName.test },
708+
column: 6,
709+
line: 1,
710+
},
711+
],
712+
},
713+
{
714+
code: "test.only('Foo', function () {})",
715+
output: "test.only('foo', function () {})",
716+
options: [{ ignoreTodos: true }],
717+
errors: [
718+
{
719+
messageId: 'unexpectedCase',
720+
data: { method: TestCaseName.test },
721+
column: 11,
722+
line: 1,
723+
},
724+
],
725+
},
726+
{
727+
code: "test.skip('Foo', function () {})",
728+
output: "test.skip('foo', function () {})",
729+
options: [{ ignoreTodos: true }],
730+
errors: [
731+
{
732+
messageId: 'unexpectedCase',
733+
data: { method: TestCaseName.test },
734+
column: 11,
735+
line: 1,
736+
},
737+
],
738+
},
739+
],
740+
});

src/rules/prefer-lowercase-title.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
type StringNode,
66
TestCaseName,
77
createRule,
8+
getAccessorValue,
89
getStringValue,
910
isStringNode,
1011
isTypeOfJestFnCall,
@@ -47,6 +48,7 @@ export default createRule<
4748
ignore: readonly IgnorableFunctionExpressions[];
4849
allowedPrefixes: readonly string[];
4950
ignoreTopLevelDescribe: boolean;
51+
ignoreTodos: boolean;
5052
}>,
5153
],
5254
'unexpectedCase'
@@ -88,17 +90,33 @@ export default createRule<
8890
type: 'boolean',
8991
default: false,
9092
},
93+
ignoreTodos: {
94+
type: 'boolean',
95+
default: false,
96+
},
9197
},
9298
additionalProperties: false,
9399
},
94100
],
95101
},
96102
defaultOptions: [
97-
{ ignore: [], allowedPrefixes: [], ignoreTopLevelDescribe: false },
103+
{
104+
ignore: [],
105+
allowedPrefixes: [],
106+
ignoreTopLevelDescribe: false,
107+
ignoreTodos: false,
108+
},
98109
],
99110
create(
100111
context,
101-
[{ ignore = [], allowedPrefixes = [], ignoreTopLevelDescribe }],
112+
[
113+
{
114+
ignore = [],
115+
allowedPrefixes = [],
116+
ignoreTopLevelDescribe,
117+
ignoreTodos,
118+
},
119+
],
102120
) {
103121
const ignores = populateIgnores(ignore);
104122
let numberOfDescribeBlocks = 0;
@@ -121,6 +139,14 @@ export default createRule<
121139
return;
122140
}
123141

142+
// Ignore *.todo test and/or test suites
143+
if (
144+
ignoreTodos &&
145+
jestFnCall.members.some(s => getAccessorValue(s) === 'todo')
146+
) {
147+
return;
148+
}
149+
124150
const [firstArg] = node.arguments;
125151

126152
const description = getStringValue(firstArg);

0 commit comments

Comments
 (0)