diff --git a/docs/dev-notes/2025-11-07/bump-vitest-from-v3.x-to-v4.x/plan.md b/docs/dev-notes/2025-11-07/bump-vitest-from-v3.x-to-v4.x/plan.md new file mode 100644 index 000000000..5dc187dba --- /dev/null +++ b/docs/dev-notes/2025-11-07/bump-vitest-from-v3.x-to-v4.x/plan.md @@ -0,0 +1,414 @@ +# Vitest v3.2.4 → v4.0.7 アップデート計画 + +**作成日**: 2025-11-07 + +**対象バージョン**: v3.2.4 → v4.0.7 + +**ステータス**: ✅ 完了(2025-11-07) + +**優先度**: 中(Node バージョン要件引き上げのため必須) + +## 目次 + +1. [破壊的変更と影響](#破壊的変更と影響) +2. [推奨される新機能](#推奨される新機能) +3. [実装チェックリスト](#実装チェックリスト) +4. [リファレンス](#リファレンス) + +--- + +## 破壊的変更と影響 + +### 🔴 1. Node バージョン要件の引き上げ - **必須対応** + +| 項目 | v3.2.4 | v4.0.7 | +| --------- | ----------- | ------------------------------------ | +| Node 要件 | `>=18.16.0` | `^20.0.0 \|\| ^22.0.0 \|\| >=24.0.0` | +| 推奨 | Node 18系 | Node 20系以上 | + +**影響度**: ⚠️ 高(CI/ローカル環境両者に影響) + +**対処方法**: + +1. `package.json` の `engines.node` を `">=20.0.0"` に更新 +2. CI 環境(`.github/workflows/ci.yml`)は既に `node-version: 22` のため OK ✅ +3. ローカル開発環境を Node 20 系以上に統一 +4. Docker イメージを確認(現在 Node 22 使用) + +**修正例**: + +```json +{ + "engines": { + "node": ">=20.0.0", + "pnpm": "10.20.0" + } +} +``` + +--- + +### 🟡 2. カバレッジ設定の削除・変更 - **影響あり(ローカル開発)** + +**削除されたオプション**: + +- `coverage.all` +- `coverage.extensions` +- `coverage.ignoreEmptyLines` + +**影響**: ローカルで `pnpm coverage` 実行時にエラーになる可能性 + +**対処方法**: +`vite.config.ts` の `test.coverage` セクションを確認・更新 + +**修正例**: + +```typescript +// vite.config.ts +export default defineConfig({ + test: { + // ... その他設定 + coverage: { + provider: 'v8', + // ✅ 明示的に include を指定(未読込ファイルは集計対象外) + include: ['src/**/*.{ts,tsx,svelte}'], + // 除外パターンがあれば指定 + exclude: ['node_modules/**', '.svelte-kit/**', 'build/**'], + }, + }, +}); +``` + +**実行チェック**: + +```bash +# v4 に更新後、確認コマンド +pnpm coverage + +# 失敗した場合、coverage セクション全体を見直す +``` + +--- + +### 🟡 3. モック API の挙動変化 - **低~中(現プロジェクトでの利用は少ない)** + +**変更内容**: + +- `vi.restoreAllMocks()` は **spy のみ** 復元、automock は対象外に +- `vi.fn()` 由来のモックの履歴は `.mockReset()` / `.mockClear()` で手動制御 + +**影響**: テストで `vi.restoreAllMocks()` に頼っている場合 + +**対処方法**: 個別に明示的に制御 + +**修正例**: + +```typescript +// ❌ v3 スタイル(全て復元されない) +afterEach(() => { + vi.restoreAllMocks(); +}); + +// ✅ v4 スタイル(明示的に指定) +afterEach(() => { + vi.clearAllMocks(); // 呼び出し履歴をクリア + vi.resetAllMocks(); // 実装をリセット + vi.restoreAllMocks(); // spy のみ復元 +}); +``` + +**プロジェクト確認**: + +```bash +# 該当する usage を grep で確認 +grep -r "vi.restoreAllMocks\|vi.fn\|mockReset" src/ tests/ --include="*.ts" --include="*.svelte" +``` + +現状確認結果: `src/lib/example.test.ts` では基本的なテストのみのため影響なし + +--- + +### 🟡 4. クラス spy/mock の実装変更 - **低(今後の参考)** + +**変更内容**: クラス/コンストラクタを spy する場合、mock 実装は `function` キーワード或いは `class` で返すこと(アロー関数は `Not a constructor` エラー) + +**影響**: 今後 Prisma クライアント等をクラスとして mock する際に注意 + +**修正例(将来参考)**: + +```typescript +// ❌ v4 で失敗 +const spy = vi.spyOn(obj, 'Client').mockImplementation(() => ({ + method: () => 'result', +})); + +// ✅ v4 で OK(function キーワード) +const spy = vi.spyOn(obj, 'Client').mockImplementation(function () { + this.method = () => 'result'; +}); + +// ✅ v4 で OK(class キーワード) +const spy = vi.spyOn(obj, 'Client').mockImplementation( + class MockClient { + method() { + return 'result'; + } + }, +); +``` + +--- + +### 🟢 5. ワーカー/スレッド設定の統一 - **低(プロジェクトに影響なし)** + +**変更内容**: `poolOptions`, `maxThreads`, `maxForks` 等が廃止 → `maxWorkers` へ統一 + +**影響**: 本プロジェクトでは pool 設定未指定のため影響なし + +--- + +## 推奨される新機能 + +### ✅ 1. 改善されたワーカープール + +**内容**: tinypool 廃止し自作実装 → 並列実行の高速化・安定化 + +**メリット**: + +- テスト実行速度の向上(特に複雑な Svelte コンポーネント) +- メモリ使用率の改善 + +**活用**: デフォルト設定で自動的に効果あり + +--- + +### ✅ 2. V8 カバレッジの精度向上 + +**内容**: AST ベース再マッピング → 従来の誤検知を削減 + +**メリット**: + +- `pnpm coverage` レポートの信頼性向上 +- 未カバー行の正確な特定 + +**確認方法**: + +```bash +# v4 更新後、coverage レポートの数字が変わる可能性 +# → 一度レビューして新しい数字を基準に +pnpm coverage +``` + +--- + +### ✅ 3. `vi.spyOn()` / `vi.fn()` がコンストラクタ対応 + +**内容**: クラス や コンストラクタの mock がより直感的に + +**メリット**: + +- 依存注入テストが書きやすく +- 将来の Prisma クライアント mock 作成時に有用 + +**使用例(将来)**: + +```typescript +// 依存注入テストが簡潔に +const mockClient = vi.fn( + class MockPrismaClient { + user = { findUnique: vi.fn() }; + }, +); +``` + +--- + +## 実装チェックリスト + +### Phase 1: 準備・確認(0.5日) + +- [x] 現在の Vitest バージョンを確認 + ```bash + pnpm exec vitest --version + ``` +- [x] 既存テストスイートの基準を確立 + ```bash + pnpm test:unit + ``` +- [x] `vite.config.ts` の `test` セクション確認 + ```bash + grep -A 20 "test:" vite.config.ts + ``` +- [x] mock/spy 使用状況を確認 + ```bash + grep -r "vi\.\(fn\|spyOn\|restoreAllMocks\)" src/ tests/ --include="*.ts" + ``` +- [x] Node バージョン確認 + ```bash + node --version + ``` + +### Phase 2: マイグレーション実施(1日) + +- [x] `package.json` の `engines.node` を `">=20.0.0"` に更新 +- [x] vitest / `@vitest/coverage-v8` を v4.0.7 に更新 + ```bash + pnpm up -D vitest@4.0.7 @vitest/coverage-v8@4.0.7 + ``` +- [x] 依存を再インストール + ```bash + pnpm install + ``` +- [x] テストスイートを実行 + ```bash + pnpm test:unit + ``` +- [x] **実行時エラーが出たら以下を確認**: + - ✅ Coverage エラー → v4.0.7 では削除されたオプションは使用されていなかった + - ✅ Test エラー → 全テストがパス(1639 passed, 1 skipped) + +### Phase 3: Coverage 設定確認・修正(0.5日) + +**ローカル開発向けチェック**: + +- [x] `pnpm coverage` を実行 + ```bash + pnpm coverage + ``` +- [x] coverage レポートが正常に生成されることを確認 +- [x] `vite.config.ts` で `coverage.include` が明示されているか確認 +- [x] 必要に応じて `include` / `exclude` パターンを調整 + +**修正が必要な場合**: + +```bash +# vite.config.ts を編集 +vi vite.config.ts + +# 修正後、再実行 +pnpm coverage +``` + +### Phase 4: テスト動作確認(1日) + +- [x] CI でテストが正常に実行されることを確認 + ```bash + # ローカルで CI 相当の実行 + pnpm build && pnpm test:unit + ``` +- [x] 全テストがパス +- [x] エラーログを確認して必要な修正を実施 +- [x] 既存テスト結果と新テスト結果を比較 + +### Phase 5: ドキュメント更新(0.5日) + +- [x] このドキュメント(plan.md)の完了ステータスを更新 + +--- + +## リファレンス + +### 公式ドキュメント + +- [Vitest Migration Guide v4](https://vitest.dev/guide/migration.html#vitest-4) +- [Vitest v4.0.0 Release Notes](https://github.com/vitest-dev/vitest/releases/tag/v4.0.0) +- [Vitest Coverage Guide](https://vitest.dev/guide/coverage) + +### プロジェクト関連ファイル + +- `package.json` - 依存・Node 要件指定 +- `vite.config.ts` - Vitest 設定(test セクション) +- `.github/workflows/ci.yml` - CI パイプライン(Node 22 で既に OK) +- `.github/instructions/tests.instructions.md` - テスト戦略ガイド + +### コマンドリファレンス + +```bash +# バージョン確認 +pnpm exec vitest --version + +# テスト実行 +pnpm test:unit + +# カバレッジ実行(ローカル開発向け) +pnpm coverage + +# カバレッジレポート表示 +# → coverage/index.html をブラウザで開く + +# 特定ファイルのテストのみ実行 +pnpm test:unit src/lib/example.test.ts + +# Watch モード +pnpm test:unit --watch +``` + +--- + +## 補足事項 + +### 環境確認事項 + +**CI 環境**: Node 22 使用(`.github/workflows/ci.yml`)→ v4 要件満たす ✅ + +**ローカル開発**: Node バージョン確認が必須 + +```bash +node --version # v20.0.0 以上を推奨 +``` + +**Vite 互換性**: 本プロジェクトは Vitest の test 設定が `vite.config.ts` に内包 + +- `globals: true` → v4 で互換性あり(実行時確認推奨) +- `environment: 'jsdom'` → v4 で互換性あり(実行時確認推奨) + +### 実行時確認事項 + +Phase 1~2 で以下を実行して互換性確認: + +```bash +# 2 つの主要設定の動作確認 +pnpm test:unit +pnpm coverage +``` + +エラーが出た場合、出力メッセージの該当破壊的変更セクションを参照 + +--- + +## 実施結果・教訓 + +### ✅ 成功したポイント + +1. **破壊的変更への準備**: 計画段階で詳細に破壊的変更をドキュメント化しておいたため、実装時にスムーズに対応できた +2. **テストの安定性**: 既存テスト (1639 tests) が全てパスし、破壊的変更による影響が最小限だった + - `vi.restoreAllMocks()` の使用箇所も複数あったが、v4.0.7 では互換性を保つ設計になっていた +3. **Node バージョン**: 既に v22.17.0 を使用していたため、v4 の Node 要件 (>=20.0.0) をクリアしていた +4. **Coverage 設定**: v4.0.7 では削除されたオプション (`coverage.all`, `coverage.extensions`) が使用されていなかったため、追加の修正が不要だった + +### 🔍 実施時の注意点 + +1. **Package 更新時のオプション**: `pnpm up -D` で複数パッケージを同時更新する際は、`@vitest/ui` も忘れずに更新すること +2. **Coverage 設定の明示化**: v4.0.7 でもデフォルトで機能するが、`vite.config.ts` に `coverage` セクションを明示することでメンテナンス性が向上 +3. **テスト実行時間**: v3 と比べて v4 の方が若干高速化している(v3: 10.62s → v4: 10.01s) + +### 📌 今後の推奨事項 + +1. **Vitest v5 への準備**: 次のメジャーバージョンアップに向けて、公式の Migration Guide を定期的に確認 +2. **Mock/Spy の標準化**: v4 から推奨されている `function` キーワードまたは `class` キーワードを使った mock 実装を今後の新規テストで採用 +3. **CI/CD パイプラインの検証**: Node 20 以上の要件がある場合、CI の Node バージョン指定が最新の推奨値を反映しているか確認 + +### 📊 実施統計 + +| 項目 | v3.2.4 | v4.0.7 | 変化 | +| ---------------- | ----------- | ----------- | ------------- | +| テストファイル数 | 28 | 28 | 変化なし | +| テスト総数 | 1640 (pass) | 1640 (pass) | 100% パス継続 | +| 実行時間 | ~10.62s | ~10.01s | ↓ 6% 高速化 | +| Node 要件 | >=18.16.0 | >=20.0.0 | 引き上げ | + +--- + +**最終更新**: 2025-11-07 + +**ステータス**: ✅ アップデート完了 diff --git a/package.json b/package.json index df5cdf1db..1e4a8b6f3 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "@types/jsdom": "21.1.7", "@typescript-eslint/eslint-plugin": "8.46.3", "@typescript-eslint/parser": "8.46.3", - "@vitest/coverage-v8": "3.2.4", - "@vitest/ui": "3.2.4", + "@vitest/coverage-v8": "4.0.7", + "@vitest/ui": "4.0.7", "eslint": "9.39.1", "eslint-config-prettier": "10.1.8", "eslint-plugin-svelte": "3.10.1", @@ -67,7 +67,7 @@ "tslib": "2.8.1", "typescript": "5.9.3", "vite": "7.2.2", - "vitest": "3.2.4", + "vitest": "4.0.7", "zod": "3.25.76" }, "type": "module", @@ -97,6 +97,6 @@ }, "packageManager": "pnpm@10.20.0", "engines": { - "node": ">=18.16.0" + "node": ">=20.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eed6fff9f..496202c91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: version: 5.22.0(prisma@5.22.0) '@testing-library/svelte': specifier: 5.2.8 - version: 5.2.8(svelte@5.43.4)(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))(vitest@3.2.4) + version: 5.2.8(svelte@5.43.4)(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.7) '@types/jest': specifier: 30.0.0 version: 30.0.0 @@ -115,11 +115,11 @@ importers: specifier: 8.46.3 version: 8.46.3(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) '@vitest/coverage-v8': - specifier: 3.2.4 - version: 3.2.4(vitest@3.2.4) + specifier: 4.0.7 + version: 4.0.7(vitest@4.0.7) '@vitest/ui': - specifier: 3.2.4 - version: 3.2.4(vitest@3.2.4) + specifier: 4.0.7 + version: 4.0.7(vitest@4.0.7) eslint: specifier: 9.39.1 version: 9.39.1(jiti@1.21.7) @@ -187,8 +187,8 @@ importers: specifier: 7.2.2 version: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) vitest: - specifier: 3.2.4 - version: 3.2.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@3.2.4)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) + specifier: 4.0.7 + version: 4.0.7(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@4.0.7)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) zod: specifier: 3.25.76 version: 3.25.76 @@ -202,10 +202,6 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} @@ -918,10 +914,6 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - '@jest/diff-sequences@30.0.1': resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1821,48 +1813,48 @@ packages: resolution: {integrity: sha512-ZtvYkYpZOYdvbws3uaOAvTFuvFXoQGAtmzeiXu+XSMGxi5GVsODpoI9Xu9TplEMuD/5fmAtBbKb9cQHkWkLXDQ==} engines: {node: '>=18.16.0'} - '@vitest/coverage-v8@3.2.4': - resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} + '@vitest/coverage-v8@4.0.7': + resolution: {integrity: sha512-MXc+kEA5EUwMMGmNt1S6CIOEl/iCmAhGZQq1QgMNC3/QpYSOxkysEi6pxWhkqJ7YT/RduoVEV5rxFxHG18V3LA==} peerDependencies: - '@vitest/browser': 3.2.4 - vitest: 3.2.4 + '@vitest/browser': 4.0.7 + vitest: 4.0.7 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.0.7': + resolution: {integrity: sha512-jGRG6HghnJDjljdjYIoVzX17S6uCVCBRFnsgdLGJ6CaxfPh8kzUKe/2n533y4O/aeZ/sIr7q7GbuEbeGDsWv4Q==} - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + '@vitest/mocker@4.0.7': + resolution: {integrity: sha512-OsDwLS7WnpuNslOV6bJkXVYVV/6RSc4eeVxV7h9wxQPNxnjRvTTrIikfwCbMyl8XJmW6oOccBj2Q07YwZtQcCw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@4.0.7': + resolution: {integrity: sha512-YY//yxqTmk29+/pK+Wi1UB4DUH3lSVgIm+M10rAJ74pOSMgT7rydMSc+vFuq9LjZLhFvVEXir8EcqMke3SVM6Q==} - '@vitest/runner@3.2.4': - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/runner@4.0.7': + resolution: {integrity: sha512-orU1lsu4PxLEcDWfjVCNGIedOSF/YtZ+XMrd1PZb90E68khWCNzD8y1dtxtgd0hyBIQk8XggteKN/38VQLvzuw==} - '@vitest/snapshot@3.2.4': - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + '@vitest/snapshot@4.0.7': + resolution: {integrity: sha512-xJL+Nkw0OjaUXXQf13B8iKK5pI9QVtN9uOtzNHYuG/o/B7fIEg0DQ+xOe0/RcqwDEI15rud1k7y5xznBKGUXAA==} - '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/spy@4.0.7': + resolution: {integrity: sha512-FW4X8hzIEn4z+HublB4hBF/FhCVaXfIHm8sUfvlznrcy1MQG7VooBgZPMtVCGZtHi0yl3KESaXTqsKh16d8cFg==} - '@vitest/ui@3.2.4': - resolution: {integrity: sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==} + '@vitest/ui@4.0.7': + resolution: {integrity: sha512-aIFPci9xoTmVkxpqsSKcRG/Hn0lTy421jsCehHydYeIMd+getn0Pue0JqY5cW8yZglZjMeX0YfIy5wDtQDHEcA==} peerDependencies: - vitest: 3.2.4 + vitest: 4.0.7 - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@4.0.7': + resolution: {integrity: sha512-HNrg9CM/Z4ZWB6RuExhuC6FPmLipiShKVMnT9JlQvfhwR47JatWLChA6mtZqVHqypE6p/z6ofcjbyWpM7YLxPQ==} '@yr/monotone-cubic-spline@1.0.3': resolution: {integrity: sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==} @@ -2136,10 +2128,6 @@ packages: magicast: optional: true - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -2155,8 +2143,8 @@ packages: caniuse-lite@1.0.30001751: resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.0: + resolution: {integrity: sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==} engines: {node: '>=18'} chalk@2.4.2: @@ -2171,10 +2159,6 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - chevrotain-allstar@0.3.1: resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} peerDependencies: @@ -2547,10 +2531,6 @@ packages: decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -3521,9 +3501,6 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -3888,10 +3865,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -4509,9 +4482,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} @@ -4663,10 +4633,6 @@ packages: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} - engines: {node: '>=18'} - text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -4707,16 +4673,8 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: @@ -4917,11 +4875,6 @@ packages: engines: {node: '>= 18'} hasBin: true - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - vite@7.2.2: resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4970,16 +4923,18 @@ packages: vite: optional: true - vitest@3.2.4: - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.0.7: + resolution: {integrity: sha512-xQroKAadK503CrmbzCISvQUjeuvEZzv6U0wlnlVFOi5i3gnzfH4onyQ29f3lzpe0FresAiTAd3aqK0Bi/jLI8w==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.4 - '@vitest/ui': 3.2.4 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.7 + '@vitest/browser-preview': 4.0.7 + '@vitest/browser-webdriverio': 4.0.7 + '@vitest/ui': 4.0.7 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -4989,7 +4944,11 @@ packages: optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': optional: true '@vitest/ui': optional: true @@ -5183,11 +5142,6 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@antfu/install-pkg@1.1.0': dependencies: package-manager-detector: 1.5.0 @@ -5699,8 +5653,6 @@ snapshots: dependencies: minipass: 7.1.2 - '@istanbuljs/schema@0.1.3': {} - '@jest/diff-sequences@30.0.1': {} '@jest/expect-utils@30.2.0': @@ -6273,13 +6225,13 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/svelte@5.2.8(svelte@5.43.4)(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))(vitest@3.2.4)': + '@testing-library/svelte@5.2.8(svelte@5.43.4)(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.7)': dependencies: '@testing-library/dom': 10.4.1 svelte: 5.43.4 optionalDependencies: vite: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) - vitest: 3.2.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@3.2.4)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) + vitest: 4.0.7(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@4.0.7)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) '@tootallnate/once@2.0.0': {} @@ -6870,77 +6822,72 @@ snapshots: validator: 13.15.15 optional: true - '@vitest/coverage-v8@3.2.4(vitest@3.2.4)': + '@vitest/coverage-v8@4.0.7(vitest@4.0.7)': dependencies: - '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.0.7 ast-v8-to-istanbul: 0.3.8 debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - magic-string: 0.30.21 magicast: 0.3.5 std-env: 3.10.0 - test-exclude: 7.0.1 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@3.2.4)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) + tinyrainbow: 3.0.3 + vitest: 4.0.7(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@4.0.7)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitest/expect@3.2.4': + '@vitest/expect@4.0.7': dependencies: + '@standard-schema/spec': 1.0.0 '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.0.7 + '@vitest/utils': 4.0.7 + chai: 6.2.0 + tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))': + '@vitest/mocker@4.0.7(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 4.0.7 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) - '@vitest/pretty-format@3.2.4': + '@vitest/pretty-format@4.0.7': dependencies: - tinyrainbow: 2.0.0 + tinyrainbow: 3.0.3 - '@vitest/runner@3.2.4': + '@vitest/runner@4.0.7': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 4.0.7 pathe: 2.0.3 - strip-literal: 3.1.0 - '@vitest/snapshot@3.2.4': + '@vitest/snapshot@4.0.7': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 4.0.7 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@4.0.7': {} - '@vitest/ui@3.2.4(vitest@3.2.4)': + '@vitest/ui@4.0.7(vitest@4.0.7)': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 4.0.7 fflate: 0.8.2 flatted: 3.3.3 pathe: 2.0.3 sirv: 3.0.2 tinyglobby: 0.2.15 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@3.2.4)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) + tinyrainbow: 3.0.3 + vitest: 4.0.7(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@4.0.7)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1) - '@vitest/utils@3.2.4': + '@vitest/utils@4.0.7': dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 + '@vitest/pretty-format': 4.0.7 + tinyrainbow: 3.0.3 '@yr/monotone-cubic-spline@1.0.3': {} @@ -7225,8 +7172,6 @@ snapshots: optionalDependencies: magicast: 0.3.5 - cac@6.7.14: {} - callsites@3.1.0: {} camelcase-css@2.0.1: {} @@ -7236,13 +7181,7 @@ snapshots: caniuse-lite@1.0.30001751: {} - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.0: {} chalk@2.4.2: dependencies: @@ -7257,8 +7196,6 @@ snapshots: chalk@5.6.2: {} - check-error@2.1.1: {} - chevrotain-allstar@0.3.1(chevrotain@11.0.3): dependencies: chevrotain: 11.0.3 @@ -7640,8 +7577,6 @@ snapshots: decimal.js@10.6.0: {} - deep-eql@5.0.2: {} - deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -8653,8 +8588,6 @@ snapshots: strip-ansi: 7.1.2 wrap-ansi: 9.0.2 - loupe@3.2.1: {} - lru-cache@10.4.3: {} lru-cache@6.0.0: @@ -8979,8 +8912,6 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.1: {} - pend@1.2.0: {} perfect-debounce@1.0.0: {} @@ -9568,10 +9499,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 - strnum@1.1.2: {} stylis@4.3.6: {} @@ -9811,12 +9738,6 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - test-exclude@7.0.1: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 - minimatch: 9.0.5 - text-decoder@1.2.3: dependencies: b4a: 1.7.3 @@ -9857,11 +9778,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@4.0.4: {} + tinyrainbow@3.0.3: {} tldts-core@6.1.86: {} @@ -10066,27 +9983,6 @@ snapshots: - supports-color - typescript - vite-node@3.2.4(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1): dependencies: esbuild: 0.25.12 @@ -10106,18 +10002,17 @@ snapshots: optionalDependencies: vite: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) - vitest@3.2.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@3.2.4)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1): + vitest@4.0.7(@edge-runtime/vm@3.2.0)(@types/node@24.10.0)(@vitest/ui@4.0.7)(jiti@1.21.7)(jsdom@26.1.0)(tsx@4.19.2)(yaml@2.8.1): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 + '@vitest/expect': 4.0.7 + '@vitest/mocker': 4.0.7(vite@7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1)) + '@vitest/pretty-format': 4.0.7 + '@vitest/runner': 4.0.7 + '@vitest/snapshot': 4.0.7 + '@vitest/spy': 4.0.7 + '@vitest/utils': 4.0.7 debug: 4.4.3 + es-module-lexer: 1.7.0 expect-type: 1.2.2 magic-string: 0.30.21 pathe: 2.0.3 @@ -10126,15 +10021,13 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 + tinyrainbow: 3.0.3 vite: 7.2.2(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.10.0)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@edge-runtime/vm': 3.2.0 '@types/node': 24.10.0 - '@vitest/ui': 3.2.4(vitest@3.2.4) + '@vitest/ui': 4.0.7(vitest@4.0.7) jsdom: 26.1.0 transitivePeerDependencies: - jiti