Skip to content

Commit e3def88

Browse files
authored
Migrate to vitest (#152)
* Set up Vitest workspace tooling Replace Jest-specific package scripts, resolver config, and lint integration with a Vitest workspace setup. Refresh the lockfile and package metadata so the repo resolves source imports through Vitest/Vite instead of the old Jest ESM workaround. * Migrate workspace tests to Vitest Update the test suite to use Vitest imports and async patterns, add the core test setup needed to shield jsdom tests from Node 25's broken global localStorage, and keep the typed-array normalization fix that the migrated Utils tests now exercise for BigInt views. * Clean up repo tooling for Vitest Update repo instructions, editor recommendations, and devcontainer defaults so local tooling points at Vitest instead of the removed Jest workflow. * Fix CI prerelease package publishing The build workflow published branch prerelease packages without an explicit dist-tag and used overly broad publish gating, causing push builds to fail and making CI package tags unsafe. * Specify bash shell for CI workflow steps Explicitly set the shell to bash for build steps that utilize bash-specific syntax, such as parameter expansion, to ensure consistent behavior across different runner environments.
1 parent f9c8483 commit e3def88

37 files changed

+3558
-6974
lines changed

.claude/agents/engineer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Modified files: [list from Step 2]
146146
Run these checks:
147147
148148
1. `npm run build` (builds all packages in dependency order via tsc + esbuild)
149-
2. `npm test` (runs Jest tests across all packages)
149+
2. `npm test` (runs Vitest tests across all packages)
150150
3. `npm run lint` (ESLint + Prettier check)
151151
152152
For single-package changes, you may scope:

.claude/agents/pr-reviewer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Run the full build and test suite:
6767
# Build all packages (tsc + esbuild, respects dependency order)
6868
npm run build
6969

70-
# Run all tests (Jest across all packages)
70+
# Run all tests (Vitest across all packages)
7171
npm test
7272

7373
# Lint check (ESLint + Prettier)

.devcontainer/devcontainer.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22
"name": "Exceptionless.JavaScript",
33
"image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:latest",
44
"extensions": [
5-
"andys8.jest-snippets",
65
"dbaeumer.vscode-eslint",
76
"editorconfig.editorconfig",
87
"esbenp.prettier-vscode",
9-
"firsttris.vscode-jest-runner",
10-
"hbenl.vscode-test-explorer",
118
"juancasanova.awesometypescriptproblemmatcher",
129
"ryanluker.vscode-coverage-gutters",
13-
"streetsidesoftware.code-spell-checker"
10+
"streetsidesoftware.code-spell-checker",
11+
"vitest.explorer"
1412
],
1513
"forwardPorts": [3000],
16-
"postCreateCommand": "npm install"
14+
"postCreateCommand": "npm ci"
1715
}

.github/workflows/build.yml

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,20 @@ jobs:
2323
with:
2424
fetch-depth: 0
2525
- name: Build Reason
26-
run: "echo ref: ${{github.ref}} event: ${{github.event_name}}"
26+
shell: bash
27+
run: |
28+
branch=${GITHUB_REF##*/}.
29+
if [[ "$branch" = "main." ]]; then
30+
branch=""
31+
elif [[ "$branch" = "master." ]]; then
32+
branch=""
33+
elif [[ "${GITHUB_REF}" = refs/tags* ]]; then
34+
branch=""
35+
elif [[ "${GITHUB_REF}" = refs/pull* ]]; then
36+
branch=""
37+
fi
38+
echo "GIT_BRANCH_SUFFIX=$branch" >> $GITHUB_ENV
39+
echo "ref: $GITHUB_REF event: $GITHUB_EVENT_NAME branch_suffix: $branch"
2740
- name: Setup Node.js environment
2841
uses: actions/setup-node@v6
2942
with:
@@ -37,18 +50,29 @@ jobs:
3750
- name: Setup .NET SDK for MinVer
3851
uses: actions/setup-dotnet@v5
3952
with:
40-
dotnet-version: "8.0.x"
41-
- name: Set Min Version
42-
uses: Stelzi79/action-minver@3.0.1
43-
id: version
44-
with:
45-
minimum-major-minor: 3.0
46-
tag-prefix: v
53+
dotnet-version: "10.0.x"
4754
- name: Build Version
55+
id: version
56+
shell: bash
4857
run: |
58+
dotnet tool install --global minver-cli --version 7.0.0
59+
version=$(minver --tag-prefix v --default-pre-release-identifiers "preview.${GIT_BRANCH_SUFFIX}0" --minimum-major-minor 3.0)
60+
61+
# If on a non-main branch, insert branch name before the height (last numeric segment)
62+
if [ -n "$GIT_BRANCH_SUFFIX" ]; then
63+
branch_name="${GIT_BRANCH_SUFFIX%.}"
64+
if [[ "$version" != *"$branch_name"* ]]; then
65+
version=$(echo "$version" | sed -E "s/\.([0-9]+)$/.${GIT_BRANCH_SUFFIX}\1/")
66+
fi
67+
fi
68+
69+
echo "version=$version" >> $GITHUB_OUTPUT
70+
echo "Version: $version"
71+
echo "### Version: $version" >> $GITHUB_STEP_SUMMARY
72+
4973
npm install --global replace-in-files-cli
50-
replace-in-files --string="3.0.0-dev" --replacement=${{steps.version.outputs.version}} packages/core/src/configuration/Configuration.ts
51-
replace-in-files --string="3.0.0-dev" --replacement=${{steps.version.outputs.version}} **/package*.json
74+
replace-in-files --string="3.0.0-dev" --replacement=$version packages/core/src/configuration/Configuration.ts
75+
replace-in-files --string="3.0.0-dev" --replacement=$version **/package*.json
5276
npm ci
5377
- name: Build
5478
run: npm run build
@@ -62,14 +86,19 @@ jobs:
6286
env:
6387
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
6488
- name: Setup GitHub CI Node.js environment
65-
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest'
89+
if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/heads/') && matrix.os == 'ubuntu-latest' && contains(steps.version.outputs.version, '-')
6690
uses: actions/setup-node@v6
6791
with:
6892
node-version: ${{ matrix.node_version }}
6993
registry-url: "https://npm.pkg.github.com"
7094
scope: "@exceptionless"
7195
- name: Push GitHub CI Packages
72-
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest'
73-
run: npm publish --workspaces --access public
96+
if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/heads/') && matrix.os == 'ubuntu-latest' && contains(steps.version.outputs.version, '-')
97+
shell: bash
98+
run: |
99+
TAG_BRANCH="${GIT_BRANCH_SUFFIX%.}"
100+
TAG_BRANCH="${TAG_BRANCH:-main}"
101+
TAG_BRANCH="${TAG_BRANCH//\//-}"
102+
npm publish --workspaces --access public --tag "ci-${TAG_BRANCH}" || true
74103
env:
75104
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

.vscode/extensions.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
{
22
"recommendations": [
3-
"andys8.jest-snippets",
43
"davidanson.vscode-markdownlint",
54
"dbaeumer.vscode-eslint",
65
"editorconfig.editorconfig",
76
"esbenp.prettier-vscode",
8-
"firsttris.vscode-jest-runner",
9-
"hbenl.vscode-test-explorer",
107
"juancasanova.awesometypescriptproblemmatcher",
118
"ryanluker.vscode-coverage-gutters",
12-
"streetsidesoftware.code-spell-checker"
9+
"streetsidesoftware.code-spell-checker",
10+
"vitest.explorer"
1311
]
1412
}

.vscode/launch.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,27 @@
1414
"name": "Test",
1515
"request": "launch",
1616
"type": "node",
17-
"program": "${workspaceFolder}/node_modules/.bin/jest",
18-
"args": ["--runInBand"],
17+
"program": "${workspaceFolder}/node_modules/.bin/vitest",
18+
"args": ["--run"],
1919
"console": "integratedTerminal",
2020
"internalConsoleOptions": "neverOpen",
2121
"disableOptimisticBPs": true,
2222
"windows": {
23-
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
23+
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs"
2424
},
2525
"cwd": "${workspaceRoot}"
2626
},
2727
{
2828
"name": "Test Current File",
2929
"request": "launch",
3030
"type": "node",
31-
"program": "${workspaceFolder}/node_modules/.bin/jest",
32-
"args": ["${fileBasenameNoExtension}"],
31+
"program": "${workspaceFolder}/node_modules/.bin/vitest",
32+
"args": ["--run", "${fileBasenameNoExtension}"],
3333
"console": "integratedTerminal",
3434
"internalConsoleOptions": "neverOpen",
3535
"disableOptimisticBPs": true,
3636
"windows": {
37-
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
37+
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs"
3838
},
3939
"cwd": "${workspaceRoot}"
4040
}

.vscode/settings.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,5 @@
3636
"webcompat"
3737
],
3838
"eslint.validate": ["javascript", "typescript"],
39-
"deno.enable": false,
40-
"jest.jestCommandLine": "npm test --"
39+
"deno.enable": false
4140
}

AGENTS.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,10 @@ Before marking work complete, verify:
262262

263263
### Framework
264264

265-
- **Jest** with **ts-jest** preset
266-
- **`@jest/globals`** for imports (`describe`, `test`, `expect`)
265+
- **Vitest** as the test runner
266+
- **`vitest`** for imports (`describe`, `test`, `expect`, `beforeEach`, `afterEach`)
267267
- **jsdom** test environment for browser packages, **node** for the node package
268-
- **jest-ts-webcompat-resolver** for ESM import resolution
268+
- **vitest.config.ts** at root defines test projects for each package
269269

270270
### Test Structure
271271

@@ -288,8 +288,7 @@ packages/core/test/
288288
Follow the Arrange-Act-Assert pattern:
289289

290290
```typescript
291-
import { describe, test } from "@jest/globals";
292-
import { expect } from "expect";
291+
import { describe, test, expect } from "vitest";
293292

294293
import { ExceptionlessClient } from "../src/ExceptionlessClient.js";
295294

@@ -330,7 +329,7 @@ npm test --workspace=packages/browser
330329
npm run test:watch --workspace=packages/core
331330

332331
# Run tests matching a pattern
333-
npx jest --testPathPattern="ExceptionlessClient"
332+
npx vitest --run --testNamePattern="ExceptionlessClient"
334333
```
335334

336335
### Test Principles (FIRST)

eslint.config.mjs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import eslint from "@eslint/js";
22
import { defineConfig } from "eslint/config";
33
import eslintConfigPrettier from "eslint-config-prettier";
4-
import jest from "eslint-plugin-jest";
4+
import vitest from "@vitest/eslint-plugin";
55
import tseslint from "typescript-eslint";
66

77
export default defineConfig(
8-
{
9-
ignores: ["**/dist/", "**/node_modules/", ".agents/", "example/", "jest-resolver.cjs"]
10-
},
8+
{ ignores: ["**/dist/", "**/node_modules/", ".agents/", "example/"] },
119
eslint.configs.recommended,
1210
{
1311
extends: tseslint.configs.recommendedTypeChecked,
@@ -36,12 +34,12 @@ export default defineConfig(
3634
eslintConfigPrettier,
3735
{
3836
files: ["**/test/**/*.ts"],
39-
extends: [jest.configs["flat/recommended"]],
37+
plugins: vitest.configs.recommended.plugins,
4038
rules: {
41-
"jest/valid-title": "off",
42-
"jest/valid-describe-callback": "off",
43-
"jest/no-export": "off",
44-
"jest/no-done-callback": "warn"
39+
...vitest.configs.recommended.rules,
40+
"vitest/valid-title": "off",
41+
"vitest/valid-describe-callback": "off",
42+
"vitest/no-done-callback": "warn"
4543
}
4644
}
4745
);

example/react/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
},
1010
"eslintConfig": {
1111
"extends": [
12-
"react-app",
13-
"react-app/jest"
12+
"react-app"
1413
]
1514
},
1615
"browserslist": {
@@ -26,7 +25,6 @@
2625
]
2726
},
2827
"devDependencies": {
29-
"@testing-library/jest-dom": "^6.9.1",
3028
"@testing-library/react": "^16.3.2",
3129
"@testing-library/user-event": "^14.6.1",
3230
"@vitejs/plugin-react": "^6.0.1",

0 commit comments

Comments
 (0)