From 781b27a456c8b523304b2c7cadb5e4f902bd5e68 Mon Sep 17 00:00:00 2001 From: hainenber Date: Thu, 6 Nov 2025 22:55:42 +0700 Subject: [PATCH 1/5] feat(rule): allow ignoring test.todo Jest functions for `prefer-lowercase-title` rule Signed-off-by: hainenber --- docs/rules/prefer-lowercase-title.md | 15 ++++++ .../__tests__/prefer-lowercase-title.test.ts | 54 +++++++++++++++++++ src/rules/prefer-lowercase-title.ts | 31 ++++++++++- 3 files changed, 98 insertions(+), 2 deletions(-) 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..2bae9ed46 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -646,3 +646,57 @@ 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 }], + }, + ], + 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: [{ ignore: [TestCaseName.it] }], + errors: [ + { + messageId: 'unexpectedCase', + data: { method: TestCaseName.test }, + column: 6, + line: 1, + }, + ], + }, + ], +}); diff --git a/src/rules/prefer-lowercase-title.ts b/src/rules/prefer-lowercase-title.ts index 96a2f97aa..12cd8bc42 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,15 @@ export default createRule< return; } + // Ignore *.todo test and/or test suites + if ( + ignoreTodos && + (jestFnCall.name.startsWith('x') || + jestFnCall.members.some(s => getAccessorValue(s) === 'todo')) + ) { + return; + } + const [firstArg] = node.arguments; const description = getStringValue(firstArg); From 2e7c6bc1daae195f91e01f83f05a5c3555075035 Mon Sep 17 00:00:00 2001 From: hainenber Date: Thu, 6 Nov 2025 22:57:09 +0700 Subject: [PATCH 2/5] fix: remove wrong conditionals Signed-off-by: hainenber --- src/rules/prefer-lowercase-title.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rules/prefer-lowercase-title.ts b/src/rules/prefer-lowercase-title.ts index 12cd8bc42..177f595a9 100644 --- a/src/rules/prefer-lowercase-title.ts +++ b/src/rules/prefer-lowercase-title.ts @@ -142,8 +142,7 @@ export default createRule< // Ignore *.todo test and/or test suites if ( ignoreTodos && - (jestFnCall.name.startsWith('x') || - jestFnCall.members.some(s => getAccessorValue(s) === 'todo')) + jestFnCall.members.some(s => getAccessorValue(s) === 'todo') ) { return; } From 39aed81b780eca6e361a1db87a5a8cffbfa10ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Tr=E1=BB=8Dng=20H=E1=BA=A3i?= <41283691+hainenber@users.noreply.github.com> Date: Mon, 10 Nov 2025 20:55:33 +0700 Subject: [PATCH 3/5] Apply suggestion from @G-Rath Co-authored-by: Gareth Jones <3151613+G-Rath@users.noreply.github.com> --- src/rules/__tests__/prefer-lowercase-title.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/__tests__/prefer-lowercase-title.test.ts b/src/rules/__tests__/prefer-lowercase-title.test.ts index 2bae9ed46..ac63d4540 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -688,7 +688,7 @@ ruleTester.run('prefer-lowercase-title with ignoreTodos', rule, { { code: "test('Foo', function () {})", output: "test('foo', function () {})", - options: [{ ignore: [TestCaseName.it] }], + options: [{ ignoreTodos: true }], errors: [ { messageId: 'unexpectedCase', From 1b4ac2ad32ea453cc895deef25d5c51fae34e557 Mon Sep 17 00:00:00 2001 From: hainenber Date: Mon, 10 Nov 2025 21:05:14 +0700 Subject: [PATCH 4/5] chore: add tests to cover more invalid cases Signed-off-by: hainenber --- .../__tests__/prefer-lowercase-title.test.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/rules/__tests__/prefer-lowercase-title.test.ts b/src/rules/__tests__/prefer-lowercase-title.test.ts index ac63d4540..400a9d0d3 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -698,5 +698,31 @@ ruleTester.run('prefer-lowercase-title with ignoreTodos', rule, { }, ], }, + { + 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, + }, + ], + }, ], }); From e6560cdfb65c56c31f88e93207f1d05b1b0a615b Mon Sep 17 00:00:00 2001 From: Gareth Jones <3151613+G-Rath@users.noreply.github.com> Date: Tue, 11 Nov 2025 07:39:43 +1300 Subject: [PATCH 5/5] test: add a few more cases --- src/rules/__tests__/prefer-lowercase-title.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rules/__tests__/prefer-lowercase-title.test.ts b/src/rules/__tests__/prefer-lowercase-title.test.ts index 400a9d0d3..9bfbb4247 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -657,6 +657,18 @@ ruleTester.run('prefer-lowercase-title with ignoreTodos', rule, { 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: [ {