web-infra-dev / web-infra-dev/rslint
[Feature]: Lint Rstest support
- Dominant language
- Go
- Stars
- 459
- Forks
- 33
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 376
Description
## What problem does this feature solve?
Related discussion: https://github.com/web-infra-dev/rstest/issues/85#issuecomment-4435049030
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.
## Tracker
### Rstest-only Recommended (1/1)
| Rule Name | Will implement | Status | Level |
| --- | :---: | :---: | :---: |
| no-async-mock-factory | β
| Merged [#2100](https://github.com/web-infra-dev/rslint/pull/2100) | `error` |
### Jest Recommended (13/13)
| Rule Name | Will implement | Status | Level |
| --- | :---: | :---: | :---: |
| expect-expect | β
| Merged [#1614](https://github.com/web-infra-dev/rslint/pull/1614) | `warn` |
| no-alias-methods | β
| Merged [#1837](https://github.com/web-infra-dev/rslint/pull/1837) | Not recommended[^no-alias-methods] |
| no-conditional-expect | β
| Merged [#1548](https://github.com/web-infra-dev/rslint/pull/1548) | `error` |
| no-deprecated-functions | π« | π« | π« |
| no-commented-out-tests | β
| Merged [#1339](https://github.com/web-infra-dev/rslint/pull/1339) | `warn` |
| no-disabled-tests | β
| Merged [#1475](https://github.com/web-infra-dev/rslint/pull/1475) | `warn` |
| no-done-callback | π« | π« | π« |
| no-export | π« | π« | π« |
| no-focused-tests | β
| Merged [#1363](https://github.com/web-infra-dev/rslint/pull/1363) | `error` |
| no-identical-title | β
| Merged [#1473](https://github.com/web-infra-dev/rslint/pull/1473) | `error` |
| no-interpolation-in-snapshots | β
| Merged [#1604](https://github.com/web-infra-dev/rslint/pull/1604) | `error` |
| no-jasmine-globals | π« | π« | π« |
| no-mocks-import | β
| Merged [#1295](https://github.com/web-infra-dev/rslint/pull/1295) | `error` |
| no-standalone-expect | β
| Merged #1701 | `error` |
| no-test-prefixes | π« | π« | π« |
| valid-describe-callback | π« | π« | π« |
| valid-expect | β
| Merged [#1695](https://github.com/web-infra-dev/rslint/pull/1695) | `error` |
| valid-expect-in-promise | β
| Merged [#1696](https://github.com/web-infra-dev/rslint/pull/1696) | `error` |
| valid-title | β
| Merged [#1606](https://github.com/web-infra-dev/rslint/pull/1606) | `error` |
### Vitest Recommended not in Jest Recommended (3/3)
| Rule Name | Will implement | Status | Level |
| --- | :---: | :---: | :---: |
| no-import-node-test | β
| Merged [#1775](https://github.com/web-infra-dev/rslint/pull/1775) | `error` |
| prefer-called-exactly-once-with | β
| Merged [#1776](https://github.com/web-infra-dev/rslint/pull/1776) | `error` |
| require-local-test-context-for-concurrent-snapshots | β
| Merged [#1778](https://github.com/web-infra-dev/rslint/pull/1778) | `error` |
### Jest Not Recommended (28/45)
| Rule Name | Ready for Jest | Will implement | Status |
| --- | :---: | :---: | :---: |
| consistent-test-it | β | β
| Merged [#2110](https://github.com/web-infra-dev/rslint/pull/2110) |
| max-expects | β
| β
| Merged [#1838](https://github.com/web-infra-dev/rslint/pull/1838) |
| max-nested-describe | β
| β
| Merged [#2167](https://github.com/web-infra-dev/rslint/pull/2167) |
| no-conditional-in-test | β
| β
| Merged [#1839](https://github.com/web-infra-dev/rslint/pull/1839) |
| no-confusing-set-timeout | β
| π« | π« |
| no-duplicate-hooks | β
| β
| PR [#2195](https://github.com/web-infra-dev/rslint/pull/2195) |
| no-hooks | β
| β
| Merged [#1835](https://github.com/web-infra-dev/rslint/pull/1835) |
| no-large-snapshots | π« | π«[^no-large-snapshots] | π« |
| no-restricted-jest-methods | β
| π« | π« |
| no-restricted-matchers | β
| β
| Merged [#2086](https://github.com/web-infra-dev/rslint/pull/2086) |
| no-test-return-statement | β | β
| β |
| no-unneeded-async-expect-function | β
| β
| PR [#2194](https://github.com/web-infra-dev/rslint/pull/2194) |
| no-untyped-mock-factory | β | β
| β |
| padding-around-after-all-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-after-each-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-all | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-before-all-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-before-each-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-describe-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-expect-groups | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| padding-around-test-blocks | β
| β
| Merged [#2075](https://github.com/web-infra-dev/rslint/pull/2075) |
| prefer-to-be | β
| β
| Merged [#2115](https://github.com/web-infra-dev/rslint/pull/2115) |
| prefer-to-contain | β
| β
| Merged [#2127](https://github.com/web-infra-dev/rslint/pull/2127) |
| prefer-to-have-length | β
| β
| PR [#2196](https://github.com/web-infra-dev/rslint/pull/2196) |
| prefer-called-with | β
| β
| Merged [#2085](https://github.com/web-infra-dev/rslint/pull/2085) |
| prefer-comparison-matcher | β
| β
| Merged [#2121](https://github.com/web-infra-dev/rslint/pull/2121) |
| prefer-each | β
| β
| Merged [#1841](https://github.com/web-infra-dev/rslint/pull/1841) |
| prefer-ending-with-an-expect | β | β
| β |
| prefer-equality-matcher | β
| β
| Merged [#2091](https://github.com/web-infra-dev/rslint/pull/2091) |
| prefer-expect-assertions | β | β
| β |
| prefer-expect-resolves | β
| β
| β |
| prefer-hooks-in-order | β
| β
| Merged [#1836](https://github.com/web-infra-dev/rslint/pull/1836) |
| prefer-hooks-on-top | β
| β
| β |
| prefer-importing-jest-globals | β | π« | π« |
| prefer-jest-mocked | β
| π« | π« |
| prefer-lowercase-title | β | β
| β |
| prefer-mock-promise-shorthand | β | β
| β |
| prefer-mock-return-shorthand | β | β
| β |
| prefer-snapshot-hint | β | β
| β |
| prefer-spy-on | β
| β
| β |
| prefer-strict-equal | β
| β
| Merged [#2093](https://github.com/web-infra-dev/rslint/pull/2093) |
| prefer-to-have-been-called | β
| β
| Merged [#2160](https://github.com/web-infra-dev/rslint/pull/2160) |
| prefer-to-have-been-called-times | β
| β
| β |
| prefer-todo | β
| β
| Merged [#1840](https://github.com/web-infra-dev/rslint/pull/1840) |
| require-hook | β
| β
| β |
| require-to-throw-message | β
| β
| Merged [#2092](https://github.com/web-infra-dev/rslint/pull/2092) |
| require-top-level-describe | β
| β
| β |
| valid-mock-module-path | β | π« | π« |
| no-error-equal | β | π« | π« |
| no-unnecessary-assertion | β | β
| Merged [#2149](https://github.com/web-infra-dev/rslint/pull/2149) |
| unbound-method | β | β
| Merged [#2155](https://github.com/web-infra-dev/rslint/pull/2155) |
| valid-expect-with-promise | β | β
| Merged [#2151](https://github.com/web-infra-dev/rslint/pull/2151) |
### Vitest Not Recommended not in Jest (15/15)
| Rule Name | Will implement | Status |
| --- | :---: | :---: |
| consistent-each-for | β
| Merged [#1979](https://github.com/web-infra-dev/rslint/pull/1979) |
| consistent-test-filename | β
| Merged [#1978](https://github.com/web-infra-dev/rslint/pull/1978) |
| consistent-vitest-vi | π«[^vi-namespace] | π« |
| hoisted-apis-on-top | β
| Merged [#1929](https://github.com/web-infra-dev/rslint/pull/1929) |
| no-conditional-tests | β
| Merged [#1919](https://github.com/web-infra-dev/rslint/pull/1919) |
| no-importing-vitest-globals | π«[^vi-namespace] | π« |
| no-restricted-vi-methods | π«[^vi-namespace] | π« |
| prefer-called-once | β
| Merged [#1921](https://github.com/web-infra-dev/rslint/pull/1921) |
| prefer-called-times | β
| Merged [#1890](https://github.com/web-infra-dev/rslint/pull/1890) |
| prefer-describe-function-title | π« | π« |
| prefer-expect-type-of | β
| Merged [#1885](https://github.com/web-infra-dev/rslint/pull/1885) |
| prefer-import-in-mock | β
| Merged [#1930](https://github.com/web-infra-dev/rslint/pull/1930) |
| prefer-importing-vitest-globals | π«[^vi-namespace] | π« |
| prefer-strict-boolean-matchers | β
| Merged [#1972](https://github.com/web-infra-dev/rslint/pull/1972) |
| prefer-to-be-falsy | β
| Merged [#1972](https://github.com/web-infra-dev/rslint/pull/1972) |
| prefer-to-be-object | π« | π« |
| prefer-to-be-truthy | β
| Merged [#1972](https://github.com/web-infra-dev/rslint/pull/1972) |
| prefer-vi-mocked | π«[^vi-namespace] | π« |
| require-awaited-expect-poll | β
| Merged [#1920](https://github.com/web-infra-dev/rslint/pull/1920) |
| require-mock-type-parameters | β
| Merged [#1944](https://github.com/web-infra-dev/rslint/pull/1944) |
| require-test-timeout | β
| Merged [#1918](https://github.com/web-infra-dev/rslint/pull/1918) |
| warn-todo | β
| Merged [#1889](https://github.com/web-infra-dev/rslint/pull/1889) |
### Rstest-only Not Recommended (5/5)
| Rule Name | Will implement | Status |
| --- | :---: | :---: |
| consistent-rstest-namespace | β
| Merged [#1942](https://github.com/web-infra-dev/rslint/pull/1942) |
| no-importing-rstest-globals | β
| Merged [#2029](https://github.com/web-infra-dev/rslint/pull/2029) |
| no-restricted-rstest-methods | β
| Merged [#2027](https://github.com/web-infra-dev/rslint/pull/2027) |
| prefer-importing-rstest-globals | β
| Merged [#2029](https://github.com/web-infra-dev/rslint/pull/2029) |
| prefer-rs-mocked | β
| Merged [#2030](https://github.com/web-infra-dev/rslint/pull/2030) |
[^no-alias-methods]: Jest deprecated these aliases in Jest 26 and [removed them in Jest 30](https://jestjs.io/docs/upgrading-to-jest30#removal-of-alias-matcher-functions). Vitest still supports them and keeps [`no-alias-methods` outside its `recommended` config](https://github.com/vitest-dev/eslint-plugin-vitest/blob/22d672abafce8c036eb830edf753b0c20e303f7b/src/index.ts), so canonical naming is primarily an opt-in style preference there. Rstest follows Vitest because its `expect` implementation is based on `@vitest/expect`.
[^no-large-snapshots]: Rslint's input pipeline only supports JavaScript and TypeScript file extensions, so it cannot lint external `.snap` files as required by this rule.
[^vi-namespace]: These rules are all defined in terms of the `vi` object or the `vitest` module specifier, neither of which exists in Rstest β the equivalent utilities are exported as `rstest` / `rs` and are also reachable through `import.meta.rstest`. So they cannot be ported under the same name. Where the underlying idea still applies, it belongs to a separately named Rstest rule (for example `no-restricted-rstest-methods`, `prefer-rs-mocked`), not to a port of the Vitest rule.
Contributor guide
Assessment
This issue has not been assessed yet.