Repository navigation
fix(test): migrate Vitest 5 with correct per-test mutation IDs - #391
Conversation
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
f25a94c to
f78a77a
Compare
5b3c9c4 to
c8ca8ce
Compare
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.11 to 5.0.2. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.2/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 5.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
c8ca8ce to
8e6bf78
Compare
|
@coderabbitai Проверьте exact 453fe29 против current main 708efd5. Старый exact RED был предметным: Vitest5 удалил describe.sequential, а Stryker9/Vitest5 дал mutation score3.32 при обязательном break80. Исправление не снижает thresholds/scope: describe.sequential заменён официальным Vitest5 |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base=708efd55a9bf9a2a158b138e8bf7d6a8b28bb25f
head=453fe29b7fe82cee395f8bab02625c1445888a2c
git rev-parse HEAD
git show -s --format='%H %s' "$base" "$head"
git diff --stat "$base" "$head"
git diff --name-status "$base" "$head"
git diff "$base" "$head" -- . ':!pnpm-lock.yaml'
fd -i 'stryker|vitest|package.json|pnpm-lock.yaml'
gh api repos/Labpics-Team/lab-motion/commits/"$head"/check-runs --paginate --jq '.check_runs[] | {name,status,conclusion,details_url,head_sha}'
gh api repos/Labpics-Team/lab-motion/commits/"$head"/status --jq '{state,statuses:[.statuses[]|{context,state,target_url}]}'
gh pr view 391 --repo Labpics-Team/lab-motion --json headRefOid,baseRefOid,statusCheckRollupLength of output: 7088 🤖 web_search executed:
Length of output: 2449 🏁 Script executed: #!/bin/bash
set -euo pipefail
for f in stryker.config.mjs stryker.driver.config.mjs vitest.config.ts vitest.stryker.config.ts vitest.stryker.driver.config.ts test/animate-finished-allocation.test.ts package.json; do
ast-grep outline "$f" --items all || true
done
for f in stryker.config.mjs stryker.driver.config.mjs vitest.config.ts vitest.stryker.config.ts vitest.stryker.driver.config.ts test/animate-finished-allocation.test.ts; do
echo "=== $f ==="; cat -n "$f"
done
sed -n '1,150p' package.json
sed -n '520,640p' package.json
fd -t f . .github/workflows
rg -n -C3 'mutation|stryker|pnpm|node-version|fuzz|vitest' .github/workflows
rg -n -C2 'sequential|sequence:|poolOptions|workspace|deps:|mockReset|isolate:|maxThreads|minThreads|coverage:|setupFiles|fakeTimers|toFake|vi\.(mock|spyOn|useFakeTimers|resetAllMocks|restoreAllMocks)|vitest/(execute|utils|browser)' --glob '*.{ts,js,mjs,json}' --glob '!pnpm-lock.yaml' .
git diff 708efd55a9bf9a2a158b138e8bf7d6a8b28bb25f 453fe29b7fe82cee395f8bab02625c1445888a2c -- pnpm-lock.yaml | head -250
gh api repos/stryker-mutator/stryker-js/compare/v9.6.1...v10.0.0 --jq '{status,total_commits,files:[.files[] | select(.filename | test("vitest-runner|mutation.*(score|result)|mutant.*(score|result)|package.json$")) | {filename,status,patch}]}'Length of output: 145511 🤖 web_search executed:
Length of output: 7535 🏁 Script executed: #!/bin/bash
set -euo pipefail
gh api repos/stryker-mutator/stryker-js/git/trees/v10.0.0?recursive=1 --jq '.tree[] | select(.path|test("^packages/vitest-runner/src/|^packages/core/src/.*(score|coverage|mutant)|^packages/instrumenter/src/.*empty-expression")) | .path'
for f in packages/vitest-runner/src/vitest-test-runner.ts packages/vitest-runner/src/vitest-helpers.ts packages/vitest-runner/src/stryker-setup.ts packages/vitest-runner/src/test-helpers.ts packages/vitest-runner/package.json; do
echo "=== upstream $f ==="
gh api "repos/stryker-mutator/stryker-js/contents/$f?ref=v10.0.0" --jq '.content' | base64 -d | cat -n
done
gh api repos/stryker-mutator/stryker-js/compare/v9.6.1...v10.0.0 --jq '.files[] | select(.filename|test("^packages/(core|instrumenter)/src/")) | {filename,patch}'
for f in test/driver-single-solve.test.ts test/root-request-frame-ssot.test.ts test/benchmark-provenance.test.ts; do
ast-grep outline "$f" --items all || true
done
sed -n '1,180p' test/driver-single-solve.test.ts
sed -n '1,100p' test/root-request-frame-ssot.test.ts
sed -n '1,90p' test/benchmark-provenance.test.ts
rg -n -C2 'testNamePattern|expect\.(poll|extend)|\.resolves\.|\.rejects\.|toThrow\((.|\n)*|vitest/|@vitest/|\.mockImplementation|vi\.fn\(' test --glob '*.ts' | head -200
sed -n '20,60p' .github/workflows/ci.yml
sed -n '259,290p' .github/workflows/ci.yml
rg -n -C2 'mutation-testing-metrics@|vitest@5.0.2:|@stryker-mutator/vitest-runner@10.0.0:|@babel/core@8' pnpm-lock.yaml
gh api repos/Labpics-Team/lab-motion/actions/runs/36820429245/jobs --paginate --jq '.jobs[] | {name,status,conclusion,head_sha,steps:[.steps[] | {name,status,conclusion}]}'Length of output: 77710 🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C2 'testNamePattern|expect\.(poll|extend)|\.resolves\.|\.rejects\.|vitest/|@vitest/|mockImplementationOnce|mockReturnValueOnce' test --glob '*.ts' || true
sed -n '20,60p' .github/workflows/ci.yml
sed -n '259,290p' .github/workflows/ci.yml
rg -n -C2 'mutation-testing-metrics@|vitest@5.0.2:|@stryker-mutator/vitest-runner@10.0.0:' pnpm-lock.yaml
gh api repos/Labpics-Team/lab-motion/actions/runs/36820429245/jobs --paginate --jq '.jobs[] | {id,name,status,conclusion,head_sha,steps:[.steps[] | {name,status,conclusion}]}'
gh api repos/vitest-dev/vitest/git/trees/v5.0.2?recursive=1 --jq '.tree[] | select(.path|test("^packages/(runner|vitest)/src/.*(collect|utils|run|config)|^docs/guide/migration")) | .path' | head -90
gh api repos/vitest-dev/vitest/contents/docs/guide/migration.md?ref=v5.0.2 --jq '.content' | base64 -d | sed -n '1,340p'
gh api repos/stryker-mutator/stryker-js/contents/packages/api/src/test-runner/mutant-run-result.ts?ref=v10.0.0 --jq '.content' | base64 -d | cat -nLength of output: 37007 🏁 Script executed: #!/bin/bash
set -euo pipefail
python - <<'PY'
import subprocess,json,base64,re
def read(repo,path,ref):
raw=subprocess.check_output(['gh','api',f'repos/{repo}/contents/{path}?ref={ref}'])
return base64.b64decode(json.loads(raw)['content']).decode()
targets=[
('vitest-dev/vitest','docs/guide/migration/index.md','v5.0.2',r'testNamePattern|clearMocks|sequential|Node.js|Vite'),
('vitest-dev/vitest','packages/vitest/src/runtime/runner/collect.ts','v5.0.2',r'testNamePattern|getTaskFullName|skip'),
('vitest-dev/vitest','packages/vitest/src/runtime/runner/utils/collect.ts','v5.0.2',r'getTaskFullName|join\('),
('vitest-dev/vitest','packages/vitest/src/runtime/runner/utils/suite.ts','v5.0.2',r'getTaskFullName|join\('),
('stryker-mutator/stryker-js','packages/api/src/test-runner/mutant-run-result.ts','v10.0.0',r'toMutantRunResult|Survived|Failed|Skipped')
]
for repo,path,ref,pat in targets:
print(f'\n=== {repo}/{path}@{ref} ===')
try: text=read(repo,path,ref)
except subprocess.CalledProcessError as e:
print('FAILED',e.returncode); continue
lines=text.splitlines(); indices=set()
for i,line in enumerate(lines):
if re.search(pat,line):
indices.update(range(max(0,i-5), min(len(lines),i+14)))
for i in sorted(indices): print(f'{i+1}: {lines[i]}')
PY
gh api repos/Labpics-Team/lab-motion/commits/453fe29b7fe82cee395f8bab02625c1445888a2c/check-runs --paginate --jq '.check_runs[] | {name,status,conclusion,details_url,head_sha}'
gh api repos/Labpics-Team/lab-motion/actions/runs/36820429245 --jq '{head_sha,event,status,conclusion,html_url}'
gh api repos/Labpics-Team/lab-motion/actions/jobs/110234623683 --jq '{status,conclusion}'
# Read hosted logs only when the mutation job is finished.
status=$(gh api repos/Labpics-Team/lab-motion/actions/jobs/110234623683 --jq '.status')
if [ "$status" = completed ]; then
gh run view 36820429245 --repo Labpics-Team/lab-motion --job 110234623683 --log | tail -100
fiLength of output: 30984 🏁 Script executed: #!/bin/bash
set -euo pipefail
python - <<'PY'
import subprocess,json,base64,re
def api(endpoint):
return json.loads(subprocess.check_output(['gh','api',endpoint]))
def content(repo,path,ref):
return base64.b64decode(api(f'repos/{repo}/contents/{path}?ref={ref}')['content']).decode()
repo='stryker-mutator/stryker-js'
tree=api(f'repos/{repo}/git/trees/v10.0.0?recursive=1')['tree']
paths=[x['path'] for x in tree if x['type']=='blob' and x['path'].startswith('packages/api/src/test-runner/') and x['path'].endswith('.ts')]
for path in paths:
text=content(repo,path,'v10.0.0')
if 'function toMutantRunResult' in text:
print('===',path,'===')
lines=text.splitlines()
start=next(i for i,l in enumerate(lines) if 'function toMutantRunResult' in l)
for i in range(max(0,start-3), min(len(lines),start+85)): print(f'{i+1}: {lines[i]}')
repo='vitest-dev/vitest'
path='packages/vitest/src/runtime/runner/utils/suite.ts'
text=content(repo,path,'v5.0.2')
print('===',path,'===')
print('\n'.join(f'{i+1}: {l}' for i,l in enumerate(text.splitlines()[:35])))
PY
gh api repos/Labpics-Team/lab-motion/commits/453fe29b7fe82cee395f8bab02625c1445888a2c/check-runs --paginate --jq '.check_runs[]|{name,status,conclusion}'Length of output: 4336 🏁 Script executed: #!/bin/bash
set -euo pipefail
gh run view 36820429245 --repo Labpics-Team/lab-motion --job 110234623683 --log | tail -120
gh api repos/Labpics-Team/lab-motion/actions/runs/36820429245 --jq '{head_sha,status,conclusion,html_url}'Length of output: 14497
Вердикт: exact остаётся RED. Обновление до Stryker 10 не завершает миграцию. Найден блокирующий дефект совместимости perTest-фильтра. 1. Блокер: Stryker 10 передаёт Vitest 5 неправильное полное имя тестаЦепочка подтверждается исходниками фиксированных версий:
Например, фильтр Дополнительный дефект диагностики усиливает проблему. В Это конкретное объяснение низкого score, но не доказательство единственной причины всех survivors. Подпись 2. Hosted CI подтвердил отказ exactRun 36820429245 завершился
Mutation job сообщил: Таким образом, прежний отказ не устранён. Порог 3. Последовательность и оракул allocation-теста сохраненыЗамена в describe('animate finished: O(1) library Promise constructors', { concurrent: false }, () => {Тела тестов, assertions и порядок объявления не изменены. Ослабления этого оракула в diff не нашёл. 4. Stryker 10 меняет набор мутаций, а не только совместимость раннераScope и thresholds в репозитории действительно сохранены:
Однако upstream Stryker 10 добавляет Поэтому старый и новый score нельзя считать результатами идентичного набора мутаций. Для сравнения нужны категории и статусы мутаций. Изменения формулы score по одной лишь неизменности конфигурации исключить нельзя. 5. Остальные требования Vitest 5Существенное изменение — Требование среды точнее, чем «Node 22+»: Vitest 5 требует как минимум Node 22.12.0. Babel 8 в новом lock требует Следующий шаг: исправить совместимость полного имени теста в раннере с Vitest 5. Исправление должно согласовать IDs coverage и mutation-фильтр. Затем повторить hosted mutation gate без снижения Спасибо за ограничения проверки. ✏️ Learnings added
You are interacting with an AI system. |
|
A newer version of vitest exists, but since this PR has been edited by someone other than Dependabot I haven't updated it. You'll get a PR for the updated version as normal once this PR is merged. |
Vitest 5.0.2 and Stryker 10.0.0 are integrated with current main. Stryker’s compiled and TypeScript test-name writers now use Vitest 5’s
>boundary and retain authored whitespace. A native regression compares the installed helper to Vitest’s actualtask.fullTestName, including nested literal names and anonymous suites. The existing allocation suite keeps its sequential execution through the Vitest 5 options API.The real pinned pnpm 11.11.0 manager generated the lockfile and accepted a final frozen lock. Existing supply-chain policy verification passed; 440 package identities resolve, and all 378 retained package resolution integrities remain unchanged. The minimum-release-age, trust/error policy, overrides, and exact patched-consumer hash remain intact.
Independent six-file source/lock review passed on
e117f19ceff40cc24f0503fb0455f94c444effd5(treebb95eeedceb8e4288a2b146c18fecd5ee6dc122c). Integrity-verified published Vitest/Stryker tarballs reproduce two nested tests skipped before the fix and selected afterward with the actual Vitest mode interpreter; bare/whitespace/anonymous controls stay selected and preserve exact identity. The patch applies to all four pinned source files.Product source, CI workflows, mutation configuration, per-test analysis and the driver break-80 gate remain unchanged versus current main. Fresh full native installation, the actual regression, test/fuzz coverage, and driver mutation score remain required before acceptance. The bounded source counterexample does not claim a passing full mutation score.