11import fs from 'node:fs/promises'
22import path from 'node:path'
3+ import type { CopyOptions } from 'node:fs'
34import type { TestProject } from 'vitest/node'
45import type { BrowserServer } from 'playwright-chromium'
56import { chromium } from 'playwright-chromium'
67
78let browserServer : BrowserServer | undefined
9+ const PLAYGROUND_NAME_REGEX = / p l a y g r o u n d \/ ( [ \w - ] + ) \/ /
810
9- export async function setup ( { provide } : TestProject ) : Promise < void > {
11+ export async function setup ( project : TestProject ) : Promise < void > {
1012 browserServer = await chromium . launchServer ( {
1113 headless : ! process . env . VITE_DEBUG_SERVE ,
1214 args : process . env . CI
1315 ? [ '--no-sandbox' , '--disable-setuid-sandbox' ]
1416 : undefined ,
1517 } )
1618
17- provide ( 'wsEndpoint' , browserServer . wsEndpoint ( ) )
19+ project . provide ( 'wsEndpoint' , browserServer . wsEndpoint ( ) )
1820
1921 const tempDir = path . resolve ( import . meta. dirname , '../playground-temp' )
22+ const testFiles = project . vitest . state . getPaths ( )
23+ const playgroundDirs = [
24+ ...new Set ( testFiles . map ( ( file ) => file . match ( PLAYGROUND_NAME_REGEX ) ?. [ 1 ] ) ) ,
25+ ]
26+ // These files / directories are used by multiple playground tests
27+ const commonPlaygroundDirs = [ 'tsconfig.json' , 'resolve-linked' ]
28+
2029 await fs . rm ( tempDir , { recursive : true , force : true } )
2130 await fs . mkdir ( tempDir , { recursive : true } )
22- await fs
23- . cp ( path . resolve ( import . meta. dirname , '../playground' ) , tempDir , {
24- recursive : true ,
25- dereference : false ,
26- filter ( file ) {
27- file = file . replace ( / \\ / g, '/' )
28- return ! file . includes ( '__tests__' ) && ! / d i s t (?: \/ | $ ) / . test ( file )
29- } ,
30- } )
31- . catch ( async ( error ) => {
32- if ( error . code === 'EPERM' && error . syscall === 'symlink' ) {
33- throw new Error (
34- 'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.' ,
35- )
36- } else {
37- throw error
38- }
39- } )
31+ await Promise . all (
32+ [ ...commonPlaygroundDirs , ...playgroundDirs ] . map ( async ( dir ) => {
33+ const srcDir = path . resolve ( import . meta. dirname , dir )
34+ const destDir = path . resolve ( tempDir , dir )
35+ await copyWithFriendlyError ( srcDir , destDir , {
36+ recursive : true ,
37+ filter : filterForPlaygroundCopy ,
38+ } )
39+ } ) ,
40+ )
4041 // also setup dedicated copy for "variant" tests
41- for ( const [ original , variants ] of [
42- [ 'assets' , [ 'encoded-base' , 'relative-base' , 'runtime-base' , 'url-base' ] ] ,
43- [ 'css' , [ 'lightningcss' ] ] ,
44- [ 'transform-plugin' , [ 'base' ] ] ,
45- ] as const ) {
46- for ( const variant of variants ) {
47- await fs . cp (
48- path . resolve ( tempDir , original ) ,
49- path . resolve ( tempDir , `${ original } __${ variant } ` ) ,
50- { recursive : true } ,
42+ const dedicatedCopyList : Record < string , string [ ] > = {
43+ assets : [ 'encoded-base' , 'relative-base' , 'runtime-base' , 'url-base' ] ,
44+ css : [ 'lightningcss' ] ,
45+ 'transform-plugin' : [ 'base' ] ,
46+ }
47+ const cpPromises = [ ]
48+ for ( const testFile of testFiles ) {
49+ const testName = testFile . match ( PLAYGROUND_NAME_REGEX ) ?. [ 1 ]
50+ const variantName = path . basename ( path . dirname ( testFile ) )
51+ if ( variantName === '__tests__' ) continue
52+ if ( testName && dedicatedCopyList [ testName ] ?. includes ( variantName ) ) {
53+ const srcDir = path . resolve ( import . meta. dirname , testName )
54+ const destDir = path . resolve ( tempDir , `${ testName } __${ variantName } ` )
55+ cpPromises . push (
56+ copyWithFriendlyError ( srcDir , destDir , {
57+ recursive : true ,
58+ filter : filterForPlaygroundCopy ,
59+ } ) ,
5160 )
5261 }
5362 }
63+ await Promise . all ( cpPromises )
5464}
5565
5666export async function teardown ( ) : Promise < void > {
@@ -61,3 +71,24 @@ export async function teardown(): Promise<void> {
6171 } )
6272 }
6373}
74+
75+ function copyWithFriendlyError (
76+ src : string ,
77+ dest : string ,
78+ opts ?: CopyOptions ,
79+ ) : Promise < void > {
80+ return fs . cp ( src , dest , opts ) . catch ( async ( error ) => {
81+ if ( error . code === 'EPERM' && error . syscall === 'symlink' ) {
82+ throw new Error (
83+ 'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.' ,
84+ )
85+ } else {
86+ throw error
87+ }
88+ } )
89+ }
90+
91+ function filterForPlaygroundCopy ( file : string ) : boolean {
92+ file = file . replace ( / \\ / g, '/' )
93+ return ! file . includes ( '__tests__' ) && ! / d i s t (?: \/ | $ ) / . test ( file )
94+ }
0 commit comments