Skip to content

consistent-test-it: false positive on test.extend / it.extend #884

@gtbuchanan

Description

@gtbuchanan

Description

vitest/consistent-test-it reports a false positive when test.extend() or it.extend() is used to create a custom test function at module scope. The rule flags the .extend() call based on the identity of the original import (test vs it), but .extend() returns a new function that may be assigned to a different name for use in a different scope.

Reproduction

https://github.com/gtbuchanan/vitest-eslint-consistent-test-it-repro

git clone https://github.com/gtbuchanan/vitest-eslint-consistent-test-it-repro
cd vitest-eslint-consistent-test-it-repro
npm install
npx eslint .

Case 1: it-extend-to-it.test.ts

import { it as base, describe } from 'vitest';

const it = base.extend<{ fixture: string }>({
  fixture: async ({}, use) => {
    await use('hello');
  },
});

describe('example', () => {
  it('should not warn', ({ fixture, expect }) => {
    expect(fixture).toBe('hello');
  });
});

Warns: Prefer using test instead of it on the base.extend(...) line (module scope).

Expected: No warning — the extended function is named it and used correctly inside describe.

Case 2: it-extend-to-test.test.ts

import { describe, it } from 'vitest';

const test = it.extend<{ fixture: string }>({
  fixture: async ({}, use) => {
    await use('hello');
  },
});

describe('example', () => {
  test('should not warn', ({ fixture, expect }) => {
    expect(fixture).toBe('hello');
  });
});

Warns: Prefer using test instead of it on the it.extend(...) line (module scope).

Expected: No warning — the extended function is named test and the it.extend() call is just the factory, not a test invocation.

Root cause

The rule treats .extend() calls as if they were test invocations, applying the same scope-based naming rules (test at top level, it inside describe). But .extend() is a factory that returns a new function — the scope where .extend() is called is irrelevant; only the scope where the returned function is invoked matters.

Environment

  • @vitest/eslint-plugin: 1.6.12
  • eslint: 9.x
  • typescript-eslint: required to reproduce (the parser enables the plugin to resolve the import identity)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions