Update dependency vitest to v4 [SECURITY]#3002
Conversation
📝 WalkthroughWalkthroughUpgrade Vitest-related devDependencies from ^3.0.0 to ^4.0.0 across root and workspace manifests; convert several test mock arrow functions to regular function implementations; lower Vitest coverage thresholds in backend and frontend configs. ChangesVitest 4.0.0 Upgrade
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (2)
packages/request/package.json (1)
46-46: Advisory: Review security configuration for Vitest API/UI usage.This upgrade addresses CVE-2026-47429 by adding
api.allowWriteandapi.allowExecoptions (disabled by default when bound to non-localhost). If your vitest configuration explicitly exposes the API server (viaapi.host), verify that the new security defaults align with your requirements.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/request/package.json` at line 46, The package's vitest upgrade adds new security options; review the vitest dependency entry ("vitest") and any Vitest configuration (e.g., vitest.config.* or package.json vitest section) and explicitly set api.allowWrite and api.allowExec to false (or to values matching your security policy) when api.host is non-localhost, and verify api.host isn't unintentionally bound to 0.0.0.0; update the configuration to document and enforce the desired defaults so the new CVE-related protections are applied.packages/polling-watcher/package.json (1)
40-40: Advisory: Review security configuration for Vitest API/UI usage.This upgrade addresses CVE-2026-47429 by adding
api.allowWriteandapi.allowExecoptions (disabled by default when bound to non-localhost). If your vitest configuration explicitly exposes the API server (viaapi.host), verify that the new security defaults align with your requirements.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/polling-watcher/package.json` at line 40, The package bumped vitest to a version that introduces new security options; inspect your Vitest configuration (e.g., vitest.config.ts or the "vitest" block in package.json) for any non-localhost API exposure via the api.host setting and explicitly set api.allowWrite and api.allowExec to false (or to the minimal required privileges) when api.host is not localhost; update the config to document and enforce these flags and run tests to confirm no regression.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/package.json`:
- Line 101: Update the `@vitest/coverage-v8` dependency to a v4-compatible major
to match vitest's ^4.0.0: change the package.json entry for
"`@vitest/coverage-v8`" from ^3.0.0 to a v4.x release (or use a range compatible
with vitest ^4.0.0), then run yarn/npm install and verify the "test-coverage"
script (vitest run --coverage) works; ensure package.json's "vitest" and
"`@vitest/coverage-v8`" versions are aligned so the peerDependency requirement is
satisfied.
In `@charts/package.json`:
- Line 38: Update the mismatched coverage provider by bumping the
`@vitest/coverage-v8` dependency to a v4 release to match vitest v4: modify the
devDependency entry for "`@vitest/coverage-v8`" (the package name symbol) to
"^4.0.0" in package.json, then reinstall dependencies (refresh lockfile) so
vitest run --coverage uses the compatible coverage-v8 v4 provider.
In `@frontend/package.json`:
- Line 110: The package.json currently sets "vitest": "^4.0.0" while
"`@vitest/ui`" and "`@vitest/coverage-v8`" remain on "^3.0.0", causing mixed-major
dependency issues; update the versions for "`@vitest/ui`" and
"`@vitest/coverage-v8`" to the v4 range (match the "vitest" major version) so all
Vitest packages are on the same major version and run a lockfile refresh/install
to ensure peers resolve correctly.
In `@packages/kube-client/package.json`:
- Line 53: Update the mismatched coverage package to match Vitest v4 by bumping
the dependency "`@vitest/coverage-v8`" to a v4 compatible major version in
packages/kube-client's package.json; locate the devDependencies entry for
"`@vitest/coverage-v8`" and change its version to the same major as "vitest" (v4)
so both "vitest" and "`@vitest/coverage-v8`" are on major version 4.
In `@packages/kube-config/package.json`:
- Line 44: The workspace has a Vitest version mismatch:
packages/kube-config/package.json pins "vitest": "^4.0.0" while
`@vitest/coverage-v8` is still at "^3.0.0"; update the dependency versions so they
match major versions (either downgrade "vitest" to a 3.x release or upgrade
"`@vitest/coverage-v8`" to a 4.x release) to ensure coverage hooks work
correctly—modify the package.json entry for "vitest" or the workspace dependency
for "`@vitest/coverage-v8`" accordingly and run the workspace install to verify no
other packages are left with conflicting Vitest major versions.
In `@packages/logger/package.json`:
- Line 39: The package.json in packages/logger lists vitest@^4.0.0 but still has
`@vitest/coverage-v8`@^3.0.0; update the devDependency for `@vitest/coverage-v8` to
the matching major (e.g. ^4.0.0) so it aligns with vitest v4, then
reinstall/update the lockfile (npm/yarn/pnpm) to resolve deps; check the
"devDependencies" entry for `@vitest/coverage-v8` and run the package manager to
regenerate the lockfile and ensure tests/coverage run under Vitest v4.
In `@packages/monitor/package.json`:
- Line 48: The package.json shows vitest upgraded to ^4.0.0 but
`@vitest/coverage-v8` remains at ^3.0.0; update the `@vitest/coverage-v8` dependency
to a v4-compatible release (match the Vitest major) in
packages/monitor/package.json and then regenerate lockfile entries (run yarn
install / yarn or npm install) so yarn.lock no longer contains mixed v3/v4
coverage-v8 versions; ensure references to "vitest" and "`@vitest/coverage-v8`" in
package.json align on major version.
In `@packages/polling-watcher/package.json`:
- Line 40: Update the `@vitest/coverage-v8` dependency to a Vitest v4-compatible
release: in package.json replace the current `@vitest/coverage-v8` version spec
(the dependency named "`@vitest/coverage-v8`") with a 4.x range such as "^4.0.0"
so it matches the "vitest" dependency "^4.0.0" used by the project and ensures
the "test-coverage" script ("vitest run --coverage") runs with compatible
coverage tooling.
In `@packages/request/package.json`:
- Line 46: package.json has vitest at v4 but `@vitest/coverage-v8` remains ^3.0.0,
which can break the test-coverage script; update the dependency
"`@vitest/coverage-v8`" to a matching v4 range (e.g., "^4.0.0" or "^4.x") so it
aligns with "vitest" and the "test-coverage" script continues to work, then run
install and verify the test-coverage script runs correctly.
---
Nitpick comments:
In `@packages/polling-watcher/package.json`:
- Line 40: The package bumped vitest to a version that introduces new security
options; inspect your Vitest configuration (e.g., vitest.config.ts or the
"vitest" block in package.json) for any non-localhost API exposure via the
api.host setting and explicitly set api.allowWrite and api.allowExec to false
(or to the minimal required privileges) when api.host is not localhost; update
the config to document and enforce these flags and run tests to confirm no
regression.
In `@packages/request/package.json`:
- Line 46: The package's vitest upgrade adds new security options; review the
vitest dependency entry ("vitest") and any Vitest configuration (e.g.,
vitest.config.* or package.json vitest section) and explicitly set
api.allowWrite and api.allowExec to false (or to values matching your security
policy) when api.host is non-localhost, and verify api.host isn't
unintentionally bound to 0.0.0.0; update the configuration to document and
enforce the desired defaults so the new CVE-related protections are applied.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 672b41f8-4f35-481c-9195-03bbe38c0098
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (11)
.pnp.cjsbackend/package.jsoncharts/package.jsonfrontend/package.jsonpackage.jsonpackages/kube-client/package.jsonpackages/kube-config/package.jsonpackages/logger/package.jsonpackages/monitor/package.jsonpackages/polling-watcher/package.jsonpackages/request/package.json
Edited/Blocked NotificationRenovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR. You can manually request rebase by checking the rebase/retry box above. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/vitest.config.js`:
- Around line 36-39: The frontend vitest coverage thresholds are much lower than
backend and may misrepresent real coverage after Vitest v4 removed coverage.all;
update frontend/vitest.config.js to (1) document and justify the chosen
thresholds (statements:52, branches:43, functions:42, lines:52) and include the
CI coverage report output proving the repo meets these exact numbers, (2) align
thresholds with backend or explain why they differ, and (3) add a
coverage.include pattern in the config to ensure measured scope matches intended
files (mirroring backend behavior) and add a short remediation plan to restore
stronger gates (e.g., target thresholds and steps: add tests, enable
instrumentation, incremental threshold bumps). Reference the keys
coverage.threshold and coverage.include and the file frontend/vitest.config.js
and ensure the PR includes the CI report snippet and the rationale/plan.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1862cd61-d83d-46ea-8263-dbc3a5dcfe3a
📒 Files selected for processing (3)
backend/__tests__/security.spec.jsbackend/vitest.config.jsfrontend/vitest.config.js
✅ Files skipped from review due to trivial changes (1)
- backend/vitest.config.js
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/tests/security.spec.js
| statements: 52, | ||
| branches: 43, | ||
| functions: 42, | ||
| lines: 52, |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Vitest v4 coverage calculation breaking changes
💡 Result:
Vitest v4 introduced several significant changes to code coverage calculation, primarily focused on improving accuracy and performance. If you are upgrading from v3, you should expect to see changes in your coverage reports [1][2]. Key Breaking Changes and Updates: 1. Coverage Options Removed: - coverage.all: This option has been completely removed [1][2]. Vitest now defaults to including only files that were loaded during the test run in the report [1][3]. If you need to include additional files, you must explicitly define them using the coverage.include configuration [1][2]. - coverage.extensions: This option has been removed [1][3]. - coverage.experimentalAstAwareRemapping: This option is removed as AST-based remapping is now enabled by default and serves as the only supported method [1][2]. - coverage.ignoreEmptyLines: This option is removed; lines without runtime code are now automatically excluded from reports [1][2]. 2. V8 Provider Improvements: - Improved Remapping: Vitest no longer uses v8-to-istanbul for V8 coverage remapping [1][2]. Instead, it uses a new, proprietary package utilizing AST-based analysis [1][3]. This change is intended to make V8 coverage reports as accurate as those generated by the Istanbul provider [1][2]. - New Support: The V8 provider now supports coverage.ignoreClassMethods [1][2]. 3. Configuration Recommendations: - Because coverage.all was removed, it is recommended that you explicitly define coverage.include in your vitest.config.ts file to ensure all relevant source files are measured [1][2]. - The default exclude behavior has been simplified; Vitest now only excludes tests from node_modules and.git folders by default, meaning other previously excluded patterns may need to be explicitly configured [2]. These changes are documented in the official Vitest migration guide [2]. Given the move to more accurate, AST-aware remapping, expect minor variations in coverage percentages when comparing v4 results to those from v3 [1][2].
Citations:
- 1: https://github.com/vitest-dev/vitest/blob/1a4705da/docs/guide/migration.md
- 2: https://vitest.dev/guide/migration.html
- 3: https://github.com/vitest-dev/vitest/blob/main/docs/guide/migration.md
🏁 Script executed:
#!/bin/bash
# Check current actual coverage to see if thresholds match reality or are padded
cd frontend
# Run coverage report to see actual percentages
npx vitest run --coverage --reporter=json 2>/dev/null | jq -r '.coverageMap | if . then "Coverage data available" else "No coverage data" end' || echo "Coverage collection may require build"
# Look for coverage.all references in config history or docs
rg -n "coverage\.all" --type js -C 2
# Check if there are test changes or removals in this PR that would explain coverage drops
git log -1 --name-only --pretty=format:"%H %s" | head -20Repository: gardener/dashboard
Length of output: 718
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== frontend/vitest.config.js (lines 1-120) =="
nl -ba frontend/vitest.config.js | sed -n '1,120p'
echo
echo "== Extract coverage-related config (frontend) =="
rg -n "coverage\.(all|include|exclude|extensions|ignoreEmptyLines)|coverage\s*:" frontend/vitest.config.js frontend/**/*.js frontend/**/*.ts frontend/package.json || true
echo
echo "== Search for coverage.all anywhere in frontend =="
rg -n "coverage\.all" frontend || true
echo
echo "== Search for coverage.include anywhere in frontend =="
rg -n "coverage\.include" frontend || true
echo
echo "== Attempt to run Vitest coverage and summarize actual coverage (may fail if deps missing) =="
cd frontend
# Try to run coverage; if it fails, we’ll print the error and exit gracefully.
set +e
npx vitest run --coverage --reporter=json > /tmp/vitest-coverage.json 2> /tmp/vitest-coverage.err
status=$?
set -e
if [ $status -ne 0 ]; then
echo "vitest coverage run failed with exit code $status"
echo "--- stderr (tail) ---"
tail -200 /tmp/vitest-coverage.err || true
exit 0
fi
python3 - <<'PY'
import json
p="/tmp/vitest-coverage.json"
data=json.load(open(p))
# Try multiple shapes (Vitest/istanbul variants)
cov = data.get("coverageMap") or data.get("coverage") or {}
if not cov:
print("No coverageMap/coverage present in report JSON.")
print("Top-level keys:", list(data.keys())[:50])
raise SystemExit(0)
# Istanbul-like: coverageMap is a dict of files; compute totals from that if possible.
total = data.get("totals") or data.get("global") or data.get("result") or {}
if total:
print("Totals/global present:", {k: total.get(k) for k in ["statements","branches","functions","lines","total"] if k in total})
# If percentages exist:
for k in ["statements","branches","functions","lines"]:
v=total.get(k)
if isinstance(v, dict) and "pct" in v:
print(f"{k}: {v['pct']}")
raise SystemExit(0)
# Fallback: compute pct by summing counts (rough; may differ if report shape differs)
def pct(hit, total):
return None if total in (0,None) else (hit/total*100.0)
# If coverageMap exists, extract hits/total from each file’s summary if available
files = cov.values() if isinstance(cov, dict) else []
agg = {"statements":[0,0],"branches":[0,0],"functions":[0,0],"lines":[0,0]}
for f in files:
s = f.get("statements",{})
b = f.get("branches",{})
fn= f.get("functions",{})
# statements: list of {count}? or summary counts?
# In some shapes, there is a 's'/'b' arrays; handle minimal common Istanbul structures:
if isinstance(s, list):
for x in s:
c=x.get("count",0) if isinstance(x,dict) else 0
agg["statements"][1]+=1
if c>0: agg["statements"][0]+=1
if isinstance(b, list):
for x in b:
# branches list items can have 'counts' array
counts = x.get("counts") if isinstance(x,dict) else None
if isinstance(counts,list):
for c in counts:
agg["branches"][1]+=1
if (c or 0)>0: agg["branches"][0]+=1
if isinstance(fn, list):
for x in fn:
c=x.get("count",0) if isinstance(x,dict) else 0
agg["functions"][1]+=1
if c>0: agg["functions"][0]+=1
# lines sometimes mirrors statements in Istanbul; skip if not present
for k,(hit,totalc) in agg.items():
if totalc:
print(f"{k}: {pct(hit,totalc):.2f}% (hit {hit} / total {totalc})")
PY
echo
echo "== Done =="Repository: gardener/dashboard
Length of output: 169
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== frontend/vitest.config.js (lines 1-140) =="
cat -n frontend/vitest.config.js | sed -n '1,140p'
echo
echo "== Extract coverage-related config (frontend) =="
rg -n "coverage\.(all|include|exclude|extensions|ignoreEmptyLines)|coverage\s*:" frontend/vitest.config.js frontend/**/*.js frontend/**/*.ts frontend/package.json || true
echo
echo "== Search for coverage.all anywhere in frontend =="
rg -n "coverage\.all" frontend || true
echo
echo "== Search for coverage.include anywhere in frontend =="
rg -n "coverage\.include" frontend || true
echo
echo "== Attempt to run Vitest coverage and summarize actual coverage =="
cd frontend
set +e
npx vitest run --coverage --reporter=json > /tmp/vitest-coverage.json 2> /tmp/vitest-coverage.err
status=$?
set -e
if [ $status -ne 0 ]; then
echo "vitest coverage run failed with exit code $status"
echo "--- stderr (tail) ---"
tail -200 /tmp/vitest-coverage.err || true
exit 0
fi
python3 - <<'PY'
import json
data=json.load(open('/tmp/vitest-coverage.json'))
cov = data.get("coverageMap") or data.get("coverage") or {}
print("JSON top-level keys:", list(data.keys())[:40])
if not cov:
print("No coverageMap/coverage present.")
raise SystemExit(0)
tot = data.get("totals") or data.get("global") or data.get("result") or {}
if isinstance(tot, dict) and any(k in tot for k in ["statements","branches","functions","lines","total"]):
print("Detected global totals keys:", list(tot.keys()))
for k in ["statements","branches","functions","lines","total"]:
if k in tot:
print(k, tot[k])
raise SystemExit(0)
print("coverageMap shape detected (no obvious totals). Files:", len(cov) if isinstance(cov, dict) else type(cov))
# Try to find a file named like coverage summary
PY
echo "== Done =="Repository: gardener/dashboard
Length of output: 9544
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== backend/vitest.config.js (lines 1-200) =="
if [ -f backend/vitest.config.js ]; then
cat -n backend/vitest.config.js | sed -n '1,200p'
else
echo "backend/vitest.config.js not found"
fi
echo
echo "== Search for coverage.all across repo =="
rg -n "coverage\.all" . || true
echo
echo "== Search for coverage.include across repo =="
rg -n "coverage\.include" . || true
echo
echo "== Search for 'coverage: {' blocks that set thresholds =="
rg -n "coverage:\s*\{" -S . || trueRepository: gardener/dashboard
Length of output: 1554
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== vitest versions in package.json files (root + workspace packages) =="
rg -n --glob '**/package.json' '"vitest"\s*:\s*"|vitest"\s*:\s*"' .
rg -n --glob '**/package.json' '"`@vitest/`|vitest"' package.json **/package.json || true
echo
echo "== Frontend package.json =="
cat frontend/package.json 2>/dev/null || echo "frontend/package.json not found"
echo
echo "== Root package.json =="
cat package.json 2>/dev/null || echo "root package.json not found"Repository: gardener/dashboard
Length of output: 6575
Justify and align frontend coverage thresholds after Vitest v4 upgrade
frontend/vitest.config.jsnow enforces much lower gates: statements52, branches43, functions42, lines52.- This is inconsistent with
backend/vitest.config.js, which sets far higher thresholds (e.g., branches68, functions93, statements/lines89). - With Vitest v4,
coverage.allwas removed and coverage reports default to measuring only files loaded during the test run;frontendalso does not setcoverage.include, so the measured scope (and therefore the threshold meaning) may have changed.
Please provide:
- The CI/coverage report output showing actual achieved coverage meets these exact thresholds.
- The rationale for choosing these threshold values (and whether
coverage.includeshould be set to match the intended measurement set / backend behavior). - A plan to restore stronger gates if these values were lowered to “make CI pass” rather than reflect real coverage quality.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/vitest.config.js` around lines 36 - 39, The frontend vitest coverage
thresholds are much lower than backend and may misrepresent real coverage after
Vitest v4 removed coverage.all; update frontend/vitest.config.js to (1) document
and justify the chosen thresholds (statements:52, branches:43, functions:42,
lines:52) and include the CI coverage report output proving the repo meets these
exact numbers, (2) align thresholds with backend or explain why they differ, and
(3) add a coverage.include pattern in the config to ensure measured scope
matches intended files (mirroring backend behavior) and add a short remediation
plan to restore stronger gates (e.g., target thresholds and steps: add tests,
enable instrumentation, incremental threshold bumps). Reference the keys
coverage.threshold and coverage.include and the file frontend/vitest.config.js
and ensure the PR includes the CI report snippet and the rationale/plan.
|
/lgtm |
|
LGTM label has been added. DetailsGit tree hash: ceafccd5169a42a0efe05495ea534ec0b8b21e90 |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: grolu The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This PR contains the following updates:
^3.0.0→^4.0.0When Vitest UI server is listening, arbitrary file can be read and executed
CVE-2026-47429 / GHSA-5xrq-8626-4rwp
More information
Details
Summary
Arbitrary file can be read on Windows when Vitest UI server is listening, especially when exposed to the network.
Impact
Only users that match either of the following conditions are affected:
--api.hostorapi.hostconfig option)Details
The API handler for
/__vitest_attachment__uses the deprecatedisFileServingAllowedincorrectly.https://github.com/vitest-dev/vitest/blob/eb1abf08573032a532015b999ad3501c5e89e3bb/packages/ui/node/index.ts#L77
The function expects the passed value to use
cleanUrlafter the check before file system related operation.Because of this, it is possible to bypass the check by
\\?\\..\\. This is not possible on Linux as Linux errors if a directory named?does not exist.A similar problem exists in other places as well.
That said, this
isFileServingAllowedcheck does not actually prevent the API to be abused. Since the API has rerun feature and file write feature, it's possible to run arbitrary script by writing a script as a test file usingsaveTestFileand running it usingrerun. This means exposing the API / Vitest UI is equivalent to giving script execution access.On the browser mode side, there're
readFile/writeFile/saveSnapshotFile. So exposing the browser mode is equivalent to giving file read / write access.PoC
curl http://localhost:51204/__vitest__/curl "http://localhost:51204/__vitest_attachment__?path=C:\\path\\to\\project\\?\\..\\..\\secret.txt&contentType=text/plain&token=$TOKEN"(TOKEN is the API token)secret.txtthat is outside the project directoryMitigations
Vitest now ships two configuration flags,
allowWriteandallowExec, that gate the privileged operations exploited by this vulnerability. Both are disabled by default whenever the API server is bound to a non-localhosthost, ensuring that exposing the server to the network no longer implicitly grants write or execute capabilities to remote clients.When these flags are disabled, the UI also enters a read-only mode: in-browser code editing and test file execution are turned off, removing the attack surface that allowed remote code execution. Many Browser Mode features are also disabled, like attachments, artifacts or snapshots. See
browser.api.Users who require the full interactive UI on a networked host must explicitly opt in by setting
allowWriteand/orallowExectotrue.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
vitest-dev/vitest (vitest)
v4.1.0Compare Source
Vitest 4.1 is out!
This release page lists all changes made to the project during the 4.1 beta. To get a review of all the new features, read our blog post.
🚀 Features
setTickModeto timer controls - by @atscott and @sheremet-va in #8726 (4b480)toTestSpecificationto reported tasks - by @sheremet-va in #9464 (1a470)vi.mockorvi.hoistedare declared outside of top level of the module - by @sheremet-va in #9387 (5db54)aroundEachandaroundAllhooks - by @sheremet-va in #9450 (2a8cb)neworallin--updateflag - by @sheremet-va in #9543 (a5acf)metain test options - by @sheremet-va in #9535 (7d622)test.extendsyntax - by @sheremet-va in #9550 (e5385)vitest listto statically collect tests instead of running files to collect them - by @sheremet-va in #9630 (7a8e7)--detect-async-leaks- by @AriPerkkio in #9528 (c594d)mockThrowandmockThrowOnce- by @thor-juhasz and @sheremet-va in #9512 (61917)update: "none"and add docs about snapshots behavior on CI - by @hi-ogawa in #9700 (05f18)launchOptionswithconnectOptions- by @hi-ogawa in #9702 (f0ff1)page/locator.markAPI to enhance playwright trace - by @hi-ogawa in #9652 (d0ee5)testinexperimental_parseSpecification- by @jgillick and Jeremy Gillick in #9235 (2f367)createSpecification- by @sheremet-va in #9336 (c8e6c)runTestFilesas alternative torunTestSpecifications- by @sheremet-va in #9443 (43d76)allowWriteandallowExecoptions toapi- by @sheremet-va in #9350 (20e00)toTestSpecification- by @sheremet-va in #9627 (6f17d)userEvent.wheelAPI - by @macarie in #9188 (66080)filterNodeoption to prettyDOM for filtering browser assertion error output - by @Copilot, sheremet-va and @sheremet-va in #9475 (d3220)detailsPanelPositionoption and button - by @shairez in #9525 (c8a31)findElementand enable strict mode in webdriverio and preview - by @sheremet-va in #9677 (c3f37)ignore start/stopignore hints - by @AriPerkkio in #9204 (e59c9)coverage.changedoption to report only changed files - by @kykim00 and @AriPerkkio in #9521 (1d939)onModuleRunnerhook toworker.init- by @sheremet-va in #9286 (e977f)importDurations: { limit, print }options - by @hi-ogawa, Claude Opus 4.6 and @sheremet-va in #9401 (7e10f)importDurations- by @hi-ogawa and Claude Opus 4.6 in #9533 (3f7a5)beforeAll/afterAll- by @sheremet-va in #9572 (c8339)agentreporter to reduce ai agent token usage - by @cpojer in #9779 (3e9e0)retryoptions - by @MazenSamehR, Matan Shavit, @AriPerkkio and @sheremet-va in #9370 (9e4cf)🐞 Bug Fixes
meta.urlincreateRequire- by @sheremet-va in #9441 (e3422)external/noExternalduringconfigEnvironmenthook - by @hi-ogawa and Claude Opus 4.6 in #9508 (59ea2)browser.isolateis used - by @sheremet-va in #9410 (3d48e)vi.mock({ spy: true })node v8 coverage - by @hi-ogawa, hi-ogawa and Claude Opus 4.6 in #9541 (687b6).namefrom statically collected test - by @sheremet-va in #9596 (b66ff)expect.soft- by @iumehara, @hi-ogawa and Claude Opus 4.6 in #9231 (3eb2c)sequence.shuffle.testsis enabled - by @kaigritun, Kai Gritun and @sheremet-va in #9576 (8182b)expect/src/utilsfromvitest- by @hi-ogawa in #9616 (48739)--detect-async-leaks- by @AriPerkkio in #9638 (9fd4c)aroundEach/Allwhen inneraroundEach/Allthrows - by @hi-ogawa in #9657 (4ec6c)aroundEach/Allsetup timed out - by @hi-ogawa in #9670 (bb013)VitestRunnerConfigoptional fields withSerializedConfig- by @hi-ogawa in #9661 (79520)toBe*spy assertions in favor oftoHaveBeen*(andtoThrowError) - by @sheremet-va in #9665 (4d390)aroundEach/Allerrors but aggregate them on runner - by @hi-ogawa in #9673 (b6365)resolves/rejectschained assertion error - by @hi-ogawa in #9679 (c6151)maxConcurrency- by @hi-ogawa in #9653 (16d13)resolve.conditionsfor externals - by @hi-ogawa in #9717 (1d498)mockObjectchange backwards compatible - by @sheremet-va in #9744 (84c69)URL.nameon jsdom - by @hi-ogawa in #9767 (031f3)vi.importActual()for virtual modules - by @hi-ogawa and Claude Opus 4.6 in #9772 (1e89e)FixtureAccessErrorif suite hook accesses undefined fixture - by @sheremet-va in #9786 (fc2ce)loadortransformoriginal module - by @hi-ogawa and Claude Opus 4.6 in #9774 (a8216)hideSkippedTestsshould not hidetest.todo- by @oilater in #9562 and #9781 (8181e)beforeEachhooks - by @hi-ogawa and Claude Opus 4.6 in #9826 (99e52)performance.nowto measure test timeout duration - by @hi-ogawa and Claude Opus 4.6 in #9795 (f48a6)toMatchScreenshotpasses - by @macarie in #9289 (46aab)toMatchScreenshot- by @macarie in #9552 (83ca0)--remote-debugging-addressfrom chrome args - by @hi-ogawa and @AriPerkkio in #9712 (f09bb)ensureAwaited- by @sheremet-va in #9732 (97685)getCDPSessionandcdp()- by @AriPerkkio in #9716 (689a2)deepEqualin the config because it's not serializable - by @sheremet-va in #9666 (9ee99)thresholds.autoUpdateto preserve ending whitespace - by @AriPerkkio in #9436 (7e534)/config/#optionhash links causing hydration errors - by @hi-ogawa, Claude Opus 4.6 and @sheremet-va in #9610 (a603c)toMatchObject(Map/Set)should expectMap/Seton left hand side - by @hi-ogawa and Claude Opus 4.6 in #9532 (381da)toThrowand make Error detection robust - by @hi-ogawa and Claude Opus 4.6 in #9570 (de215)dotreporter leaves pending tests - by @AriPerkkio in #9684 (4d793)undefined- by @sheremet-va in #9511 (6f181)bench.reportersno longer gives type errors when passing file name string paths - by @Bertie690 in #9695 (093c8)🏎 Performance
View changes on GitHub
v4.0.18Compare Source
🚀 Experimental Features
onModuleRunnerhook toworker.init- by @sheremet-va in #9286 (ea837)🐞 Bug Fixes
meta.urlincreateRequire- by @sheremet-va in #9441 (e0572)View changes on GitHub
v4.0.17Compare Source
🚀 Experimental Features
🐞 Bug Fixes
addEventHandler#9371 - by @ThibautMarechal in #9372 and #9371 (40841)process.envandimport.meta.envdefines in inline project - by @hi-ogawa in #9239 (b70c9)ErrorEvent.messagewhen unhandledErrorEvent.erroris null - by @hi-ogawa in #9322 (5d84e)fileParallelismon an instance - by @sheremet-va in #9328 (15006)istanbul-lib-source-mapsusage - by @AriPerkkio in #9344 (b0940)View changes on GitHub
v4.0.16Compare Source
🐞 Bug Fixes
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.
Summary by CodeRabbit