Skip to main content
Version: v3

Unit Testing

Extensions use Jest for unit tests. The development app generated by npm init does not include test infrastructure by default — the steps below set it up.

Setup

1. Install test dependencies

From the root of your development app:

yarn add --dev \
jest jest-environment-jsdom \
ts-jest babel-jest \
@vue/vue3-jest @vue/test-utils \
@babel/core @babel/preset-env \
@types/jest

Note: You may see a peer dependency warning from @vue/vue3-jest about expecting Jest 29.x. This is harmless — the package works correctly with Jest 30.

2. Create jest.config.js

Create jest.config.js at the root of your development app:

// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
testEnvironmentOptions: { customExportConditions: ['node', 'node-addons'] },
watchman: false,
moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
modulePaths: ['<rootDir>'],
moduleNameMapper: {
'^~/(.*)$': '<rootDir>/$1',
'^@/(.*)$': '<rootDir>/$1',
'@shell/(.*)': '<rootDir>/node_modules/@rancher/shell/$1',
'@components/(.*)': '<rootDir>/node_modules/@rancher/shell/rancher-components/$1',
'\\.(jpe?g|png|gif|webp|svg|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$': '<rootDir>/utils/svgTransform.js',
},
modulePathIgnorePatterns: ['<rootDir>/cypress/'],
transform: {
'^.+\\.vue$': '@vue/vue3-jest',
'^.+\\.tsx?$': 'ts-jest',
'^.+\\.jsx?$': ['babel-jest', {
configFile: false,
presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
}],
'^.+\\.svg$': '<rootDir>/utils/svgTransform.js'
},
transformIgnorePatterns: ['/node_modules/(?!@rancher/shell).+\\.js$'],
testMatch: ['**/__tests__/**/*.test.ts']
};

Note on configFile: false: This prevents Jest from inheriting Rancher's webpack-oriented babel.config.js, which adds plugins not installed in your extension. TypeScript files are handled directly by ts-jest and never reach Babel. Do not modify babel.config.js — it is required for the webpack dev server and build.

3. Create utils/svgTransform.js

Create utils/svgTransform.js at the root of your development app. This stubs out SVG imports so they don't break Jest:

// utils/svgTransform.js
module.exports = {
process() { return { code: 'module.exports = {};' }; },
getCacheKey() { return 'svgTransform'; },
};

4. Add test scripts to package.json

"scripts": {
"test": "jest",
"test:ci": "NODE_OPTIONS=--max_old_space_size=8192 jest --silent"
}

5. Add @types/jest to tsconfig.json

In the root tsconfig.json, add "@types/jest" to the types array:

"types": ["@types/node", "cypress", "rancher", "shell", "@types/jest"]

Note: A shims-vue.d.ts file is not needed. @rancher/shell already provides the *.vue module declaration through its published types, which TypeScript picks up via the "shell" entry in the types array above.


Writing Tests

Tests live in __tests__ directories placed next to the code they test. Files must be named *.test.ts.

pkg/
my-app/
utils/
greet.ts
__tests__/
greet.test.ts ← utility function test
components/
MyComponent.vue
__tests__/
MyComponent.test.ts ← Vue component test

Utility function test

import { describe, it, expect } from '@jest/globals';
import { greet } from '../greet';

describe('greet', () => {
it('returns a greeting with the name', () => {
expect(greet('World')).toStrictEqual('Hello, World!');
});

it('handles empty string', () => {
expect(greet('')).toStrictEqual('Hello, !');
});
});

Vue component test

import { shallowMount } from '@vue/test-utils';
import MyComponent from '../MyComponent.vue';

describe('MyComponent', () => {
it('renders the title prop', () => {
const wrapper = shallowMount(MyComponent, {
props: { title: 'Hello' }
});

expect(wrapper.find('h1').text()).toStrictEqual('Hello');
});
});

Tip: Prefer shallowMount over mount — it stubs child components, isolating the component under test and avoiding unresolved dependency errors from shell or other child components.


Running Tests

# Run all tests
yarn test

# CI mode (higher memory limit, silent output)
yarn test:ci

# Run a single file
yarn test:ci pkg/my-app/utils/__tests__/greet.test.ts

GitHub Actions Workflow

Create .github/workflows/unit-tests.yml to run tests automatically on every pull request:

name: Unit Tests

on:
push:
branches:
- main
pull_request:

jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Run unit tests
run: yarn test:ci