@@ -96,21 +96,22 @@ function shouldIgnore(name: string, ignore?: Array<string>) {
9696const EXTENSIONS = [ ".js" , ".mjs" , ".ts" , ".tsx" , ".cts" , ".mts" , ".vue" ] ;
9797const JSON_AND_EXTENSIONS = [ ".json" , ...EXTENSIONS ] ;
9898
99- function findFile ( filepath : string , allowJSON ?: boolean ) {
100- const matches = [ ] ;
99+ function checkFile (
100+ loc : string ,
101+ allowJSON : boolean ,
102+ matchedLoc : string | undefined ,
103+ ) {
104+ const ext = path . extname ( loc ) ;
101105 const extensions = allowJSON ? JSON_AND_EXTENSIONS : EXTENSIONS ;
102106
103- for ( const ext of extensions ) {
104- const name = filepath + ext ;
105-
106- if ( fs . existsSync ( name ) ) matches . push ( name ) ;
107+ if ( ! extensions . includes ( ext ) ) {
108+ throw new Error ( `Unsupported input extension: ${ loc } ` ) ;
107109 }
108-
109- if ( matches . length > 1 ) {
110- throw new Error ( `Found conflicting file matches: ${ matches . join ( ", " ) } ` ) ;
110+ if ( ! matchedLoc ) {
111+ return loc ;
112+ } else {
113+ throw new Error ( `Found conflicting file matches: ${ matchedLoc } ,${ loc } ` ) ;
111114 }
112-
113- return matches [ 0 ] ;
114115}
115116
116117function pushTask (
@@ -120,86 +121,128 @@ function pushTask(
120121 suiteName : string ,
121122) {
122123 const taskDirStats = fs . statSync ( taskDir ) ;
123- let actualLoc = findFile ( taskDir + "/input" ) ;
124- let execLoc = findFile ( taskDir + "/exec" ) ;
124+ let actualLoc ,
125+ expectLoc ,
126+ execLoc ,
127+ execLocAlias ,
128+ taskOptsLoc ,
129+ stdoutLoc ,
130+ stderrLoc ,
131+ sourceMapLoc ,
132+ inputSourceMap ;
125133
126- // If neither input nor exec is present it is not a real testcase
127- if ( taskDirStats . isDirectory ( ) && ! actualLoc && ! execLoc ) {
128- if ( fs . readdirSync ( taskDir ) . length > 0 ) {
134+ const taskOpts : TaskOptions = JSON . parse ( JSON . stringify ( suite . options ) ) ;
135+ if ( taskDirStats . isDirectory ( ) ) {
136+ const files = fs . readdirSync ( taskDir ) ;
137+ for ( const file of files ) {
138+ const loc = path . join ( taskDir , file ) ;
139+ const name = path . basename ( file , path . extname ( file ) ) ;
140+
141+ switch ( name ) {
142+ case "input" :
143+ actualLoc = checkFile ( loc , false , actualLoc ) ;
144+ break ;
145+ case "exec" :
146+ execLoc = checkFile ( loc , false , execLoc ) ;
147+ break ;
148+ case "output" :
149+ expectLoc = checkFile ( loc , true , expectLoc ) ;
150+ break ;
151+ case "output.extended" :
152+ expectLoc = checkFile ( loc , true , expectLoc ) ;
153+ break ;
154+ case "options" :
155+ taskOptsLoc = loc ;
156+ Object . assign ( taskOpts , require ( taskOptsLoc ) ) ;
157+ break ;
158+ case "source-map" : {
159+ sourceMapLoc = loc ;
160+ break ;
161+ }
162+ case "input-source-map" :
163+ inputSourceMap = JSON . parse ( readFile ( loc ) ) ;
164+ break ;
165+ }
166+ }
167+ // If neither input nor exec is present it is not a real testcase
168+ if ( files . length > 0 && ! actualLoc && ! execLoc ) {
129169 console . warn ( `Skipped test folder with invalid layout: ${ taskDir } ` ) ;
170+ return ;
130171 }
131- return ;
132- } else if ( ! actualLoc ) {
133- actualLoc = taskDir + "/input.js" ;
134- } else if ( ! execLoc ) {
135- execLoc = taskDir + "/exec.js" ;
136- }
172+ actualLoc ??= taskDir + "/input.js" ;
173+ execLoc ??= taskDir + "/exec.js" ;
174+ expectLoc ??= taskDir + "/output.js" ;
137175
138- const expectLoc =
139- findFile ( taskDir + "/output" , true /* allowJSON */ ) ||
140- findFile ( `${ taskDir } /output.extended` , true ) ||
141- taskDir + "/output.js" ;
142- const stdoutLoc = taskDir + "/stdout.txt" ;
143- const stderrLoc = taskDir + "/stderr.txt" ;
144-
145- const actualLocAlias =
146- suiteName + "/" + taskName + "/" + path . basename ( actualLoc ) ;
147- const expectLocAlias =
148- suiteName + "/" + taskName + "/" + path . basename ( actualLoc ) ;
149- let execLocAlias =
150- suiteName + "/" + taskName + "/" + path . basename ( actualLoc ) ;
151-
152- if ( taskDirStats . isFile ( ) ) {
176+ stdoutLoc = taskDir + "/stdout.txt" ;
177+ stderrLoc = taskDir + "/stderr.txt" ;
178+ } else if ( taskDirStats . isFile ( ) ) {
153179 const ext = path . extname ( taskDir ) ;
154180 if ( EXTENSIONS . indexOf ( ext ) === - 1 ) return ;
155181
156182 execLoc = taskDir ;
157183 execLocAlias = suiteName + "/" + taskName ;
184+ } else {
185+ console . warn ( `Skipped test folder with invalid layout: ${ taskDir } ` ) ;
186+ return ;
158187 }
159188
160- const taskOpts : TaskOptions = JSON . parse ( JSON . stringify ( suite . options ) ) ;
189+ const shouldIgnore = process . env . BABEL_8_BREAKING
190+ ? taskOpts . BABEL_8_BREAKING === false
191+ : taskOpts . BABEL_8_BREAKING === true ;
192+
193+ if ( shouldIgnore ) return ;
194+
195+ function buildTestFile (
196+ loc : string | undefined ,
197+ fileName ?: true | string ,
198+ ) : TestFile {
199+ return {
200+ loc,
201+ code : readFile ( loc ) ,
202+ filename : ! loc
203+ ? undefined
204+ : fileName === true
205+ ? suiteName + "/" + taskName + "/" + path . basename ( loc )
206+ : fileName || undefined ,
207+ } ;
208+ }
161209
162- const taskOptsLoc = tryResolve ( taskDir + "/options" ) ;
163- if ( taskOptsLoc ) Object . assign ( taskOpts , require ( taskOptsLoc ) ) ;
210+ const sourceMapFile = buildTestFile ( sourceMapLoc , true ) ;
211+ // TODO: code should not be a object
212+ sourceMapFile . code &&= JSON . parse ( sourceMapFile . code ) ;
164213
165214 const test : Test = {
166215 taskDir,
167216 optionsDir : taskOptsLoc ? path . dirname ( taskOptsLoc ) : null ,
168217 title : humanize ( taskName , true ) ,
169- disabled :
170- taskName [ 0 ] === "." ||
171- ( process . env . BABEL_8_BREAKING
172- ? taskOpts . BABEL_8_BREAKING === false
173- : taskOpts . BABEL_8_BREAKING === true ) ,
218+ disabled : taskName [ 0 ] === "." ,
174219 options : taskOpts ,
175220 doNotSetSourceType : taskOpts . DO_NOT_SET_SOURCE_TYPE ,
176221 externalHelpers :
177222 taskOpts . externalHelpers ??
178223 ! ! tryResolve ( "@babel/plugin-external-helpers" ) ,
179224 validateLogs : taskOpts . validateLogs ,
180225 ignoreOutput : taskOpts . ignoreOutput ,
181- stdout : { loc : stdoutLoc , code : readFile ( stdoutLoc ) } ,
182- stderr : { loc : stderrLoc , code : readFile ( stderrLoc ) } ,
183- exec : {
184- loc : execLoc ,
185- code : readFile ( execLoc ) ,
186- filename : execLocAlias ,
187- } ,
188- actual : {
189- loc : actualLoc ,
190- code : readFile ( actualLoc ) ,
191- filename : actualLocAlias ,
192- } ,
193- expect : {
194- loc : expectLoc ,
195- code : readFile ( expectLoc ) ,
196- filename : expectLocAlias ,
197- } ,
198- sourceMap : undefined ,
199- sourceMapFile : undefined ,
200- inputSourceMap : undefined ,
226+ stdout : buildTestFile ( stdoutLoc ) ,
227+ stderr : buildTestFile ( stderrLoc ) ,
228+ exec : buildTestFile ( execLoc , execLocAlias ) ,
229+ actual : buildTestFile ( actualLoc , true ) ,
230+ expect : buildTestFile ( expectLoc , true ) ,
231+ sourceMap : sourceMapFile . code ,
232+ sourceMapFile,
233+ inputSourceMap,
201234 } ;
202235
236+ if (
237+ test . exec . code &&
238+ test . actual . code &&
239+ path . extname ( execLoc ) !== path . extname ( actualLoc )
240+ ) {
241+ throw new Error (
242+ `Input file extension should match exec file extension: ${ execLoc } , ${ actualLoc } ` ,
243+ ) ;
244+ }
245+
203246 delete taskOpts . BABEL_8_BREAKING ;
204247 delete taskOpts . DO_NOT_SET_SOURCE_TYPE ;
205248
@@ -241,29 +284,8 @@ function pushTask(
241284 delete taskOpts . os ;
242285 }
243286
244- // traceur checks
245-
246- if ( test . exec . code . indexOf ( "// Async." ) >= 0 ) {
247- return ;
248- }
249-
250287 suite . tests . push ( test ) ;
251288
252- const sourceMapLoc = taskDir + "/source-map.json" ;
253- if ( fs . existsSync ( sourceMapLoc ) ) {
254- test . sourceMap = JSON . parse ( readFile ( sourceMapLoc ) ) ;
255- }
256- test . sourceMapFile = {
257- loc : sourceMapLoc ,
258- code : test . sourceMap ,
259- filename : "" ,
260- } ;
261-
262- const inputMapLoc = taskDir + "/input-source-map.json" ;
263- if ( fs . existsSync ( inputMapLoc ) ) {
264- test . inputSourceMap = JSON . parse ( readFile ( inputMapLoc ) ) ;
265- }
266-
267289 if ( taskOpts . throws ) {
268290 if ( test . expect . code ) {
269291 throw new Error (
@@ -396,8 +418,8 @@ export function resolveOptionPluginOrPreset(
396418 return options ;
397419}
398420
399- export default function get ( entryLoc : string ) : Array < Suite > {
400- const suites = [ ] ;
421+ export default function get ( entryLoc : string ) {
422+ const suites : Suite [ ] = [ ] ;
401423
402424 let rootOpts : TaskOptions = { } ;
403425 const rootOptsLoc = tryResolve ( entryLoc + "/options" ) ;
@@ -406,9 +428,9 @@ export default function get(entryLoc: string): Array<Suite> {
406428 for ( const suiteName of fs . readdirSync ( entryLoc ) ) {
407429 if ( shouldIgnore ( suiteName ) ) continue ;
408430
409- const suite = {
431+ const suite : Suite = {
410432 options : { ...rootOpts } ,
411- tests : [ ] as Test [ ] ,
433+ tests : [ ] ,
412434 title : humanize ( suiteName ) ,
413435 filename : entryLoc + "/" + suiteName ,
414436 } ;
@@ -447,12 +469,16 @@ export function multiple(entryLoc: string, ignore?: Array<string>) {
447469 return categories ;
448470}
449471
450- export function readFile ( filename : string ) {
451- if ( fs . existsSync ( filename ) ) {
452- let file = fs . readFileSync ( filename , "utf8" ) . trimRight ( ) ;
453- file = file . replace ( / \r \n / g, "\n" ) ;
454- return file ;
455- } else {
456- return "" ;
472+ export function readFile ( filename : string | undefined ) {
473+ try {
474+ if ( filename === undefined ) {
475+ return "" ;
476+ }
477+ return fs . readFileSync ( filename , "utf8" ) . trimRight ( ) ;
478+ } catch ( e ) {
479+ if ( e . code === "ENOENT" ) {
480+ return "" ;
481+ }
482+ throw e ;
457483 }
458484}
0 commit comments