@@ -4,21 +4,10 @@ const { performance } = require('perf_hooks');
44
55global . currentSpec = null ;
66
7- /**
8- * Names of tests that fail randomly and are considered flaky. These tests will be retried
9- * a number of times to reduce the chance of false negatives. The test name must be the same
10- * as the one displayed in the CI log test output.
11- */
12- const flakyTests = [ ] ;
13-
147/** The minimum execution time in seconds for a test to be considered slow. */
158const slowTestLimit = 2 ;
169
17- /** The number of times to retry a flaky test. */
18- const retries = 5 ;
19-
2010const timerMap = { } ;
21- const retryMap = { } ;
2211const duplicates = [ ] ;
2312class CurrentSpecReporter {
2413 specStarted ( spec ) {
@@ -52,61 +41,64 @@ global.displayTestStats = function() {
5241 console . warn ( 'Duplicate spec: ' + spec ) ;
5342 } ) ;
5443 console . log ( '\n' ) ;
55- Object . keys ( retryMap ) . forEach ( ( spec ) => {
56- console . warn ( `Flaky test: ${ spec } failed ${ retryMap [ spec ] } times` ) ;
57- } ) ;
58- console . log ( '\n' ) ;
5944} ;
6045
61- global . retryFlakyTests = function ( ) {
62- const originalSpecConstructor = jasmine . Spec ;
63-
64- jasmine . Spec = function ( attrs ) {
65- const spec = new originalSpecConstructor ( attrs ) ;
66- const originalTestFn = spec . queueableFn . fn ;
67- const runOriginalTest = ( ) => {
68- if ( originalTestFn . length == 0 ) {
69- // handle async testing
70- return originalTestFn ( ) ;
71- } else {
72- // handle done() callback
46+ /**
47+ * Transitional compatibility shim for Jasmine 5.
48+ *
49+ * Jasmine 5 throws when a test or hook function uses both `async` and a `done` callback:
50+ * "An asynchronous before/it/after function was defined with the async keyword
51+ * but also took a done callback."
52+ *
53+ * Many existing tests use `async (done) => { ... done(); }`. This wrapper converts
54+ * those to promise-based functions by intercepting the `done` callback and resolving
55+ * a promise instead, so Jasmine sees a plain async function.
56+ *
57+ * To remove this shim, convert each file below so that tests and hooks use plain
58+ * `async () => {}` without a `done` parameter, then remove the file from this list.
59+ * Once the list is empty, delete this function and its call in `helper.js`.
60+ */
61+ global . normalizeAsyncTests = function ( ) {
62+ function wrapDoneCallback ( fn ) {
63+ if ( fn . length > 0 ) {
64+ return function ( ) {
7365 return new Promise ( ( resolve ) => {
74- originalTestFn ( resolve ) ;
66+ fn . call ( this , resolve ) ;
7567 } ) ;
76- }
77- } ;
78- spec . queueableFn . fn = async function ( ) {
79- const isFlaky = flakyTests . includes ( spec . result . fullName ) ;
80- const runs = isFlaky ? retries : 1 ;
81- let exceptionCaught ;
82- let returnValue ;
68+ } ;
69+ }
70+ return fn ;
71+ }
8372
84- for ( let i = 0 ; i < runs ; ++ i ) {
85- spec . result . failedExpectations = [ ] ;
86- returnValue = undefined ;
87- exceptionCaught = undefined ;
88- try {
89- returnValue = await runOriginalTest ( ) ;
90- } catch ( exception ) {
91- exceptionCaught = exception ;
92- }
93- const failed = ! spec . markedPending &&
94- ( exceptionCaught || spec . result . failedExpectations . length != 0 ) ;
95- if ( ! failed ) {
96- break ;
97- }
98- if ( isFlaky ) {
99- retryMap [ spec . result . fullName ] = ( retryMap [ spec . result . fullName ] || 0 ) + 1 ;
100- await global . afterEachFn ( ) ;
101- }
102- }
103- if ( exceptionCaught ) {
104- throw exceptionCaught ;
105- }
106- return returnValue ;
107- } ;
73+ // Wrap it() specs
74+ const originalSpecConstructor = jasmine . Spec ;
75+ jasmine . Spec = function ( attrs ) {
76+ const spec = new originalSpecConstructor ( attrs ) ;
77+ spec . queueableFn . fn = wrapDoneCallback ( spec . queueableFn . fn ) ;
10878 return spec ;
10979 } ;
110- }
80+
81+ // Wrap beforeEach/afterEach/beforeAll/afterAll
82+ const originalBeforeEach = jasmine . Suite . prototype . beforeEach ;
83+ jasmine . Suite . prototype . beforeEach = function ( fn ) {
84+ fn . fn = wrapDoneCallback ( fn . fn ) ;
85+ return originalBeforeEach . call ( this , fn ) ;
86+ } ;
87+ const originalAfterEach = jasmine . Suite . prototype . afterEach ;
88+ jasmine . Suite . prototype . afterEach = function ( fn ) {
89+ fn . fn = wrapDoneCallback ( fn . fn ) ;
90+ return originalAfterEach . call ( this , fn ) ;
91+ } ;
92+ const originalBeforeAll = jasmine . Suite . prototype . beforeAll ;
93+ jasmine . Suite . prototype . beforeAll = function ( fn ) {
94+ fn . fn = wrapDoneCallback ( fn . fn ) ;
95+ return originalBeforeAll . call ( this , fn ) ;
96+ } ;
97+ const originalAfterAll = jasmine . Suite . prototype . afterAll ;
98+ jasmine . Suite . prototype . afterAll = function ( fn ) {
99+ fn . fn = wrapDoneCallback ( fn . fn ) ;
100+ return originalAfterAll . call ( this , fn ) ;
101+ } ;
102+ } ;
111103
112104module . exports = CurrentSpecReporter ;
0 commit comments