Skip to content

You are reading the documentation for version 0.6, which is not the latest release.

Testing (Vitest / Jest)

$debug is installed by the plugin's runtime (browser injection, SSR virtual import, dev-server global). A unit-test runner runs none of that, so source that calls $debug(...), especially at module-eval time, throws ReferenceError: $debug is not defined. A no-op stub fixes it: it behaves exactly like a stripped production build.

Vitest — automatic (nothing to add)

If mtDebug() is in the Vite config Vitest reads (the usual case: Vitest merges your vite.config), the plugin detects the test run and registers the stub for you as a first setupFiles entry. Just run your tests: $debug is defined. Opt out with mtDebug({ testStub: false }).

Note

This is not a Vite or Vitest plugin hook you add: the plugin you already have contributes a setup file (a global installed before your tests import anything). Auto-registration covers the default $debug; for a custom globalName, set testStub: false and register the stub yourself.

Explicit — Jest, or a Vitest config without the plugin

Add the shipped setup module to setupFiles, first, before any other setup that imports your source:

ts
// vitest.config.ts (or jest config)
export default defineConfig({
  test: {
    setupFiles: ["@mars-tech/vite-debug-plugin/testing"],
  },
});

Importing the module installs a no-op $debug (callable, plus ns, enable, disable, setLevel, assert, time, timeEnd, count, group and groupEnd).

In 0.6 this stub, like the one installMtDebugStub installs, has no setPrefixFilter: source that calls it throws a TypeError under test. Use the manual stub below, which adds it.

Custom globalName, or asserting calls

Use the programmatic form from your own setup file:

ts
// tests/setup.ts   (setupFiles: ["./tests/setup.ts"])
import { installMtDebugStub } from "@mars-tech/vite-debug-plugin/testing";
import { vi } from "vitest";

installMtDebugStub({ globalName: "$log", impl: vi.fn() }); // spy on every call

installMtDebugStub accepts two options: globalName (the identifier to install, default "$debug"; match the plugin's globalName) and impl (the function invoked for every call, a no-op by default; pass vi.fn() or jest.fn() to assert calls). It returns the installed stub.

Manual stub (no dependency)

If you'd rather not import the package in tests, hand-write it. It must be the first setupFile and contain no imports. ES modules evaluate a file's imports before its body, so a stub placed after imports (or in a file that transitively imports $debug-using modules) runs too late and still throws:

js
// tests/debug-stub.js   (setupFiles: ["./tests/debug-stub.js", ...])  — NO imports
const noop = () => {};
globalThis.$debug = Object.assign(noop, {
  ns: () => noop,
  enable: noop,
  disable: noop,
  setLevel: noop,
  setPrefixFilter: noop,
  assert: noop,
  time: noop,
  timeEnd: noop,
  count: noop,
  group: noop,
  groupEnd: noop,
});

Seeing $debug output in tests

The stub is a no-op: it stops tests throwing, but swallows output. To actually see logs during a test run, from your test files and from components or library code exercised by the test, flip one flag:

ts
// vite.config.ts
mtDebug({ testLog: true });

Under Vitest the plugin swaps the no-op for a real, formatted console $debug. It is config-aware: it uses your resolved prefix, globalName and levels (handed to the test setup over the environment), so the prefix, global name and level set match your dev output. Nothing else to add. testLog requires testStub to stay on.

Test output in 0.6

In 0.6 the test logger does not apply redact / redactDefaults, uses the default level labels and colors, and prints no source location or stack. Values masked in dev appear unmasked in test output and CI logs.

Filter with the same environment variables as the runtime filter: MT_DEBUG=cart* MT_DEBUG_LEVEL=info vitest.

A line logged by a library built with libraryPrefix keeps its prefix, so app and library logs stay distinguishable under test:

text
XYZ Info [A/UsesB] - UsesB mounted        ← your app (prefix XYZ)
ABC Info [cart/action] - cart.add(…)      ← library B (prefix ABC)

Stub the library (vi.mock('…')) and its lines simply stop appearing: only your app's logs remain.

Tip

Vitest groups console output under each test by default. Pass --disableConsoleIntercept (or --reporter=verbose) to see the lines inline.

Calling $debug in test files needs no runtime change: the stub or logger defines it. For your editor and CI, TypeScript picks up the global from the /// <reference types="@mars-tech/vite-debug-plugin/client" /> you already added (as long as your test files sit in a tsconfig that includes it), and the shipped /eslint flat config declares $debug so no-undef stays quiet (see Usage).