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.
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-jestrules 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-jestactively, 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:internally, that can become a wrapper for the new layer:
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.
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
fitorfdescribe, 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 recommendrs.mockinstead ofjest.mock.jest/no-commented-out-tests
✅ Almost fully compatible with Rstest.
The core heuristic for detecting commented-out
test,it, anddescribecalls remains valid. The Rstest version should remove support for Jest's unsupportedf/xprefixes.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
.foras 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, Chaiassert, and tests created through.forortest.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, andTestContext.expect.jest/no-disabled-tests
✅ Highly compatible with Rstest.
Rstest has the same need to prevent committed
.skipcalls and tests without callbacks, which otherwise pass without executing any test logic. The core rule behavior can be reused while continuing to allow explicit.todotests; Rstest simply does not need Jest'sxprefixes orpending().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 providesexpect.soft,expect.poll,expect.element, andTestContext.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'sf/xprefix handling, and use Rstest's printf specifiers:%Oand%care valid, while Jest's%pis 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
TestContextorSuiteContext, not Jest-styledone. Porting this rule would report valid callback parameters, while invaliddone()usage is already covered by TypeScript.jest/no-test-prefixes
❌ No need for Rstest.
Rstest does not expose Jest's
fit,fdescribe,xit,xtest, orxdescribealiases. 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.