Skip to content

[Feature]: Lint Rstest support #935

Description

@elecmonkey

What problem does this feature solve?

Related discussion: web-infra-dev/rstest#85 (comment)

Most of the rules for jest may also be applicable to Rstest. In a typical repo which using Rstest - web-infra-dev/rsbuild - around 2/3 of the eslint-plugin-jest rules can pass directly.

So I have a proposal: we could share an abstraction layer under both Jest and Rstest lint rules in our repo. Consider Rslint is now porting rules from eslint-plugin-jest actively, we can extract some utils outside first. once the jest rules become stable, we can start building Rstest rules on top of the existing things.

@fansenze @eryue0220

What does the proposed API of configuration look like?

some idea: maybe we could go on use in jest's rules in internal/plugins/jest/rules/*/*.go:

utils.ParseJestFnCall(node, ctx)

internally, that can become a wrapper for the new layer:

testfw.ParseFnCall(node, ctx, testfw.JestProfile)

jest/* rules for Rstest analyzing [17/19]

jest/no-focused-tests

✅ Highly compatible with Rstest.

Rstest supports .only on both test and describe, so the same risk exists: a developer may commit a focused test and accidentally make CI run only part of the suite.

import { describe, expect, test } from '@rstest/core';

describe.only('math utils', () => {
  test('squares a number', () => {
    expect(square(2)).toBe(4);
  });
});

This should be reported. The Rstest rule can share the same core logic as the Jest rule while using an Rstest-specific parser profile. Unlike Jest, Rstest does not need to handle fit or fdescribe, since those aliases are not part of the Rstest API.

jest/no-mocks-import

✅ Almost fully compatible with Rstest.

Rstest uses the same __mocks__ convention, so the detection logic can be reused unchanged. Only the diagnostic should recommend rs.mock instead of jest.mock.

jest/no-commented-out-tests

✅ Almost fully compatible with Rstest.

The core heuristic for detecting commented-out test, it, and describe calls remains valid. The Rstest version should remove support for Jest's unsupported f/x prefixes.

jest/no-identical-title

✅ Highly compatible with Rstest.

Duplicate static titles cause the same reporting ambiguity in Rstest, and the scope-based comparison logic can be reused. The Rstest version additionally needs to recognize .for as a parameterized test form.

jest/expect-expect

✅ Highly compatible with Rstest.

Rstest tests have the same risk of passing without executing any assertion. The core detection logic can be reused, but the Rstest version must recognize TestContext.expect, expect.soft/poll/element, Chai assert, and tests created through .for or test.extend.

jest/no-alias-methods

✅ Highly compatible with Rstest.

Rstest supports the same matcher aliases, and each alias is behaviorally equivalent to its canonical matcher. The mapping and autofix logic can be reused to enforce consistent and more descriptive assertion names without changing test behavior.

jest/no-conditional-expect

✅ Highly compatible with Rstest.

Conditional assertions have the same risk in Rstest: a branch may not execute, allowing the test to pass without running the assertion. The core control-flow logic can be reused, but the Rstest version must recognize Rstest test modifiers, test.for, and TestContext.expect.

jest/no-disabled-tests

✅ Highly compatible with Rstest.

Rstest has the same need to prevent committed .skip calls and tests without callbacks, which otherwise pass without executing any test logic. The core rule behavior can be reused while continuing to allow explicit .todo tests; Rstest simply does not need Jest's x prefixes or pending().

jest/no-export

✅ Highly compatible with Rstest.

Exporting from a test file creates the same risk in Rstest: importing shared helpers from that file may execute and register its tests again. The export detection logic can be reused unchanged, while the Rstest version only needs an Rstest-specific parser to identify files containing test or describe blocks.

jest/no-standalone-expect

✅ Highly compatible with Rstest.

Assertions executed outside test blocks have the same risk in Rstest: they run during test collection and are not associated with an individual test. The core scope logic can be reused with support for Rstest-specific test and expect APIs, while preserving the original rule behavior for hooks and helper functions.

jest/valid-expect

✅ Compatible with Rstest, with framework-specific extensions.

The matcher-chain and async-assertion checks remain valuable. However, Rstest allows expect(actual, message?) and additionally provides expect.soft, expect.poll, expect.element, and TestContext.expect, each requiring dedicated parsing and async handling.

jest/valid-title

✅ Highly compatible with Rstest.

The general title checks can be reused. The Rstest version must also support .for, remove Jest's f/x prefix handling, and use Rstest's printf specifiers: %O and %c are valid, while Jest's %p is not supported.

jest/no-deprecated-functions

❌ No need for Rstest.

jest/no-jasmine-globals

❌ No need for Rstest.

jest/no-done-callback

❌ No need for Rstest.

Rstest callbacks receive TestContext or SuiteContext, not Jest-style done. Porting this rule would report valid callback parameters, while invalid done() usage is already covered by TypeScript.

jest/no-test-prefixes

❌ No need for Rstest.

Rstest does not expose Jest's fit, fdescribe, xit, xtest, or xdescribe aliases. These names are already rejected by TypeScript and are only relevant during migration from Jest.

jest/valid-describe-callback

❌ No need for Rstest.

Its constraints conflict with Rstest, which supports optional and async callbacks, options overloads, and describe.for. The remaining call-shape validation is already covered by Rstest's TypeScript types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Enhancement.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions