eslint-plugin-test-signal
eslint-plugin-test-signal reports tests that look green while proving too
little about behavior.
The first rule set focuses on common weak-test signals:
- tests whose only assertion is a snapshot;
- tests whose only assertion inspects mock call metadata;
- assertions whose subject is a static constant;
- broad existence assertions that do not verify expected shape or value;
- assertions that compare a value to itself;
- vacuous whole-value asymmetric assertions;
- length assertions that only prove length is non-negative;
- fixed real-time waits that make tests slow or flaky;
- synthetic Promise assertions that do not exercise code under test;
- string and numeric assertions with vacuous expected values;
- broad object key-count assertions that only prove non-emptiness;
- duplicate assertion chains in the same test;
- Promise assertions that are not awaited or returned;
- async tests that contain no assertion;
- suites that have no negative-path coverage signal.
Design scopeโ
The plugin uses syntax-level heuristics that work across Vitest, Jest-style
APIs, and @typescript-eslint/rule-tester suites. It intentionally avoids type
checker work because the targeted patterns are visible directly in the test AST.
Presetsโ
testSignal.configs.minimalenables the lowest-noise correctness rules.testSignal.configs.recommendedadds weak assertion signal detection, including snapshot-only, mock-call-only, constant-subject, and broad existence assertions.testSignal.configs["recommended-type-checked"]currently matchesrecommendedbecause no shipped rule requires parser services yet.testSignal.configs.strictadds negative-path coverage enforcement.testSignal.configs.allenables every stable rule.testSignal.configs.experimentalis reserved for future candidate rules and currently matchesall.
Rule referenceโ
| Rule | Purpose |
|---|---|
no-empty-async-tests | Flags async tests without assertions. |
require-awaited-async-assertions | Flags floating .resolves and .rejects assertions. |
no-snapshot-only-tests | Flags tests whose only assertions are snapshots. |
no-mock-call-only-tests | Flags tests whose only assertions inspect mock calls. |
no-constant-assertions | Flags assertions whose subject is a static constant. |
no-weak-existence-assertions | Flags broad existence assertions such as toBeDefined(). |
no-identical-expected-actual | Flags assertions that compare a value to itself. |
no-weak-asymmetric-assertions | Flags vacuous whole-value asymmetric assertions. |
no-tautological-length-assertions | Flags length assertions that only prove length is non-negative. |
no-fixed-delay-tests | Flags fixed real-time delays in executable tests. |
no-synthetic-promise-assertions | Flags .resolves and .rejects assertions against synthetic Promise values. |
no-vacuous-string-assertions | Flags string assertions with expected values that match anything. |
no-vacuous-numeric-assertions | Flags numeric bound assertions with infinite thresholds. |
no-broad-object-key-count-assertions | Flags object key-count assertions that only prove an object is non-empty. |
no-duplicate-assertions | Flags repeated identical assertion chains in the same test. |
require-negative-path | Flags test scopes without negative-path coverage signals. |