vitest/no-conditional-expect

Disallow expect inside if, catch and other code that only runs sometimes

An expect that only runs under a condition might not run at all. If the condition is false, or nothing is thrown, the test passes without checking anything.

In a test, the rule reports an expect inside an if, a switch, a catch block, a .catch() callback, a ? b : c, or an operand of &&, || or ??.

It also checks function declarations that a test uses. It doesn't look inside a function expression such as function () {}, even when that's the test callback. Arrow functions are checked.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"vitest/no-conditional-expect" = "error" # or "warn"

Examples#

Reported, because the test passes if JSON.parse stops throwing:

example.ts1 problem
import { expect, test } from "vitest";

test("rejects bad JSON", () => {
  try {
    JSON.parse("{");
  } catch (error) {
    expect(error).toBeInstanceOf(SyntaxError);
  }
});
example.ts1 problem
import { expect, test } from "vitest";
import { readFile } from "node:fs/promises";

test("rejects a missing file", async () => {
  await readFile("missing.txt").catch(error => {
    expect(error.code).toBe("ENOENT");
  });
});
example.ts1 problem
import { expect, test } from "vitest";

const users = [{ name: "Ada", admin: true }];

test("finds the admin", () => {
  const admin = users.find(user => user.admin);
  if (admin) {
    expect(admin.name).toBe("Ada");
  }
});
example.tsNo problems
import { expect, test } from "vitest";
import { readFile } from "node:fs/promises";

const users = [{ name: "Ada", admin: true }];

test("rejects bad JSON", () => {
  expect(() => JSON.parse("{")).toThrow(SyntaxError);
});

test("rejects a missing file", async () => {
  await expect(readFile("missing.txt")).rejects.toThrow("ENOENT");
});

test("finds the admin", () => {
  const admin = users.find(user => user.admin);
  expect(admin).toBeDefined();
  expect(admin?.name).toBe("Ada");
});