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-jestabout 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-orientedbabel.config.js, which adds plugins not installed in your extension. TypeScript files are handled directly byts-jestand never reach Babel. Do not modifybabel.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.tsfile is not needed.@rancher/shellalready provides the*.vuemodule declaration through its published types, which TypeScript picks up via the"shell"entry in thetypesarray 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
shallowMountovermount— 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