Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

vitest/prefer-called-exactly-once-with

Require toHaveBeenCalledExactlyOnceWith() over separate call count and argument checks

toHaveBeenCalledOnce() followed by toHaveBeenCalledWith(...) on the same mock takes two assertions to say one thing: the mock ran once, with these arguments. toHaveBeenCalledExactlyOnceWith(...) says it in one line.

The pair is reported when both assertions are in the same block, in either order. Assertions with .not are ignored.

--fix-dangerously replaces the pair with one toHaveBeenCalledExactlyOnceWith(...) call. --fix doesn't.

Configure

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"vitest/prefer-called-exactly-once-with" = "error" # or "warn"

Examples

Reported:

import { expect, test, vi } from "vitest";

test("saves the draft", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledOnce();
  expect(save).toHaveBeenCalledWith("draft");
});

Not reported:

import { expect, test, vi } from "vitest";

test("saves the draft", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledExactlyOnceWith("draft");
});

A mockClear(), mockReset(), or mockRestore() on the mock between the two assertions means they're about different calls, so they aren't a pair:

import { expect, test, vi } from "vitest";

test("saves again after an edit", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledOnce();

  save.mockClear();
  autosave("edited", save);
  expect(save).toHaveBeenCalledWith("edited");
});