no-only-tests
Disallow focused test invocations such as test.only(...).
Targeted pattern scope
This rule inspects complete call/member chains, resolves supported test-runner imports and aliases, and distinguishes their bindings from shadowing locals.
What this rule reports
The rule reports calls whose static member path starts with a configured test
block and contains a configured focus method. This includes middle-chain forms
such as test.only.each(...). It also reports direct focused functions such as
fit(...) and fdescribe(...).
Unlike the original plugin, this implementation checks actual calls. A binding
or object property merely named fit is not reported.
Why this rule exists
Focused tests silently exclude part of a suite and can let incomplete test runs reach continuous integration or a release branch.
❌ Incorrect
describe.only("focused suite", () => {});
test.concurrent.only("focused test", () => {});
test.only.each([1])("focused parameterized test", () => {});
fit("focused test", () => {});
✅ Correct
describe("suite", () => {});
test.skip("skipped test", () => {});
const fit = testFactory;
Static computed focus properties are reported without an automatic fix. Object
options such as { only: true } are not member-chain focus APIs and remain out
of scope.
The rule understands named, renamed, namespace, and applicable default imports
from @jest/globals, vitest, node:test, bun:test, @playwright/test,
mocha, ava, qunit, and tape. A local or parameter binding that shadows a
known global/import is ignored. Renaming an ordinary import to fit does not
turn it into a focused-test API.
Behavior and migration notes
type Options = [
{
block?: readonly string[];
focus?: readonly string[];
functions?: readonly string[];
fix?: boolean;
},
];
blockdefaults todescribe,it,context,test,bench,suite,QUnit,tape,fixture,serial,Feature,Scenario,Given,And,When, andThen. A trailing*enables prefix matching, sotest*matchestestResource.only(...).focusdefaults toonly.functionsdefaults tofitandfdescribe.fixdefaults tofalse. When enabled, the fixer removes a plain, non-optional.focussegment even when it occurs in the middle of a chain. Optional or computed chains are reported without a fix.
Example configuration:
{
block: ["test", "check*"],
focus: ["only", "focus"],
functions: ["fit", "fdescribe"],
fix: false,
}
ESLint flat config example
import etcMisc from "eslint-plugin-etc-misc";
export default [
{
plugins: { "etc-misc": etcMisc },
rules: { "etc-misc/no-only-tests": "error" },
},
];
When not to use it
Disable the rule when the test runner already provides an enforced CI guard and editor-time feedback is unnecessary, or when the configured block names are used by unrelated APIs.
Package documentation
Rule catalog ID: R050
Further reading
Upstream inspiration
This is a clean-room, typed modernization of
eslint-plugin-no-only-tests.
Additional resources
Adoption resources
- Start at warning level in CI, then move to error after cleanup.
- Use focused codemods/autofix batches per package or directory.