vitest/valid-expect-in-promise
Require a promise chain that contains expect to be awaited or returned from the test
A callback passed to .then(), .catch() or .finally() runs later. If the test doesn't await or return the promise, Vitest marks the test as passed before the expect in the callback runs, and a failed assertion doesn't fail the test.
Configure#
Off by default. To turn it on:
bunfig.toml
[lint.rules]
"vitest/valid-expect-in-promise" = "error" # or "warn"Examples#
example.ts1 problem
import { expect, test } from "vitest";
test("loads the user", () => {
loadUser(1).then((user) => {Expect in a promise chain must be awaited or returned
expect(user.name).toBe("Ada");
});
});A promise kept in a variable must be awaited or returned too:
example.ts1 problem
import { expect, test } from "vitest";
test("loads the user", () => {
const check = loadUser(1).then((user) => {Expect in a promise chain must be awaited or returned
expect(user.name).toBe("Ada");
});
});Code after the test's return never runs:
example.ts1 problem
import { expect, test } from "vitest";
test("loads both users", () => {
return loadUser(1).then((user) => {
expect(user.name).toBe("Ada");
});
loadUser(2).then((user) => {Expect in a promise chain is unreachable after a return statement
expect(user.name).toBe("Grace");
});
});example.tsNo problems
import { expect, test } from "vitest";
test("loads the user", () => {
return loadUser(1).then((user) => {
expect(user.name).toBe("Ada");
});
});
test("loads the admin", async () => {
await loadUser(2).then((user) => {
expect(user.role).toBe("admin");
});
});
test("loads the guest", async () => {
const user = await loadUser(3);
expect(user.role).toBe("guest");
});You can await several promises together:
example.tsNo problems
import { expect, test } from "vitest";
test("loads both users", async () => {
const first = loadUser(1).then((user) => {
expect(user.name).toBe("Ada");
});
const second = loadUser(2).then((user) => {
expect(user.name).toBe("Grace");
});
await Promise.all([first, second]);
});A test with a parameter isn't checked. This test takes the test context, so the rule misses the promise that nobody waits for:
example.tsNo problems
import { test } from "vitest";
test("loads the user", ({ expect }) => {
loadUser(1).then((user) => {
expect(user.name).toBe("Ada");
});
});