Skip to content

Commit bd82c7d

Browse files
authored
fix(require-test-timeout): treat imported bindings as explicit timeouts (#906)
resolveConstTimeout only walked Variable definitions, so an imported const used as a timeout argument resolved to undefined and the rule reported a missing timeout. Same-file consts were already accepted via #887/#889; imports were not. ImportBinding definitions cannot be resolved cross-file, so accept them opaquely: if a developer named the imported identifier in the timeout position, treat it as an explicit timeout and let the rule pass. Same behaviour as the existing handling for ancestor-scope const bindings. Tests added (positive + negative axes): - imported identifier as third-arg timeout (test + it) - imported identifier in { timeout } object property - imported identifier as { timeout } options object - default-imported binding - importing a binding without using it as a timeout still reports Closes #892
1 parent 28bc45f commit bd82c7d

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

src/rules/require-test-timeout.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
9292
return undefined
9393

9494
for (const def of variable.defs) {
95+
// Imported bindings: we cannot statically resolve a cross-file
96+
// initializer, but the developer named the imported identifier in
97+
// the timeout position. Treat it as an explicit timeout so the
98+
// rule does not flag the test.
99+
if (def.type === 'ImportBinding') return 0
100+
95101
if (def.type !== 'Variable') continue
96102

97103
// only accept `const` bindings

tests/require-test-timeout.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ ruleTester.run(RULE_NAME, rule, {
3636
// in-source unit tests
3737
'if (import.meta.vitest) { const opts = { timeout: 500 }; describe("outer", () => { it("repro: same-file opts object", opts, () => {}); }); }',
3838
'if (import.meta.vitest) { const T = 500; describe("outer", () => { describe("inner", () => { it("repro: same-file const timeout", () => {}, T); }); }); }',
39+
// imported const used as the timeout argument (#892)
40+
'import { TIMEOUT } from "./test-constants"; test("a", () => {}, TIMEOUT)',
41+
'import { TIMEOUT } from "./test-constants"; it("a", () => {}, TIMEOUT)',
42+
'import { TIMEOUT } from "./test-constants"; test("a", () => {}, { timeout: TIMEOUT })',
43+
'import { TIMEOUT } from "./test-constants"; test("a", { timeout: TIMEOUT }, () => {})',
44+
'import { OPTS } from "./test-constants"; test("a", OPTS, () => {})',
45+
'import T from "./test-constants"; test("a", () => {}, T)',
3946
],
4047
invalid: [
4148
{
@@ -135,5 +142,11 @@ ruleTester.run(RULE_NAME, rule, {
135142
code: 'test("a", () => {}, 1000, { timeout: -1 })',
136143
errors: [{ messageId: 'missingTimeout' }],
137144
},
145+
// importing a binding does not bypass the rule when the import is not in
146+
// the timeout position
147+
{
148+
code: 'import { TIMEOUT } from "./test-constants"; test("a", () => {})',
149+
errors: [{ messageId: 'missingTimeout' }],
150+
},
138151
],
139152
})

0 commit comments

Comments
 (0)