Compare commits

...

1 Commits

Author SHA1 Message Date
Olivier Floch
9ced4c7d37 test(web-core): set up Vitest unit test runner
Single happy-dom `unit` project mirroring @xen-orchestra/web, with `test`, `test:ui` and `type-check` scripts. web and lite exclude web-core test files from their type-check, and the shared npmignore keeps TS tests and Vitest config out of published packages.
2026-10-13 14:57:08 +02:00
13 changed files with 147 additions and 13 deletions

View File

@@ -1,7 +1,7 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "./src/**/*", "./src/**/*.vue", "../web-core/lib/**/*", "../web-core/lib/**/*.vue"],
"exclude": ["./src/**/__tests__/*"],
"exclude": ["./src/**/__tests__/*", "../web-core/lib/**/*.unit.test.ts", "../web-core/lib/**/*.unit.spec.ts"],
"compilerOptions": {
"composite": true,
"noEmit": true,

View File

@@ -1,4 +1,4 @@
{
"extends": "./tsconfig.app.json",
"exclude": ["src/stories"]
"exclude": ["src/stories", "../web-core/lib/**/*.unit.test.ts", "../web-core/lib/**/*.unit.spec.ts"]
}

View File

@@ -7,6 +7,7 @@
- [Stores](./stores.md)
- [Subscribable stores](./subscribable-stores.md)
- [Overlays (modals & drawers)](./overlays.md)
- [Tests](./tests.md)
# Composables

View File

@@ -0,0 +1,34 @@
# Tests
Testing uses **Vitest 4** with a single `unit` project (see `vitest.config.ts`): every test matches `**/*.unit.test.ts` and runs on `happy-dom`, CLI-only, no browser. Conventions follow the [XO 6 test docs](../../web/docs/tests.md).
| Path | Role |
| ---------------------- | ------------------------------------------------------------------------- |
| `vitest.config.ts` | Runner config: `vue` + `vue-i18n` plugins, `@core` alias, `globals: true` |
| `test/setup.ts` | Global setup: auto-unmounts every mounted wrapper after each test |
| `tsconfig.vitest.json` | Type-checks test files with the Vitest globals |
| `tsconfig.app.json` | Type-checks the library, test files excluded |
Test files sit next to the code they test, as `lib/**/*.unit.test.ts`. Shared test infrastructure lives in `test/`, outside `lib/`. The shared `scripts/npmignore` keeps all of it out of the published package.
`@xen-orchestra/web` and `@xen-orchestra/lite` type-check `web-core/lib` as part of their own sources: their tsconfigs exclude the web-core test files, which they would otherwise check without the Vitest globals.
`test.alias` maps `placement.js` to its ESM build: the package only declares a `module` entry, which the Node-style resolution used by Vitest ignores.
## Running tests
```sh
cd @xen-orchestra/web-core
# Run the whole suite once
yarn test
# Watch mode
yarn vitest
# Browse and re-run tests from the Vitest UI
yarn test:ui
# Type-check the library and the tests
yarn type-check
```

View File

@@ -43,13 +43,24 @@
"vue-router": "^5.0.0"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^6.0.3",
"@tsconfig/node18": "^18.2.4",
"@types/lodash-es": "^4.17.12",
"@types/node": "^18.19.80",
"@types/novnc__novnc": "~1.5.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vitest/ui": "^4.1.9",
"@vue/test-utils": "^2.4.11",
"@vue/tsconfig": "^0.9.0",
"happy-dom": "^20.0.0",
"pinia": "^3.0.1",
"typescript": "^6.0.0",
"vite": "^8.0.0",
"vitest": "^4.1.9",
"vue": "~3.5.13",
"vue-i18n": "^11.1.2",
"vue-router": "5.0.6"
"vue-router": "5.0.6",
"vue-tsc": "^3.0.0"
},
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/web-core",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
@@ -67,6 +78,9 @@
"node": ">=18"
},
"scripts": {
"postversion": "npm publish --access public"
"postversion": "npm publish --access public",
"test": "vitest run",
"test:ui": "vitest --ui",
"type-check": "vue-tsc --build --force"
}
}

View File

@@ -0,0 +1,3 @@
import { enableAutoUnmount } from '@vue/test-utils'
enableAutoUnmount(afterEach)

View File

@@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "./lib/**/*", "./lib/**/*.vue"],
"exclude": ["./lib/**/*.unit.test.ts", "./lib/**/*.unit.spec.ts"],
"compilerOptions": {
"composite": true,
"noEmit": true,
"paths": {
"@core/*": ["./lib/*"]
}
}
}

View File

@@ -1,11 +1,14 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "./lib/**/*", "./lib/**/*.vue"],
"exclude": ["./lib/**/__tests__/*"],
"compilerOptions": {
"noEmit": true,
"paths": {
"@core/*": ["./lib/*"]
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.vitest.json"
}
}
]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "@tsconfig/node18/tsconfig.json",
"include": ["vitest.config.*"],
"compilerOptions": {
"composite": true,
"noEmit": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.app.json",
"include": ["env.d.ts", "./lib/**/*", "./lib/**/*.vue", "./test/**/*"],
"exclude": [],
"compilerOptions": {
"types": ["vitest/globals"]
}
}

View File

@@ -0,0 +1,39 @@
import { fileURLToPath, URL } from 'node:url'
import vueI18n from '@intlify/unplugin-vue-i18n/vite'
import vue from '@vitejs/plugin-vue'
import type { PluginOption } from 'vite'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [
vue(),
vueI18n({
include: fileURLToPath(new URL('./lib/locales/**', import.meta.url)),
}),
] as PluginOption[],
resolve: {
alias: {
'@core': fileURLToPath(new URL('./lib', import.meta.url)),
},
},
test: {
globals: true,
// Lint-staged runs this suite on every web-core change, so it must not fail while no test exists yet
passWithNoTests: true,
setupFiles: ['./test/setup.ts'],
alias: {
// `placement.js` only declares a `module` entry, which the Node-style resolution used by Vitest ignores
'placement.js': fileURLToPath(new URL('../../node_modules/placement.js/dist/index.es.js', import.meta.url)),
},
projects: [
{
extends: true,
test: {
include: ['**/*.unit.{test,spec}.ts'],
name: 'unit',
environment: 'happy-dom',
},
},
],
},
})

View File

@@ -8,7 +8,13 @@
"../web-core/lib/**/*",
"../web-core/lib/**/*.vue"
],
"exclude": ["./src/**/*.unit.test.ts", "./src/**/*.unit.spec.ts", "./src/test/setup.ts"],
"exclude": [
"./src/**/*.unit.test.ts",
"./src/**/*.unit.spec.ts",
"./src/test/setup.ts",
"../web-core/lib/**/*.unit.test.ts",
"../web-core/lib/**/*.unit.spec.ts"
],
"compilerOptions": {
"composite": true,
"noEmit": true,

View File

@@ -28,6 +28,9 @@ example.{,c,m}js.map
*.spec.{,c,m}js.map
*.test.{,c,m}js
*.test.{,c,m}js.map
*.spec.{,c,m}ts
*.test.{,c,m}ts
/vitest.config.*
__snapshots__/