test(web): standardize frontend tests on Vitest - #6569
Conversation
- configure Vitest, jsdom, and React Testing Library with shared test scripts. - migrate existing node:test suites to the Vitest runner. - rewrite JsonCodeEditor component tests with RTL and remove the direct happy-dom dependency.
# Conflicts: # web/src/features/profile/components/login-session-utils.test.ts
WalkthroughThe web test infrastructure now uses Vitest with jsdom and React Testing Library. The JSON editor tests use Testing Library interactions. Existing tests now use Vitest imports and lifecycle hooks. ChangesVitest test infrastructure
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
- invoke the configured Vitest script so browser test setup loads in CI. - migrate remaining node:test suites to Vitest lifecycle APIs.
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 `@web/src/features/usage-logs/components/__tests__/cost-display.test.tsx`:
- Line 20: Remove the stale happy-dom Window imports and fixtures from
cost-display.test.tsx at lines 20-20 and 108-108, and from
tool-price-validation.test.tsx at lines 20-20 and 89-89; retain the existing
jsdom-based test behavior and cleanup.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3be0a2ad-0b5d-4b13-8b61-e1d1bb0a43bb
📒 Files selected for processing (7)
.github/workflows/ci.ymlweb/src/features/auth/lib/__tests__/oauth-callback-mode.test.tsweb/src/features/channels/lib/__tests__/new-api-channel.test.tsweb/src/features/profile/components/__tests__/login-session-utils.test.tsweb/src/features/system-settings/models/__tests__/tool-price-validation.test.tsxweb/src/features/usage-logs/components/__tests__/cost-display.test.tsxweb/src/features/usage-logs/lib/__tests__/tool-surcharge.test.ts
| */ | ||
| import assert from 'node:assert/strict' | ||
| import { after, describe, test } from 'node:test' | ||
| import { afterAll, describe, test } from 'vitest' |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
for file in \
web/src/features/usage-logs/components/__tests__/cost-display.test.tsx \
web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx
do
rg -n -C 3 '\bWindow\b|happy-dom|jsdom' "$file"
done
fd -i 'package.json|bun.lock|bun.lockb' web -x \
rg -n '"happy-dom"|'\''happy-dom'\''' {}Repository: QuantumNous/new-api
Length of output: 2378
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo "== package files =="
git ls-files 'web/**/package.json' | sed -n '1,120p'
echo
echo "== project/dependency declarations for happy-dom/jsdom/vitest =="
while IFS= read -r f; do
echo "-- $f --"
rg -n -C 2 '"(happy-dom|jsdom|vitest)\"|happy-dom|jsdom' "$f" || true
done < <(git ls-files 'web/**/package.json')
echo
echo "== vitest config files =="
git ls-files 'web' | rg '(^|/)(vitest\.config\.[cm][jt]sx?|vitest\.config\.[cm]?[jt]s|vite\.config\.[cm][jt]sx?)$' | while read -r f; do
echo "-- $f --"
sed -n '1,220p' "$f"
doneRepository: QuantumNous/new-api
Length of output: 296
🏁 Script executed:
#!/usr/bin/env bash
set -uo pipefail
echo "== package files under tracked repo =="
git ls-files | rg '(^|/)web/src/features/.*/package\.json$|(^|/)web/package\.json$|(^|/)package\.json$' || true
echo
echo "== happy-dom / jsdom declarations in package manifests =="
while IFS= read -r f; do
echo "-- $f --"
rg -n -C 2 '"(happy-dom|jsdom|vitest)\"|happy-dom|jsdom' "$f" || true
done < <(git ls-files | rg '(^|/)web/src/features/.*/package\.json$|(^|/)web/package\.json$|(^|/)package\.json$')
echo
echo "== vitest config files =="
git ls-files | rg '(^|/)(vitest\.config\.[cm][jt]sx?|vitest\.config\.[cm]?[jt]s|vite\.config\.[cm][jt]sx?)$' | while read -r f; do
echo "-- $f --"
sed -n '1,220p' "$f"
doneRepository: QuantumNous/new-api
Length of output: 1615
🏁 Script executed:
#!/usr/bin/env bash
set -uo pipefail
echo "== web/package.json =="
cat web/package.json
echo
echo "== focused declarations =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path('web/package.json')
data = json.loads(p.read_text())
for section in ('dependencies','devDependencies','peerDependencies','optionalDependencies'):
print(f'[{section}]')
deps = data.get(section,{})
for name in ('happy-dom','jsdom','vitest','`@types/jsdom`'):
if name in deps:
print(f'{name}: {deps[name]}')
PY
echo
echo "== imports/usages in test files =="
python3 - <<'PY'
from pathlib import Path
for p in [
Path('web/src/features/usage-logs/components/__tests__/cost-display.test.tsx'),
Path('web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx'),
]:
print(f'-- {p} --')
text = p.read_text()
for idx,line in enumerate(text.splitlines(),1):
if 'Window' in line or 'happy-dom' in line or 'jsdom' in line or 'afterAll' in line:
print(f'{idx}: {line}')
PYRepository: QuantumNous/new-api
Length of output: 4780
🌐 Web query:
Vitest 4 jsdom environment global Window property domGlobals configuration
💡 Result:
In Vitest, there is no configuration setting explicitly named "domGlobals" [1][2]. Vitest manages global browser-like APIs through its environment system (e.g., jsdom or happy-dom) [3][4]. When using the jsdom environment, Vitest automatically injects browser globals into the Node.js global object [5][6]. Vitest uses a facade pattern to ensure that window, self, global, and globalThis consistently share the same state [6][7]. If you need to configure or customize the jsdom environment, you should use the environmentOptions configuration in your vitest.config file [3][1]: // vitest.config.ts import { defineConfig } from 'vitest/config' export default defineConfig({ test: { environment: 'jsdom', environmentOptions: { jsdom: { // Options passed directly to the JSDOM constructor url: 'http://localhost:3000', userAgent: 'MyApp/1.0', }, }, }, }) Key points regarding global configuration in Vitest: 1. Environment Selection: Set environment: 'jsdom' in your test configuration to enable the browser-like environment [3][4]. 2. Globals API: If you want Vitest's test APIs (like describe, it, expect) to be globally available, set globals: true in your test configuration [8]. 3. TypeScript Support: To help TypeScript recognize the jsdom-specific globals, add vitest/jsdom to the types array in your tsconfig.json [4]: { "compilerOptions": { "types": ["vitest/jsdom"] } } Vitest manages the Window object internally by populating the global namespace with the JSDOM window's properties [6]. Modifications to standard window properties are generally handled by Vitest's internal utility functions to maintain synchronization across the various global aliases (window, self, etc.) [6][7].
Citations:
- 1: https://vitest.dev/config/environmentoptions
- 2: https://vitest.dev/config/
- 3: https://vitest.dev/guide/environment
- 4: https://vitest.dev/config/environment
- 5: https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/integrations/env/jsdom.ts
- 6: https://github.com/vitest-dev/vitest/blob/206e8cff/packages/vitest/src/integrations/env/utils.ts
- 7: Setting
window.innerWidthdoesn't actually setinnerWidthon happy-dom'swindowobject vitest-dev/vitest#10343 - 8: https://vitest.dev/config/globals
Remove the stale happy-dom imports and fixtures
Vitest test runs use jsdom, but both tests still import and create Window from happy-dom. Since happy-dom is no longer declared in web/package.json, delete web/src/features/usage-logs/components/__tests__/cost-display.test.tsx#L22-L25 and web/src/features/usage-logs/components/__tests__/cost-display.test.tsx#L108-L109; update the same fixture/cleanup in web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx#L22-L25 and web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx#L89-L90.
📍 Affects 2 files
web/src/features/usage-logs/components/__tests__/cost-display.test.tsx#L20-L20(this comment)web/src/features/usage-logs/components/__tests__/cost-display.test.tsx#L108-L108web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx#L20-L20web/src/features/system-settings/models/__tests__/tool-price-validation.test.tsx#L89-L89
🤖 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 `@web/src/features/usage-logs/components/__tests__/cost-display.test.tsx` at
line 20, Remove the stale happy-dom Window imports and fixtures from
cost-display.test.tsx at lines 20-20 and 108-108, and from
tool-price-validation.test.tsx at lines 20-20 and 89-89; retain the existing
jsdom-based test behavior and cleanup.
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
概述
改动说明
测试说明
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit