From 73bcbcc26ab1f4cceb3b552caf544fba13fb916a Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sat, 26 Sep 2026 15:31:36 +0500 Subject: [PATCH] test: add coverage --- .gitignore | 1 + AGENTS.md | 3 +- docs/README.md | 6 +- docs/plan-codebase-quality.md | 30 +++++++- docs/quality-gates.md | 20 ++++- docs/testing-strategy.md | 19 +++++ package.json | 2 +- web/package.json | 2 + web/pnpm-lock.yaml | 136 +++++++++++++++++++++++++++++++++- web/vitest.config.ts | 24 ++++++ 10 files changed, 232 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 48436db..09d2743 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ refs/public/placeholder-logo.png refs/public/placeholder.svg web/audit/cdp-audit*.txt css-lint.txt +web/coverage # Локальные планы с приватной информацией (выбранное имя домена) — не коммитить docs/plan-domain.local.md diff --git a/AGENTS.md b/AGENTS.md index 89a9a38..1fd6d68 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,8 @@ корне: `pnpm build`, `pnpm dev` (это `pnpm --dir web ...`). Не использовать npm. - Сборка: `pnpm --dir web build`, проверка типов: `pnpm --dir web check`, тесты: - `pnpm --dir web test` (Vitest), тесты lint-правил: + `pnpm --dir web test` (Vitest), тесты с coverage-гейтом: + `pnpm --dir web test:coverage`, тесты lint-правил: `pnpm --dir web test:rules`, e2e: `pnpm --dir web test:e2e` (Playwright, `web/e2e/`, свой webServer на `pnpm build` + `scripts/serve-static.mjs`, порт 4173). diff --git a/docs/README.md b/docs/README.md index 16d81a1..a68cdfe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -51,9 +51,9 @@ только если темы нет в существующем документе; иначе обновляется источник истины. -## Текущий baseline Q6f.3 +## Текущий baseline Q6f.4 -На момент фиксации Q6f.3: +На момент фиксации Q6f.4: - production registry содержит 122 инструмента; - `pnpm --dir web check` проходит без ошибок и предупреждений; @@ -61,6 +61,8 @@ - `pnpm --dir web test:rules` — 4 test files / 74 tests; - `pnpm --dir web lint:all` — 0 errors и 0 i18n warnings; остаются 4 unused design tokens от token audit; +- coverage `src/lib` — statements 91.77%, branches 83.3%, functions 74.31%, + lines 92.53% при порогах 90 / 82 / 72 / 91; - `pnpm verify` проходит; - `pnpm --dir web test:e2e` — 276 тестов в четырёх проектах: 276 passed, 0 skipped, 0 failed. Отказ декодера битого PNG зафиксирован per-engine в diff --git a/docs/plan-codebase-quality.md b/docs/plan-codebase-quality.md index cb9a44d..878109a 100644 --- a/docs/plan-codebase-quality.md +++ b/docs/plan-codebase-quality.md @@ -331,11 +331,33 @@ Firefox и WebKit для browser-critical спецификаций и mobile Chr - Локальный прогон: 276 passed, 0 skipped, 0 failed. Visual snapshots и coverage thresholds не добавлялись — это Q6f.4. -#### Q6f.4. Оставшиеся направления +#### Q6f.4. Coverage thresholds -- visual snapshots для kit/критичных экранов; -- coverage thresholds для `web/src/lib/`; -- при необходимости отдельное решение по DOM-тестам `SchemaToolView`/controls. +**Статус:** выполнен для чистой логики. Vitest считает покрытие только по +`src/lib`, с явным списком исключений, и `pnpm verify` падает при падении ниже +порога. + +- `web/vitest.config.ts`: provider `v8`, `reporter: text-summary`, пороги + statements 90, branches 82, functions 72, lines 91. +- Пороги поставлены на 1.5–2.5 п.п. ниже измеренного baseline (91.77 / 83.3 / + 74.31 / 92.53), поэтому gate ловит регрессию, а не текущий долг. +- Scope — логика, которую node-Vitest вообще может исполнить. Исключены + браузерные модули `core/domText.ts` и `core/io.ts` (canvas, + `createImageBitmap`), data-модули `i18n/en.ts`, `i18n/ru.ts`, `tool-icons.ts`, + rune-файлы `*.svelte.ts`, entry worker-а и type-only `components/define.ts`. + Причина каждого исключения зафиксирована в конфиге и в + `docs/testing-strategy.md`. +- `registry/*` (47–81% statements, 25–47% functions) в scope остаётся: это + обычная непокрытая логика, а не ограничение окружения. Покрывается e2e-smoke + Q6e, но unit-порог её не скрывает. +- `verify` теперь выполняет `test:coverage` вместо `test`: набор тестов тот же, + двойного прогона нет. +- Порог functions самый слабый (74.31% против 91.77%): добавление инструмента с + непокрытым `run` быстрее всего опускает именно его. Это ожидаемо, порог держит + запас. +- DOM-тесты `SchemaToolView`/controls и visual snapshots не начаты: браузерные + модули исключены сознательно, а baselines snapshots платформенные и должны + рождаться на Linux. Не применять один одинаковый smoke-сценарий к image-, text-, generator- и file-result-инструментам. diff --git a/docs/quality-gates.md b/docs/quality-gates.md index 644ef6a..107fcfe 100644 --- a/docs/quality-gates.md +++ b/docs/quality-gates.md @@ -14,7 +14,8 @@ pnpm verify `verify` выполняет последовательно: 1. `pnpm --dir web check` — SvelteKit sync и `svelte-check`. -2. `pnpm --dir web test` — полный Vitest-набор. +2. `pnpm --dir web test:coverage` — полный Vitest-набор вместе с + coverage-гейтом. 3. `pnpm --dir web test:rules` — отдельный быстрый прогон тестов ESLint-правил. 4. `pnpm --dir web lint:all` — ESLint, Stylelint и token audit. 5. `pnpm --dir web exec prettier --check .` — форматирование кода `web/`. @@ -24,6 +25,23 @@ pnpm verify Полный `test` уже включает тесты lint-правил; отдельный `test:rules` в `verify` оставлен как явный быстрый диагностический этап. +## Coverage + +`pnpm --dir web test:coverage` считает покрытие только по `src/lib` и падает +ниже порога. Scope и список исключений — в `web/vitest.config.ts`, обоснование — +в `docs/testing-strategy.md`. + +| Метрика | Порог | Baseline | +| ---------- | ----- | -------- | +| statements | 90 | 91.77% | +| branches | 82 | 83.3% | +| functions | 72 | 74.31% | +| lines | 91 | 92.53% | + +Порог — нижняя граница от текущего baseline, а не оценка качества: он блокирует +регрессию и не требует сначала закрывать весь долг. Локальный замер занимает ~30 +с, поэтому отдельного прогона в `verify` нет — `test:coverage` заменяет `test`. + ## E2E E2E не входит в `verify`, потому что Playwright поднимает build и статический diff --git a/docs/testing-strategy.md b/docs/testing-strategy.md index 55e0d39..0ea8074 100644 --- a/docs/testing-strategy.md +++ b/docs/testing-strategy.md @@ -68,6 +68,25 @@ browser-контракт: critical CRC и truncated отклоняются дв `src/**/*.test.ts`; DOM, hydration и пользовательские потоки — в Playwright. Component-тесты не дублируют e2e-контракт. +### Что попадает в coverage + +Coverage-гейт считает только `src/lib` и только то, что node-Vitest способен +исполнить. Исключения в `web/vitest.config.ts` и их причины: + +| Исключение | Причина | +| ------------------------------------------- | ------------------------------------------- | +| `**/*.test.ts`, `**/test-helpers.ts` | сами тесты | +| `**/*.svelte.ts` | runes, не работают в node | +| `executor/executor.worker.ts` | entry worker, исполняется только в браузере | +| `components/define.ts` | type-only, нет исполняемого кода | +| `core/domText.ts`, `core/io.ts` | canvas, `createImageBitmap`, нужен браузер | +| `i18n/en.ts`, `i18n/ru.ts`, `tool-icons.ts` | данные, а не логика | + +`registry/*` в scope остаётся: низкое покрытие там — это непокрытая логика, а не +следствие окружения. Исключение браузерных модулей означает, что переход +браузерного кода в scope — отдельное решение, связанное с DOM-тестами или visual +snapshots, а не молчаливое расширение списка исключений. + ## 5. Helpers и `test.fixme` `web/e2e/helpers/page.ts` владеет общими операциями `openTool`, `uploadImage`, diff --git a/package.json b/package.json index e391a27..06ec9ba 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "pnpm --dir web test", - "verify": "pnpm --dir web check && pnpm --dir web test && pnpm --dir web test:rules && pnpm --dir web lint:all && pnpm --dir web exec prettier --check . && pnpm check:docs && pnpm --dir web build", + "verify": "pnpm --dir web check && pnpm --dir web test:coverage && pnpm --dir web test:rules && pnpm --dir web lint:all && pnpm --dir web exec prettier --check . && pnpm check:docs && pnpm --dir web build", "dev": "pnpm --dir web dev", "build": "pnpm --dir web build", "format": "pnpm format:docs && pnpm --dir web format", diff --git a/web/package.json b/web/package.json index 742d6d3..a4050a1 100644 --- a/web/package.json +++ b/web/package.json @@ -11,6 +11,7 @@ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "test": "vitest run", + "test:coverage": "vitest run --coverage", "test:rules": "vitest run eslint-plugins/__tests__", "test:e2e": "playwright test", "format": "prettier --write . --log-level warn", @@ -27,6 +28,7 @@ "@sveltejs/kit": "^2.63.0", "@sveltejs/vite-plugin-svelte": "^7.1.2", "@types/node": "^26.5.0", + "@vitest/coverage-v8": "^4.1.11", "diff": "^9.0.0", "eslint": "^10.9.0", "eslint-config-prettier": "^10.1.8", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 8503fce..0bf4238 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -42,6 +42,9 @@ importers: '@types/node': specifier: ^26.5.0 version: 26.5.0 + '@vitest/coverage-v8': + specifier: ^4.1.11 + version: 4.1.11(vitest@4.1.11) diff: specifier: ^9.0.0 version: 9.0.0 @@ -98,7 +101,7 @@ importers: version: 8.2.1(@types/node@26.5.0) vitest: specifier: ^4.1.11 - version: 4.1.11(@types/node@26.5.0)(vite@8.2.1(@types/node@26.5.0)) + version: 4.1.11(@types/node@26.5.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.1(@types/node@26.5.0)) packages: @@ -106,10 +109,27 @@ packages: resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@cacheable/memory@2.2.0': resolution: {integrity: sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==} @@ -510,6 +530,15 @@ packages: resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/coverage-v8@4.1.11': + resolution: {integrity: sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==} + peerDependencies: + '@vitest/browser': 4.1.11 + vitest: 4.1.11 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/expect@4.1.11': resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} @@ -578,6 +607,9 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-v8-to-istanbul@1.0.7: + resolution: {integrity: sha512-kFL68AG6ajd8fg248zwM9GQrUWEp79gsmjum34OEXjs4yHuUMZfYKwOLW9GMmB4oNvVrj+EAGxsP7ye2UR9UlA==} + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -897,6 +929,10 @@ packages: globjoin@0.1.4: resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + has-flag@5.0.1: resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} engines: {node: '>=12'} @@ -911,6 +947,9 @@ packages: hookified@2.2.0: resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-tags@5.1.0: resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==} engines: {node: '>=20.10'} @@ -966,6 +1005,21 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1106,6 +1160,13 @@ packages: magic-string@1.2.0: resolution: {integrity: sha512-ptco+HFxTLgjafSLim2LojBSwfg5feBjd+SqyiwdGkzC38UPdZy3zgrHMI2CoTf5fJL38tbHMYWVzIH8BxGqJw==} + magicast@0.5.5: + resolution: {integrity: sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + mathml-tag-names@4.0.0: resolution: {integrity: sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==} @@ -1385,6 +1446,10 @@ packages: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} engines: {node: '>=18'} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + supports-hyperlinks@4.5.0: resolution: {integrity: sha512-ZW2OvfeCXrNTbLakPUzjQG922EeGCOteFSVoek5DKStTh898wf7zgtuFlzQN8HfZCxC3Eh02yJVrRW51hADf+w==} engines: {node: '>=20'} @@ -1608,8 +1673,21 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@bcoe/v8-coverage@1.0.2': {} + '@cacheable/memory@2.2.0': dependencies: '@cacheable/utils': 2.5.0 @@ -1961,6 +2039,20 @@ snapshots: '@typescript-eslint/types': 8.67.0 eslint-visitor-keys: 5.0.1 + '@vitest/coverage-v8@4.1.11(vitest@4.1.11)': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.11 + ast-v8-to-istanbul: 1.0.7 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.5 + obug: 2.1.4 + std-env: 4.2.0 + tinyrainbow: 3.1.1 + vitest: 4.1.11(@types/node@26.5.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.1(@types/node@26.5.0)) + '@vitest/expect@4.1.11': dependencies: '@standard-schema/spec': 1.1.0 @@ -2036,6 +2128,12 @@ snapshots: assertion-error@2.0.1: {} + ast-v8-to-istanbul@1.0.7: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + astral-regex@2.0.0: {} axobject-query@4.1.0: {} @@ -2345,6 +2443,8 @@ snapshots: globjoin@0.1.4: {} + has-flag@4.0.0: {} + has-flag@5.0.1: {} hashery@1.5.1: @@ -2355,6 +2455,8 @@ snapshots: hookified@2.2.0: {} + html-escaper@2.0.2: {} + html-tags@5.1.0: {} ignore@5.3.2: {} @@ -2392,6 +2494,21 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + js-tokens@10.0.0: {} + js-tokens@4.0.0: {} js-yaml@4.3.2: @@ -2496,6 +2613,16 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.5.5: + dependencies: + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + mathml-tag-names@4.0.0: {} mdn-data@2.27.1: {} @@ -2769,6 +2896,10 @@ snapshots: supports-color@10.2.2: {} + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + supports-hyperlinks@4.5.0: dependencies: has-flag: 5.0.1 @@ -2893,7 +3024,7 @@ snapshots: optionalDependencies: vite: 8.2.1(@types/node@26.5.0) - vitest@4.1.11(@types/node@26.5.0)(vite@8.2.1(@types/node@26.5.0)): + vitest@4.1.11(@types/node@26.5.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.1(@types/node@26.5.0)): dependencies: '@vitest/expect': 4.1.11 '@vitest/mocker': 4.1.11(vite@8.2.1(@types/node@26.5.0)) @@ -2917,6 +3048,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.5.0 + '@vitest/coverage-v8': 4.1.11(vitest@4.1.11) transitivePeerDependencies: - msw diff --git a/web/vitest.config.ts b/web/vitest.config.ts index 30f2992..5a65d4a 100644 --- a/web/vitest.config.ts +++ b/web/vitest.config.ts @@ -6,5 +6,29 @@ export default defineConfig({ test: { include: ["src/**/*.test.ts", "eslint-plugins/**/*.test.ts"], environment: "node", + coverage: { + provider: "v8", + reporter: ["text-summary"], + reportsDirectory: "./coverage", + include: ["src/lib/**/*.ts"], + exclude: [ + "src/lib/**/*.test.ts", + "src/lib/**/test-helpers.ts", + "src/lib/**/*.svelte.ts", + "src/lib/executor/executor.worker.ts", + "src/lib/components/define.ts", + "src/lib/core/domText.ts", + "src/lib/core/io.ts", + "src/lib/i18n/en.ts", + "src/lib/i18n/ru.ts", + "src/lib/tool-icons.ts", + ], + thresholds: { + statements: 90, + branches: 82, + functions: 72, + lines: 91, + }, + }, }, });