diff --git a/docs/rules/prefer-lowercase-title.md b/docs/rules/prefer-lowercase-title.md index d0c1cf094..221d5cfa5 100644 --- a/docs/rules/prefer-lowercase-title.md +++ b/docs/rules/prefer-lowercase-title.md @@ -109,3 +109,18 @@ describe('MyClass', () => { }); }); ``` + +### `ignoreTodos` + +This option is used to control whether +[`todo`](https://jestjs.io/docs/api#testtodoname) Jest functions to be checked +by this rule. By the default, the option is set to false. + +Example of **correct** code for the `{ "ignoreTodos": true }` option: + +```js +/* eslint jest/prefer-lowercase-title: ["error", { "ignoreTodos": true }] */ +test.todo('Uppercase description'); + +it.todo('Uppercase description'); +``` diff --git a/src/rules/__tests__/prefer-lowercase-title.test.ts b/src/rules/__tests__/prefer-lowercase-title.test.ts index 5a98542a4..9bfbb4247 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -646,3 +646,95 @@ ruleTester.run('prefer-lowercase-title with ignoreTopLevelDescribe', rule, { }, ], }); + +ruleTester.run('prefer-lowercase-title with ignoreTodos', rule, { + valid: [ + { + code: 'test.todo(`Foo`, function () {})', + options: [{ ignoreTodos: true }], + }, + { + code: 'it.todo(`Foo`, function () {})', + options: [{ ignoreTodos: true }], + }, + { + code: 'it.todo("Foo", () => {})', + options: [{ ignoreTodos: true }], + }, + { + code: 'it.only.todo("Foo", () => {})', + options: [{ ignoreTodos: true }], + }, + { + code: 'it.todo.only("Foo", () => {})', + options: [{ ignoreTodos: true }], + }, + ], + invalid: [ + { + code: "describe('Foo', function () {})", + output: "describe('foo', function () {})", + options: [{ ignoreTodos: true }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: DescribeAlias.describe }, + column: 10, + line: 1, + }, + ], + }, + { + code: "it('Foo', function () {})", + output: "it('foo', function () {})", + options: [{ ignoreTodos: true }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: TestCaseName.it }, + column: 4, + line: 1, + }, + ], + }, + { + code: "test('Foo', function () {})", + output: "test('foo', function () {})", + options: [{ ignoreTodos: true }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: TestCaseName.test }, + column: 6, + line: 1, + }, + ], + }, + { + code: "test.only('Foo', function () {})", + output: "test.only('foo', function () {})", + options: [{ ignoreTodos: true }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: TestCaseName.test }, + column: 11, + line: 1, + }, + ], + }, + { + code: "test.skip('Foo', function () {})", + output: "test.skip('foo', function () {})", + options: [{ ignoreTodos: true }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: TestCaseName.test }, + column: 11, + line: 1, + }, + ], + }, + ], +}); diff --git a/src/rules/prefer-lowercase-title.ts b/src/rules/prefer-lowercase-title.ts index 96a2f97aa..177f595a9 100644 --- a/src/rules/prefer-lowercase-title.ts +++ b/src/rules/prefer-lowercase-title.ts @@ -5,6 +5,7 @@ import { type StringNode, TestCaseName, createRule, + getAccessorValue, getStringValue, isStringNode, isTypeOfJestFnCall, @@ -47,6 +48,7 @@ export default createRule< ignore: readonly IgnorableFunctionExpressions[]; allowedPrefixes: readonly string[]; ignoreTopLevelDescribe: boolean; + ignoreTodos: boolean; }>, ], 'unexpectedCase' @@ -88,17 +90,33 @@ export default createRule< type: 'boolean', default: false, }, + ignoreTodos: { + type: 'boolean', + default: false, + }, }, additionalProperties: false, }, ], }, defaultOptions: [ - { ignore: [], allowedPrefixes: [], ignoreTopLevelDescribe: false }, + { + ignore: [], + allowedPrefixes: [], + ignoreTopLevelDescribe: false, + ignoreTodos: false, + }, ], create( context, - [{ ignore = [], allowedPrefixes = [], ignoreTopLevelDescribe }], + [ + { + ignore = [], + allowedPrefixes = [], + ignoreTopLevelDescribe, + ignoreTodos, + }, + ], ) { const ignores = populateIgnores(ignore); let numberOfDescribeBlocks = 0; @@ -121,6 +139,14 @@ export default createRule< return; } + // Ignore *.todo test and/or test suites + if ( + ignoreTodos && + jestFnCall.members.some(s => getAccessorValue(s) === 'todo') + ) { + return; + } + const [firstArg] = node.arguments; const description = getStringValue(firstArg);