@@ -125,55 +125,63 @@ export async function runTest(test: Test, runner: VitestRunner) {
125125
126126 setCurrentTest ( test )
127127
128- const retry = test . retry || 1
129- for ( let retryCount = 0 ; retryCount < retry ; retryCount ++ ) {
130- let beforeEachCleanups : HookCleanupCallback [ ] = [ ]
131- try {
132- await runner . onBeforeTryTest ?.( test , retryCount )
128+ const repeats = typeof test . repeats === 'number' ? test . repeats : 1
133129
134- beforeEachCleanups = await callSuiteHook ( test . suite , test , 'beforeEach' , runner , [ test . context , test . suite ] )
130+ for ( let repeatCount = 0 ; repeatCount < repeats ; repeatCount ++ ) {
131+ const retry = test . retry || 1
135132
136- test . result . retryCount = retryCount
133+ for ( let retryCount = 0 ; retryCount < retry ; retryCount ++ ) {
134+ let beforeEachCleanups : HookCleanupCallback [ ] = [ ]
135+ try {
136+ await runner . onBeforeTryTest ?.( test , { retry : retryCount , repeats : repeatCount } )
137137
138- if ( runner . runTest ) {
139- await runner . runTest ( test )
140- }
141- else {
142- const fn = getFn ( test )
143- if ( ! fn )
144- throw new Error ( 'Test function is not found. Did you add it using `setFn`?' )
145- await fn ( )
146- }
138+ test . result . retryCount = retryCount
139+ test . result . repeatCount = repeatCount
147140
148- // some async expect will be added to this array, in case user forget to await theme
149- if ( test . promises ) {
150- const result = await Promise . allSettled ( test . promises )
151- const errors = result . map ( r => r . status === 'rejected' ? r . reason : undefined ) . filter ( Boolean )
152- if ( errors . length )
153- throw errors
154- }
141+ beforeEachCleanups = await callSuiteHook ( test . suite , test , 'beforeEach' , runner , [ test . context , test . suite ] )
155142
156- await runner . onAfterTryTest ?.( test , retryCount )
143+ if ( runner . runTest ) {
144+ await runner . runTest ( test )
145+ }
146+ else {
147+ const fn = getFn ( test )
148+ if ( ! fn )
149+ throw new Error ( 'Test function is not found. Did you add it using `setFn`?' )
150+ await fn ( )
151+ }
157152
158- test . result . state = 'pass'
159- }
160- catch ( e ) {
161- failTask ( test . result , e )
162- }
153+ // some async expect will be added to this array, in case user forget to await theme
154+ if ( test . promises ) {
155+ const result = await Promise . allSettled ( test . promises )
156+ const errors = result . map ( r => r . status === 'rejected' ? r . reason : undefined ) . filter ( Boolean )
157+ if ( errors . length )
158+ throw errors
159+ }
163160
164- try {
165- await callSuiteHook ( test . suite , test , 'afterEach' , runner , [ test . context , test . suite ] )
166- await callCleanupHooks ( beforeEachCleanups )
167- }
168- catch ( e ) {
169- failTask ( test . result , e )
170- }
161+ await runner . onAfterTryTest ?.( test , { retry : retryCount , repeats : repeatCount } )
171162
172- if ( test . result . state === 'pass' )
173- break
163+ if ( ! test . repeats )
164+ test . result . state = 'pass'
165+ else if ( test . repeats && retry === retryCount )
166+ test . result . state = 'pass'
167+ }
168+ catch ( e ) {
169+ failTask ( test . result , e )
170+ }
174171
175- // update retry info
176- updateTask ( test , runner )
172+ try {
173+ await callSuiteHook ( test . suite , test , 'afterEach' , runner , [ test . context , test . suite ] )
174+ await callCleanupHooks ( beforeEachCleanups )
175+ }
176+ catch ( e ) {
177+ failTask ( test . result , e )
178+ }
179+
180+ if ( test . result . state === 'pass' )
181+ break
182+ // update retry info
183+ updateTask ( test , runner )
184+ }
177185 }
178186
179187 if ( test . result . state === 'fail' )
@@ -291,30 +299,30 @@ export async function runSuite(suite: Suite, runner: VitestRunner) {
291299 catch ( e ) {
292300 failTask ( suite . result , e )
293301 }
294- }
295302
296- suite . result . duration = now ( ) - start
297-
298- if ( suite . mode === 'run' ) {
299- if ( ! hasTests ( suite ) ) {
300- suite . result . state = 'fail'
301- if ( ! suite . result . error ) {
302- const error = processError ( new Error ( `No test found in suite ${ suite . name } ` ) )
303- suite . result . error = error
304- suite . result . errors = [ error ]
303+ if ( suite . mode === 'run' ) {
304+ if ( ! hasTests ( suite ) ) {
305+ suite . result . state = 'fail'
306+ if ( ! suite . result . error ) {
307+ const error = processError ( new Error ( `No test found in suite ${ suite . name } ` ) )
308+ suite . result . error = error
309+ suite . result . errors = [ error ]
310+ }
311+ }
312+ else if ( hasFailed ( suite ) ) {
313+ suite . result . state = 'fail'
314+ }
315+ else {
316+ suite . result . state = 'pass'
305317 }
306318 }
307- else if ( hasFailed ( suite ) ) {
308- suite . result . state = 'fail'
309- }
310- else {
311- suite . result . state = 'pass'
312- }
313- }
314319
315- await runner . onAfterRunSuite ?. ( suite )
320+ updateTask ( suite , runner )
316321
317- updateTask ( suite , runner )
322+ suite . result . duration = now ( ) - start
323+
324+ await runner . onAfterRunSuite ?.( suite )
325+ }
318326}
319327
320328async function runSuiteChild ( c : Task , runner : VitestRunner ) {
0 commit comments