Skip to content

Using Vitest

Vitest is a modern JavaScript testing framework that integrates with the Vite bundler. It is recommended for developers that are already using Vite or Vitest on their project.

To get started with Vitest, install the relevant packages using your preferred package manager:

Terminal window
npm i -D vitest @types/node

Create a tsconfig.json file:

tsconfig.json
{
"compilerOptions": {
// enable latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"allowJs": true, // allow importing `.js` from `.ts`
"types": ["node", "vitest"],
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags
"useUnknownInCatchVariables": true,
"noPropertyAccessFromIndexSignature": true
},
"include": ["./tests/**/*.ts", "./global-setup.ts", "./types.d.ts"]
}

The PocketIC server needs to be started before running tests and stopped once they’re finished running. This can be done by creating a global-setup.ts file in your project’s root directory:

global-setup.ts
import type { TestProject } from 'vitest/node';
import { PocketIcServer } from '@dfinity/pic';
let pic: PocketIcServer | undefined;
export async function setup(project: TestProject): Promise<void> {
pic = await PocketIcServer.start();
const url = pic.getUrl();
project.provide('PIC_URL', url);
}
export async function teardown(): Promise<void> {
await pic?.stop();
}

To improve type-safety for project.provide('PIC_URL') and (later) inject('PIC_URL'), create a types.d.ts file:

types.d.ts
export declare module 'vitest' {
export interface ProvidedContext {
PIC_URL: string;
}
}

Create a vitest.config.ts file:

vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globalSetup: './global-setup.ts',
testTimeout: 30_000,
},
});

Then, add a test script to your package.json:

package.json
{
"scripts": {
"test": "vitest run"
}
}

Vitest tests are very similar to tests written with Jest or Jasmine, so they will feel very familiar to developers who have used these frameworks before.

The basic skeleton of all PicJS tests written with Vitest will look something like this:

tests/example.spec.ts
import { resolve } from 'node:path';
import { describe, beforeEach, afterEach, it, expect, inject } from 'vitest';
import { type Actor, PocketIc } from '@dfinity/pic';
// Import the declarations generated for your canister,
// see the Canister declarations guide
import { idlFactory, type _SERVICE } from './declarations/backend.did';
// Define the path to your canister's WASM file.
// icp-cli writes it to `.icp/cache/artifacts/<canister name>`.
const WASM_PATH = resolve(
__dirname,
'..',
'.icp',
'cache',
'artifacts',
'backend',
);
// The `describe` function is used to group tests together
// and is completely optional.
describe('backend', () => {
// Define variables to hold our PocketIC instance
// and an actor to interact with our canister.
let pic: PocketIc;
let actor: Actor<_SERVICE>;
// The `beforeEach` hook runs before each test.
//
// This can be replaced with a `beforeAll` hook to persist canister
// state between tests.
beforeEach(async () => {
// create a new PocketIC instance
pic = await PocketIc.create(inject('PIC_URL'));
// Setup the canister and actor
const fixture = await pic.setupCanister<_SERVICE>({
idlFactory,
wasm: WASM_PATH,
});
// Save the actor for use in tests
actor = fixture.actor;
});
// The `afterEach` hook runs after each test.
//
// This should be replaced with an `afterAll` hook if you use
// a `beforeAll` hook instead of a `beforeEach` hook.
afterEach(async () => {
// tear down the PocketIC instance
await pic.tearDown();
});
// The `it` function is used to define individual tests
it('should greet', async () => {
const response = await actor.greet('PicJS');
expect(response).toEqual('Hello, PicJS!');
});
});

You can check out the official Vitest documentation for more information writing tests.