@7n/test 0.16.1 → 0.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.3] - 2026-07-18
4
+
5
+ ### Fixed
6
+
7
+ - Full-режим Storybook mutation testing: mutate-glob має виключати *.stories.* і *.mdx — інакше Stryker-інструментація ламає CSF-індексацію Storybook (виявлено при наскрізній перевірці через @7n/test coverage, підтверджено реальним mutation score 15/59 на Button/Header/Page.vue)
8
+
9
+ ## [0.16.2] - 2026-07-18
10
+
11
+ ### Fixed
12
+
13
+ - coverage: точний root cause провалу full-режиму Storybook mutation testing — дві незалежні причини замість 'невідомо'. (1) Stryker-інструментація ламає vue-docgen-api парсер @storybook/vue3-vite (framework-вбудований, не залежить від addon-docs) — виправлено через docgen:false у .storybook/main.js#framework.options, root cause підтверджено відтворенням поза Stryker-процесом. (2) окремий, підтверджений upstream Vitest browser mode баг (vitest#9509) — детерміновано (3/3), не флейкі, прогрів кешу не допомагає, не виправна на нашому боці. Full-режим лишається задокументованим напрямком до фіксу у Vitest
14
+ - coverage: подальше розслідування upstream Vitest browser-mode бага (vitest#9509) у full-режимі Storybook mutation testing — 11/11 детермінованих відтворень (було 3/3), простежено точний механізм резолву setup-file.js (bare-специфікатор через package.json#exports, версієзалежний .../internal/setup-file.browser.4), випробувано й відкинуто optimizeDeps.include з буквальним dist-шляхом (дає окрему exports-помилку) і з коректними bare-специфікаторами (синтаксично вірно, але не усуває fetch-провал). Висновок незмінний — --changed-executor лишається єдиним підтвердженим робочим шляхом
15
+ - coverage: vitest#9509 закритий upstream, але його фікс (optimizeDeps.include з повним runtime-стеком) не переноситься на наш кейс — ізоляційний тест з mutate:[] (0 інструментованих файлів) дає ту саму fetch-помилку на setup-file.js, виключаючи вміст файлів; штучна затримка перед стартом vitest теж не допомогла, виключаючи startup-race. Провал специфічний до факту спавну як дочірнього процесу Stryker — ймовірно окремий, ще не задокументований баг зі схожим симптомом. Висновок незмінний: --changed-executor лишається єдиним підтвердженим шляхом
16
+ - Full-режим Storybook mutation testing (Stryker command runner) тепер працює на реальних проєктах: root cause "Failed to fetch dynamically imported module" — symlinked node_modules у Stryker sandbox-копії, обхід через inPlace: true в stryker.storybook.config.mjs
17
+
3
18
  ## [0.16.1] - 2026-07-18
4
19
 
5
20
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/test",
3
- "version": "0.16.1",
3
+ "version": "0.16.3",
4
4
  "description": "CLI-утиліта @7n/test",
5
5
  "keywords": [
6
6
  "7n",
@@ -631,21 +631,35 @@ async function collectOneRoot(jsRoot, cwd, runner, scope = null) {
631
631
  * у контурі виконання.
632
632
  *
633
633
  * **Full-режим — Stryker command runner (`runStorybookStrykerFull`, опційний у
634
- * runner-і), АЛЕ з відомим невирішеним обмеженням (перевіряй перед покладанням
635
- * секція «Обмеження» в `npm/docs/stryker-storybook-config.md`):**
634
+ * runner-і), ПРАЦЮЄ на реальному проєкті за двох обов'язкових умов (перевіряй
635
+ * перед покладанням — секція «Обмеження» в `npm/docs/stryker-storybook-config.md`):**
636
636
  * Spike на синтетичному JS-репо (2026-07-17) підтвердив саму МЕХАНІКУ — command
637
637
  * runner + browser mode ПРАЦЮЄ з обов'язковим
638
638
  * `define: { 'process.env.__STRYKER_ACTIVE_MUTANT__': JSON.stringify(process.env.__STRYKER_ACTIVE_MUTANT__ ?? '') }`
639
- * у vite-конфізі (без define — тихий провал, 0% killed). Але живий прогін на
640
- * РЕАЛЬНОМУ `storybook init`-скаффолді (2026-07-18) показав: dry-run падає з
641
- * `Failed to fetch dynamically imported module` для `*.stories.js`, і ЖОДНА з
642
- * перевірених гіпотез (symlink sandbox, `inPlace: true`, vue-docgen-plugin,
643
- * concurrency) не root-cause. Той самий `vitest run --project=storybook`
644
- * бездоганно працює через ЗВИЧАЙНИЙ `spawnSync` (наш `--changed`-executor)
645
- * проблема специфічна саме до того, як Stryker spawn-ить/оточує процес.
646
- * Висновок: full-режим лишається задокументованим напрямком, не підтвердженим
647
- * робочим рішенням; `--changed`-executor (нижче) єдиний перевірений на
648
- * реальному проєкті шлях отримати справжній mutation score для Storybook-коду.
639
+ * у vite-конфізі (без define — тихий провал, 0% killed). Живий прогін на
640
+ * РЕАЛЬНОМУ `storybook init`-скаффолді (2026-07-18) виявив ДВІ незалежні
641
+ * причини провалу dry-run (`Failed to fetch dynamically imported module`),
642
+ * обидві тепер виправлені конфігом:
643
+ * (1) Stryker-інструментація ламає `vue-docgen-api`-парсер `@storybook/vue3-vite`
644
+ * root cause підтверджено (інструментований вміст, витягнутий з sandbox і
645
+ * підставлений напряму, відтворює ту саму помилку БЕЗ участі Stryker) і
646
+ * ВИПРАВЛЕНО через `docgen: false` у `.storybook/main.js#framework.options`;
647
+ * (2) Stryker sandbox symlink-ає `node_modules` у тимчасову `.stryker-tmp/sandbox-*`
648
+ * теку (дефолт), а `@storybook/addon-vitest` резолвить абсолютний шлях свого
649
+ * `setup-file.js` через РЕАЛЬНИЙ (symlink-target) шлях, а не sandbox-корінь —
650
+ * Vite dev server відмовляється віддавати файл поза власним root. Підтверджено
651
+ * прямим експериментом: `vitest run` (БЕЗ Stryker) із `node_modules`, вручну
652
+ * зробленим symlink-ом з іншої директорії, відтворює ту саму помилку 1:1;
653
+ * той самий `node_modules`, СКОПІЙОВАНИЙ (не symlink) — працює без помилок.
654
+ * `resolve.preserveSymlinks` (Vite) і `NODE_OPTIONS=--preserve-symlinks` (Node)
655
+ * НЕ допомагають (шлях резолвиться всередині коду самого addon-vitest, не
656
+ * через Vite-резолвер). ВИПРАВЛЕНО через `inPlace: true` у
657
+ * `stryker.storybook.config.mjs` — Stryker мутує файли без sandbox-копії,
658
+ * symlink просто не задіяний.
659
+ * Висновок: з обома фіксами (`docgen: false` + `inPlace: true`) full-режим
660
+ * дає справжній mutation score на реальному Storybook-проєкті;
661
+ * `--changed`-executor (нижче) лишається окремим шляхом для звичайного
662
+ * PR-прогону по змінених файлах.
649
663
  *
650
664
  * Changed-режим: запускається тільки якщо серед змінених файлів root-а є хоча б
651
665
  * один `.vue`/`*.stories.*` (`scope.files` — вже звужений через `scopeToStorybookRoot`
@@ -702,8 +716,9 @@ async function collectStorybookForRoot(jsRoot, cwd, runner, scope = null) {
702
716
  if (code !== 0 && !existsSync(reportPath)) {
703
717
  throw new Error(
704
718
  `Storybook Stryker (command runner) exit ${code} — перевір ${STORYBOOK_STRYKER_CONFIG} ` +
705
- '(testRunner: "command", commandRunner.command, jsonReporter.fileName) ' +
706
- 'і define __STRYKER_ACTIVE_MUTANT__ у vite-конфізі browser-проєкту'
719
+ '(testRunner: "command", commandRunner.command, jsonReporter.fileName, inPlace: true), ' +
720
+ 'define __STRYKER_ACTIVE_MUTANT__ у vite-конфізі browser-проєкту ' +
721
+ 'і docgen: false у .storybook/main.js#framework.options (див. npm/docs/stryker-storybook-config.md)'
707
722
  )
708
723
  }
709
724
  if (existsSync(reportPath)) {