@@ -8,6 +8,9 @@ import util from 'node:util';
88import vm from 'node:vm' ;
99import yaml from 'js-yaml' ;
1010
11+
12+ const UTF8 = { encoding : 'utf-8' } ;
13+
1114/**
1215 * Temporal Test262 runner
1316 *
@@ -66,6 +69,11 @@ import yaml from 'js-yaml';
6669 * is provided, it'll be parsed into a number before evaluation, which makes
6770 * it easier for callers to pass environment variables as-is. NaN values will
6871 * silently be assigned the default value.
72+ * @property {boolean= } updateExpectedFailureFiles Used in local development to
73+ * automatically revise expected-failure files after making code changes that
74+ * fix test failures, removing tests that were expected to fail but now pass
75+ * from the expected-failure files. This option does not add newly failing
76+ * tests to the expected-failure files - this must be done manually.
6977 *
7078 * @param {Options } options Object with the following properties:
7179 * - `polyfillCodeFile: string` - Filename of the Temporal polyfill. Must be a
@@ -94,9 +102,14 @@ import yaml from 'js-yaml';
94102 * is provided, it'll be parsed into a number before evaluation, which makes
95103 * it easier for callers to pass environment variables as-is. NaN values
96104 * will silently be assigned the default value.
105+ * - `updateExpectedFailureFiles`: boolean - Used in local development to
106+ * automatically revise expected-failure files after making code changes that
107+ * fix test failures, removing tests that were expected to fail but now pass
108+ * from the expected-failure files. This option does not add newly failing
109+ * tests to the expected-failure files - this must be done manually.
97110 * @returns {boolean } `true` if all tests completed as expected, `false` if not.
98111 */
99- export default function runTest262 ( { test262Dir, testGlobs, polyfillCodeFile, expectedFailureFiles, timeoutMsecs } ) {
112+ export default function runTest262 ( { test262Dir, testGlobs, polyfillCodeFile, expectedFailureFiles, timeoutMsecs, updateExpectedFailureFiles } ) {
100113
101114 // Default timeout is 2 seconds. Set a longer timeout for running tests under
102115 // a debugger.
@@ -121,7 +134,6 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
121134 // Front matter consists of a YAML document in between /*--- and ---*/
122135 const frontmatterMatcher = / \/ \* - - - \n ( .* ) - - - \* \/ / ms;
123136
124- const UTF8 = { encoding : 'utf-8' } ;
125137 const GLOB_OPTS = { filesOnly : true } ;
126138
127139 // EX_NOINPUT -- An input file (not a system file) did not exist or was not readable.
@@ -201,7 +213,7 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
201213 // e.g. intl402/DateTimeFormat/prototype/format/temporal-objects-resolved-time-zone.js
202214 path . resolve ( testSubdirectory , 'intl402/**/*[tT]emporal*.js' ) ,
203215 // "p*" is a workaround because there is no toTemporalInstant dir at this time
204- path . resolve ( testSubdirectory , 'built-ins/Date/p*/toTemporalInstant/*.js' )
216+ path . resolve ( testSubdirectory , 'built-ins/Date/p*/toTemporalInstant/*.js' )
205217 ] . forEach ( ( defaultGlob ) => globResults . push ( ...globSync ( defaultGlob , GLOB_OPTS ) ) ) ;
206218 }
207219
@@ -356,8 +368,13 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
356368
357369 if ( unexpectedPasses . size > 0 ) {
358370 hasFailures = true ;
359- print ( `\n${ color . yellow . bold ( 'WARNING:' ) } Tests passed unexpectedly; remove them from their respective files?` ) ;
371+ if ( updateExpectedFailureFiles ) {
372+ print ( `\n${ color . yellow . bold ( 'WARNING:' ) } Tests passed unexpectedly; the following tests have been removed from their respective files:` ) ;
373+ } else {
374+ print ( `\n${ color . yellow . bold ( 'WARNING:' ) } Tests passed unexpectedly; remove them from their respective files?` ) ;
375+ }
360376 for ( const [ expectedFailureFile , unexpectedPassesSet ] of unexpectedPasses ) {
377+ if ( updateExpectedFailureFiles ) updateExpectedFailureFile ( expectedFailureFile , unexpectedPassesSet ) ;
361378 print ( ` \u2022 ${ expectedFailureFile } :` ) ;
362379 for ( const unexpectedPass of unexpectedPassesSet ) {
363380 print ( `${ unexpectedPass } ` ) ;
@@ -382,3 +399,11 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
382399 }
383400 return ! hasFailures ;
384401}
402+
403+ function updateExpectedFailureFile ( fileName , expectedFailuresInFile ) {
404+ const linesOnDisk = fs
405+ . readFileSync ( fileName , UTF8 )
406+ . split ( / \r ? \n / g) ;
407+ const output = linesOnDisk . filter ( l => ! expectedFailuresInFile . has ( l ) ) ;
408+ fs . writeFileSync ( fileName , output . join ( '\n' ) , UTF8 ) ;
409+ }
0 commit comments