Skip to content

Commit a806c4a

Browse files
committed
feat: add migrate-vitest-to-rstest skill
1 parent 02796fa commit a806c4a

File tree

1 file changed

+208
-0
lines changed

1 file changed

+208
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
name: migrate-vitest-to-rstest
3+
description: Migrate or convert Vitest test suites and configs to Rstest. Use when asked to move from Vitest to Rstest, replace `vitest` imports with `@rstest/core`, translate Vitest config to `rstest.config.ts`, or update Vite test config to Rsbuild/Rstest equivalents.
4+
---
5+
6+
# Migrate Vitest to Rstest
7+
8+
## Goal
9+
10+
Migrate Vitest-based tests and configuration to Rstest with minimal behavior changes. Use the reference guide as the source of truth for exact API and config mappings.
11+
12+
## Migration principles (must follow)
13+
14+
1. **Smallest-change-first**: prefer the smallest viable change that restores test pass.
15+
2. **Config before code**: prefer fixing in config/tooling/mocks before touching test logic.
16+
3. **Do not change user source behavior**: avoid modifying production/business source files unless user explicitly requests it.
17+
4. **Avoid bulk test rewrites**: do not refactor entire test suites when a local compatibility patch can solve it.
18+
5. **Preserve test intent**: keep assertions and scenario coverage unchanged unless clearly broken by framework differences.
19+
6. **Defer Vitest removal**: keep `vitest` dependency and `vitest.config.*` during migration; remove them only after Rstest tests pass.
20+
21+
## Workflow
22+
23+
1. Inventory current Vitest usage
24+
2. **Open the official migration guide**
25+
- Use the Official guide as the source of truth:
26+
- https://rstest.rs/guide/migration/vitest.md
27+
3. Dependency install gate (blocker check)
28+
4. Migrate configuration and test files following the guide and reference details (minimal patch scope)
29+
5. Check type errors
30+
6. Run tests and fix deltas (apply the `providedExports` checklist below when mocks fail unexpectedly)
31+
7. Remove `vitest` dependency and legacy `vitest.config.*` only after Rstest is green
32+
8. Summarize changes
33+
34+
## 1. Inventory current Vitest usage
35+
36+
- Locate Vitest config (`vitest.config.*` or `vite.config.*` with a `test` block) and record the format.
37+
- Capture current test commands and test file patterns (include/exclude or globs).
38+
- Run test suite to verify current behavior.
39+
- List setup files, environment settings, and any globals usage.
40+
- Note any Vite config dependencies that tests rely on (aliases, plugins, or defines).
41+
42+
## 3. Dependency install gate (blocker check)
43+
44+
Before large-scale edits, verify dependencies can be installed and test runner binaries are available.
45+
46+
### Goal
47+
48+
Avoid partial migrations that cannot be validated due to missing dependencies.
49+
50+
### Recommended checks
51+
52+
- Confirm lockfile/package manager context is healthy.
53+
- Install dependencies for the target workspace/package.
54+
- Verify `rstest` executable is resolvable from local dependencies.
55+
56+
### Package manager detection (do this before install)
57+
58+
Always detect package manager from repo context before running install commands.
59+
60+
Preferred signal order:
61+
62+
1. `packageManager` field in nearest `package.json`.
63+
2. Lockfile presence in workspace/root:
64+
- `pnpm-lock.yaml` -> `pnpm`
65+
- `yarn.lock` -> `yarn`
66+
- `package-lock.json` or `npm-shrinkwrap.json` -> `npm`
67+
3. Monorepo convention/scripts already used in repo docs/CI.
68+
69+
If signals conflict, prefer `packageManager` field, then lockfile.
70+
71+
### Install command policy
72+
73+
- Use the detected package manager first.
74+
- In monorepo, run workspace-scoped install/check before root-level install when possible.
75+
- Do not mix package managers in one migration attempt unless user explicitly asks.
76+
77+
Reference command patterns (choose one by detection):
78+
79+
- `pnpm`: `pnpm install` / workspace-scoped equivalent
80+
- `yarn`: `yarn install`
81+
- `npm`: `npm install`
82+
83+
If the chosen manager fails due to environment/tool absence (not dependency conflict), report it and propose the exact next command for the user instead of auto-switching silently.
84+
85+
### If install/check succeeds
86+
87+
- Continue migration normally.
88+
89+
### If install/check fails (blocked mode)
90+
91+
Do **not** continue broad code migration.
92+
Stop at a minimal safe point and return a blocker report for the user to resolve manually.
93+
94+
Blocked-mode output should include:
95+
96+
1. Exact failed command(s).
97+
2. Error class (network/auth/registry/peer conflict/lockfile mismatch/permission).
98+
3. Concrete next command(s) for the user to run.
99+
4. Whether any files were already changed.
100+
5. Resume point: "after dependencies are installed, continue from Step 4".
101+
6. Detected package manager and detection basis (field/lockfile).
102+
103+
### Monorepo guidance
104+
105+
- Prefer workspace-scoped install/check first (target package), then root if needed.
106+
- Avoid changing unrelated packages while blocked.
107+
- If root install is required but unavailable, limit edits to docs or planning notes only.
108+
109+
## Patch scope policy (strict)
110+
111+
### Preferred change order
112+
113+
1. CLI/script/config migration (`package.json`, `rstest.config.ts`, include/exclude, test environment).
114+
2. Mock compatibility adjustments (target module path, `{ mock: true }`, `importActual`).
115+
3. Narrow per-test setup fixes (single-file, single-suite level).
116+
4. As a last resort, test body changes.
117+
5. Never modify runtime source logic by default.
118+
119+
### Red lines
120+
121+
- Do not rewrite many tests in one sweep without first proving config-level fixes are insufficient.
122+
- Do not alter business/runtime behavior to satisfy tests.
123+
- Do not change assertion semantics just to make tests pass.
124+
- Do not broaden migration to unrelated packages in monorepo.
125+
- Do not delete `vitest` dependency or `vitest.config.*` before confirming Rstest tests pass.
126+
127+
### Escalation rule for large edits
128+
129+
If a fix would require either:
130+
131+
- editing many test files, or
132+
- changing user source files,
133+
134+
stop and provide:
135+
136+
1. why minimal fixes failed,
137+
2. proposed large-change options,
138+
3. expected impact/risk per option,
139+
4. recommended option.
140+
141+
## 5. Run tests and fix deltas
142+
143+
- Run the test suite and fix failures iteratively.
144+
- Fix configuration and resolver errors first, then address mocks/timers/snapshots, and touch test logic last.
145+
- If mocks fail for re-exported modules under Rspack, use the **ProvidedExports Troubleshooting** section below before rewriting lots of tests.
146+
147+
## ProvidedExports Troubleshooting (Rspack + Mock-heavy tests)
148+
149+
This is a high-frequency migration pitfall and should be checked early.
150+
151+
### When to suspect this
152+
153+
- Test imports and mocks a re-export module (for example `foo-dom` re-exporting from `foo-core`).
154+
- Mock appears to be ignored after migration.
155+
- Failures are concentrated in module-mock tests, especially with `rs.mock('re-export-module', ...)`.
156+
- Runtime behavior suggests code is resolved from source module, not the re-export module.
157+
158+
### Why it happens
159+
160+
Rspack may optimize re-exports with `optimization.providedExports`.
161+
After optimization, runtime can bypass the re-export layer, so your mock target no longer matches what is actually executed.
162+
163+
### Migration-safe handling order (do this in order)
164+
165+
1. Temporarily disable `providedExports` to stabilize migration.
166+
2. Migrate tests until green.
167+
3. Re-enable `providedExports` and re-run tests.
168+
4. If failures come back, either:
169+
- keep `providedExports: false` temporarily, or
170+
- change mocks to the actual resolved source module.
171+
172+
### Temporary config snippet
173+
174+
```ts
175+
export default defineConfig({
176+
tools: {
177+
rspack: {
178+
optimization: {
179+
providedExports: false,
180+
},
181+
},
182+
},
183+
});
184+
```
185+
186+
### Mock target adjustment example
187+
188+
If code imports from `react-router-dom` but runtime resolves to `react-router`, mock `react-router`:
189+
190+
```ts
191+
rs.mock('react-router', () => ({
192+
useParams: () => ({ id: 'mocked-id' }),
193+
}));
194+
```
195+
196+
### Documentation expectation in migration summary
197+
198+
If this workaround is used, explicitly record:
199+
200+
- where `providedExports` was changed,
201+
- whether the change is temporary or permanent,
202+
- which tests/modules still rely on it,
203+
- next cleanup action (re-enable and retest scope).
204+
205+
## 6. Summarize changes
206+
207+
- Provide a concise change summary and list files touched.
208+
- Call out any remaining manual steps or TODOs.

0 commit comments

Comments
 (0)