@@ -1680,6 +1680,108 @@ export default defineConfig(CONFIG);`,
16801680 expect ( planProject ( root ) . projects [ 0 ] . active ) . toBe ( false ) ;
16811681 } ) ;
16821682
1683+ it . each ( [
1684+ "export const tools = ['vite', 'vitest', '@vitest/runner', 'vite-plus/test'];" ,
1685+ "export const tool = { name: 'vitest' };" ,
1686+ "// import { test } from 'vitest';\nexport const value = 1;" ,
1687+ "/* export * from 'vitest'; vitest run */\nexport const value = 1;" ,
1688+ 'export const example = "import { test } from \'vitest\';";' ,
1689+ 'export const help = `Run vitest run or vp test`;' ,
1690+ "console.log('vitest run');" ,
1691+ "const execSync = (command) => command; execSync('vitest run');" ,
1692+ "const { execSync } = require('./logger'); execSync('vitest run');" ,
1693+ 'const docs = `\n/// <reference types="vitest/globals" />\n`;' ,
1694+ '/*\n/// <reference types="vitest/globals" />\n*/' ,
1695+ "function require(name) { return name; } require('vitest');" ,
1696+ "const loader = { require(name) { return name; } }; loader.require('vitest');" ,
1697+ "import { expect } from 'vitest-like';" ,
1698+ "export * from 'vite-plus/testing';" ,
1699+ ] ) ( 'does not require a runner version for incidental source text: %s' , ( input ) => {
1700+ const root = project ( { 'package.json' : '{}' , 'src/plugin.ts' : input } ) ;
1701+ const plan = planProject ( root ) ;
1702+ expect ( plan . projects [ 0 ] . active ) . toBe ( false ) ;
1703+ expect ( plan . findings ) . toEqual ( [ ] ) ;
1704+ expect ( plan . changes ) . toEqual ( [ ] ) ;
1705+ } ) ;
1706+
1707+ it . each ( [
1708+ "import { test } from 'vitest';" ,
1709+ "import 'vitest';" ,
1710+ "import type { TestAPI } from 'vitest';" ,
1711+ "export { test } from 'vite-plus/test';" ,
1712+ "export * from '@vitest/runner';" ,
1713+ "const runner = await import('vitest/node');" ,
1714+ "const runner = require('vitest');" ,
1715+ "import runner = require('vitest');" ,
1716+ "type Runner = import('vitest/node').Vitest;" ,
1717+ "declare module 'vitest' { interface ProvidedContext { port: number } }" ,
1718+ '/// <reference types="vitest/globals" />' ,
1719+ "import { execSync as run } from 'node:child_process'; run('pnpm exec vitest run');" ,
1720+ "import * as cp from 'child_process'; cp.spawn('vitest', ['run']);" ,
1721+ "import cp from 'node:child_process'; cp.execSync('vp test');" ,
1722+ "import { spawnSync } from 'node:child_process'; spawnSync('pnpm', ['exec', 'vitest', 'run']);" ,
1723+ "import { execFileSync } from 'child_process'; execFileSync('vp', ['test']);" ,
1724+ "const { execSync: run } = require('node:child_process'); run('vitest run');" ,
1725+ "const cp = require('child_process'); cp.spawn('vitest', ['run']);" ,
1726+ "require('node:child_process').execSync('vp test');" ,
1727+ ] ) ( 'still requires a runner version for actual source usage: %s' , ( input ) => {
1728+ const root = project ( { 'package.json' : '{}' , 'runner.ts' : input } ) ;
1729+ const plan = planProject ( root ) ;
1730+ expect ( plan . projects [ 0 ] . active ) . toBe ( true ) ;
1731+ expect ( plan . findings ) . toContainEqual (
1732+ expect . objectContaining ( { code : 'source-version' , severity : 'block' } ) ,
1733+ ) ;
1734+ expect ( plan . changes ) . toEqual ( [ ] ) ;
1735+ } ) ;
1736+
1737+ it ( 'keeps the version check when source usage cannot be parsed' , ( ) => {
1738+ const root = project ( {
1739+ 'package.json' : '{}' ,
1740+ 'runner.ts' : "import { test } from 'vitest'; const broken = ;" ,
1741+ } ) ;
1742+ const plan = planProject ( root ) ;
1743+ expect ( plan . projects [ 0 ] . active ) . toBe ( true ) ;
1744+ expect ( plan . findings ) . toContainEqual (
1745+ expect . objectContaining ( { code : 'source-version' , severity : 'block' } ) ,
1746+ ) ;
1747+ } ) ;
1748+
1749+ it ( 'migrates Vitest workspace members without activating their plugin package' , ( ) => {
1750+ const plugin = "export const NON_RUNTIME_PKGS = ['vite', 'vitest'];" ;
1751+ const root = project ( {
1752+ 'package.json' : JSON . stringify ( {
1753+ name : 'plugin' ,
1754+ scripts : { test : 'node test-examples.js' } ,
1755+ } ) ,
1756+ 'src/index.ts' : plugin ,
1757+ 'examples/vite-8/package.json' : JSON . stringify ( { devDependencies : { vitest : '^4.1.11' } } ) ,
1758+ 'examples/vite-8/vitest.config.ts' : 'export default { test: { globals: true } };' ,
1759+ 'examples/vite-8/unit.test.js' : "test.sequential('works', () => {});" ,
1760+ } ) ;
1761+ const workspace = {
1762+ rootDir : root ,
1763+ packageManager : PackageManager . pnpm ,
1764+ packages : [ { name : 'example' , path : 'examples/vite-8' } ] ,
1765+ } ;
1766+ const plan = planVitestV5Migration ( workspace ) ;
1767+ expect ( plan . projects . map ( ( { active, sourceVersion } ) => ( { active, sourceVersion } ) ) ) . toEqual ( [
1768+ { active : false , sourceVersion : undefined } ,
1769+ { active : true , sourceVersion : '4.1.11' } ,
1770+ ] ) ;
1771+ expect ( plan . findings ) . toEqual ( [ ] ) ;
1772+ applyVitestV5Migration ( plan ) ;
1773+ expect ( finishVitestV5Migration ( plan ) ) . toEqual ( [ ] ) ;
1774+ expect ( fs . readFileSync ( path . join ( root , 'src/index.ts' ) , 'utf8' ) ) . toBe ( plugin ) ;
1775+ expect ( fs . readFileSync ( path . join ( root , 'examples/vite-8/unit.test.js' ) , 'utf8' ) ) . toContain (
1776+ "test('works', { concurrent: false }" ,
1777+ ) ;
1778+ const repeated = planVitestV5Migration ( workspace ) ;
1779+ expect ( repeated . projects [ 0 ] . active ) . toBe ( false ) ;
1780+ expect ( repeated . findings ) . toEqual ( [ ] ) ;
1781+ expect ( repeated . changes ) . toEqual ( [ ] ) ;
1782+ expect ( Object . keys ( repeated . state . vitest5 ! ) ) . toEqual ( [ 'examples/vite-8' ] ) ;
1783+ } ) ;
1784+
16831785 it . each ( [
16841786 [ 'vitest' , '4.1.11' , '4.1.11' , { } ] ,
16851787 [
0 commit comments