Skip to content


Created: 2023-06-24 15:35:54 -0700 Modified: 2023-12-15 13:35:50 -0800

  • pnpm add -D vitest
  • Add a script to package.json: "test": "vitest"
  • Make the “test” (or “tests”) directory. In it, throw in a file like basic.test.ts.
  • If you need environment variables, put them into an .env.test file. This is the kind of thing you should check in to your repo so that other people can run tests without having to copy and fill out an .env file.
  • pnpm test

Rather than have global variables in your test, consider using Test Context, which is based on Playwright’s test fixtures. In short, it lets you provide exactly what a test needs and nothing more. For example, consider this code that I wrote for testing my bot. I needed to create a spy on a particular method that depended on a context and then pass both things (the spy and the context) into the test method

// Type used by the test context below
interface ContextAndReplySpy {
context: BotCommandContext;
replySpy: MockInstance<[text: string], Promise<void>>;
// Test context
export const testWithReplySpy = test.extend<{
contextAndReplySpy: ContextAndReplySpy;
// Can't use an underscore here or you get a runtime error in the test.
// eslint-disable-next-line no-empty-pattern
contextAndReplySpy: async ({}, use) => {
const context = createMockContext();
const replySpy = vi
.spyOn(context, "reply")
.mockImplementation(async () => {});
await use({ context, replySpy });
// Test itself
"editing a command with no parameters returns a usage message",
async ({ contextAndReplySpy: { context, replySpy } }) => {
await bot.userEditCommand([], context);
  • Set a breakpoint
  • ⌘⇧P → Debug: JavaScript Debug Terminal
  • Type pnpm test
    • Note: if you only want to test a single test, change the test to be test.only(...) (note: this is a toggle in Toggler) and run the test with pnpm test ./src/test/foo.test.ts