@@ -15,6 +15,7 @@ const { DD_MAJOR } = require('../../../version')
1515
1616const testStartCh = channel ( 'ci:playwright:test:start' )
1717const testFinishCh = channel ( 'ci:playwright:test:finish' )
18+ const testSkipCh = channel ( 'ci:playwright:test:skip' )
1819
1920const testSessionStartCh = channel ( 'ci:playwright:session:start' )
2021const testSessionFinishCh = channel ( 'ci:playwright:session:finish' )
@@ -285,7 +286,12 @@ function getTestFullname (test) {
285286 return names . join ( ' ' )
286287}
287288
288- function testBeginHandler ( test , browserName , isMainProcess ) {
289+ function shouldFinishTestSuite ( testSuiteAbsolutePath ) {
290+ const remainingTests = remainingTestsByFile [ testSuiteAbsolutePath ]
291+ return ! remainingTests . length || remainingTests . every ( test => test . expectedStatus === 'skipped' )
292+ }
293+
294+ function testBeginHandler ( test , browserName , shouldCreateTestSpan ) {
289295 const {
290296 _requireFile : testSuiteAbsolutePath ,
291297 location : {
@@ -297,6 +303,10 @@ function testBeginHandler (test, browserName, isMainProcess) {
297303 if ( _type === 'beforeAll' || _type === 'afterAll' ) {
298304 return
299305 }
306+ // this means that a skipped test is being handled
307+ if ( ! remainingTestsByFile [ testSuiteAbsolutePath ] . length ) {
308+ return
309+ }
300310
301311 const isNewTestSuite = ! startedSuites . includes ( testSuiteAbsolutePath )
302312
@@ -313,7 +323,7 @@ function testBeginHandler (test, browserName, isMainProcess) {
313323 }
314324
315325 // this handles tests that do not go through the worker process (because they're skipped)
316- if ( isMainProcess ) {
326+ if ( shouldCreateTestSpan ) {
317327 const testName = getTestFullname ( test )
318328 const testCtx = {
319329 testName,
@@ -328,7 +338,7 @@ function testBeginHandler (test, browserName, isMainProcess) {
328338 }
329339}
330340
331- function testEndHandler ( test , annotations , testStatus , error , isTimeout , isMainProcess ) {
341+ function testEndHandler ( test , annotations , testStatus , error , isTimeout , shouldCreateTestSpan ) {
332342 const { _requireFile : testSuiteAbsolutePath , results, _type } = test
333343
334344 let annotationTags
@@ -368,31 +378,34 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
368378 }
369379
370380 // this handles tests that do not go through the worker process (because they're skipped)
371- if ( isMainProcess ) {
381+ if ( shouldCreateTestSpan ) {
372382 const testResult = results . at ( - 1 )
373383 const testCtx = testToCtx . get ( test )
374384 const isAtrRetry = testResult ?. retry > 0 &&
375385 isFlakyTestRetriesEnabled &&
376386 ! test . _ddIsAttemptToFix &&
377387 ! test . _ddIsEfdRetry
378- testFinishCh . publish ( {
379- testStatus,
380- steps : testResult ?. steps || [ ] ,
381- isRetry : testResult ?. retry > 0 ,
382- error,
383- extraTags : annotationTags ,
384- isNew : test . _ddIsNew ,
385- isAttemptToFix : test . _ddIsAttemptToFix ,
386- isAttemptToFixRetry : test . _ddIsAttemptToFixRetry ,
387- isQuarantined : test . _ddIsQuarantined ,
388- isEfdRetry : test . _ddIsEfdRetry ,
389- hasFailedAllRetries : test . _ddHasFailedAllRetries ,
390- hasPassedAttemptToFixRetries : test . _ddHasPassedAttemptToFixRetries ,
391- hasFailedAttemptToFixRetries : test . _ddHasFailedAttemptToFixRetries ,
392- isAtrRetry,
393- isModified : test . _ddIsModified ,
394- ...testCtx . currentStore
395- } )
388+ // if there is no testCtx, the skipped test will be created later
389+ if ( testCtx ) {
390+ testFinishCh . publish ( {
391+ testStatus,
392+ steps : testResult ?. steps || [ ] ,
393+ isRetry : testResult ?. retry > 0 ,
394+ error,
395+ extraTags : annotationTags ,
396+ isNew : test . _ddIsNew ,
397+ isAttemptToFix : test . _ddIsAttemptToFix ,
398+ isAttemptToFixRetry : test . _ddIsAttemptToFixRetry ,
399+ isQuarantined : test . _ddIsQuarantined ,
400+ isEfdRetry : test . _ddIsEfdRetry ,
401+ hasFailedAllRetries : test . _ddHasFailedAllRetries ,
402+ hasPassedAttemptToFixRetries : test . _ddHasPassedAttemptToFixRetries ,
403+ hasFailedAttemptToFixRetries : test . _ddHasFailedAttemptToFixRetries ,
404+ isAtrRetry,
405+ isModified : test . _ddIsModified ,
406+ ...testCtx . currentStore
407+ } )
408+ }
396409 }
397410
398411 if ( testSuiteToTestStatuses . has ( testSuiteAbsolutePath ) ) {
@@ -410,8 +423,24 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
410423 . filter ( currentTest => currentTest !== test )
411424 }
412425
413- // Last test, we finish the suite
414- if ( ! remainingTestsByFile [ testSuiteAbsolutePath ] . length ) {
426+ if ( shouldFinishTestSuite ( testSuiteAbsolutePath ) ) {
427+ const skippedTests = remainingTestsByFile [ testSuiteAbsolutePath ]
428+ . filter ( test => test . expectedStatus === 'skipped' )
429+
430+ skippedTests . forEach ( test => {
431+ testSkipCh . publish ( {
432+ testName : getTestFullname ( test ) ,
433+ testSuiteAbsolutePath : test . _requireFile ,
434+ testSourceLine : test . location . line ,
435+ browserName : 'chromium' , // TODO: REMOVE HARDCODE
436+ isNew : test . _ddIsNew ,
437+ isDisabled : test . _ddIsDisabled ,
438+ isModified : test . _ddIsModified ,
439+ isQuarantined : test . _ddIsQuarantined
440+ } )
441+ } )
442+ remainingTestsByFile [ testSuiteAbsolutePath ] = [ ]
443+
415444 const testStatuses = testSuiteToTestStatuses . get ( testSuiteAbsolutePath )
416445 let testSuiteStatus = 'pass'
417446 if ( testStatuses . includes ( 'fail' ) ) {
@@ -455,21 +484,23 @@ function dispatcherHook (dispatcherExport) {
455484 const { test } = dispatcher . _testById . get ( params . testId )
456485 const projects = getProjectsFromDispatcher ( dispatcher )
457486 const browser = getBrowserNameFromProjects ( projects , test )
458- testBeginHandler ( test , browser , true )
487+ const shouldCreateTestSpan = test . expectedStatus === 'skipped'
488+ testBeginHandler ( test , browser , shouldCreateTestSpan )
459489 } else if ( method === 'testEnd' ) {
460490 const { test } = dispatcher . _testById . get ( params . testId )
461491
462492 const { results } = test
463493 const testResult = results . at ( - 1 )
464494
465495 const isTimeout = testResult . status === 'timedOut'
496+ const shouldCreateTestSpan = test . expectedStatus === 'skipped'
466497 testEndHandler (
467498 test ,
468499 params . annotations ,
469500 STATUS_TO_TEST_STATUS [ testResult . status ] ,
470501 testResult . error ,
471502 isTimeout ,
472- true
503+ shouldCreateTestSpan
473504 )
474505 }
475506 } )
@@ -489,13 +520,22 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
489520 const test = getTestByTestId ( dispatcher , testId )
490521 const projects = getProjectsFromDispatcher ( dispatcher )
491522 const browser = getBrowserNameFromProjects ( projects , test )
492- testBeginHandler ( test , browser , false )
523+ const shouldCreateTestSpan = test . expectedStatus === 'skipped'
524+ testBeginHandler ( test , browser , shouldCreateTestSpan )
493525 } )
494526 worker . on ( 'testEnd' , ( { testId, status, errors, annotations } ) => {
495527 const test = getTestByTestId ( dispatcher , testId )
496528
497529 const isTimeout = status === 'timedOut'
498- testEndHandler ( test , annotations , STATUS_TO_TEST_STATUS [ status ] , errors && errors [ 0 ] , isTimeout , false )
530+ const shouldCreateTestSpan = test . expectedStatus === 'skipped'
531+ testEndHandler (
532+ test ,
533+ annotations ,
534+ STATUS_TO_TEST_STATUS [ status ] ,
535+ errors && errors [ 0 ] ,
536+ isTimeout ,
537+ shouldCreateTestSpan
538+ )
499539 const testResult = test . results . at ( - 1 )
500540 const isAtrRetry = testResult ?. retry > 0 &&
501541 isFlakyTestRetriesEnabled &&
@@ -625,6 +665,9 @@ function runAllTestsWrapper (runAllTests, playwrightVersion) {
625665
626666 let runAllTestsReturn = await runAllTests . apply ( this , arguments )
627667
668+ // Tests that have only skipped tests may reach this point
669+ // Skipped tests may or may not go through `testBegin` or `testEnd`
670+ // depending on the playwright configuration
628671 Object . values ( remainingTestsByFile ) . forEach ( tests => {
629672 // `tests` should normally be empty, but if it isn't,
630673 // there were tests that did not go through `testBegin` or `testEnd`,
@@ -1007,6 +1050,10 @@ addHook({
10071050 const stepInfoByStepId = { }
10081051
10091052 shimmer . wrap ( workerPackage . WorkerMain . prototype , '_runTest' , _runTest => async function ( test ) {
1053+ if ( test . expectedStatus === 'skipped' ) {
1054+ console . log ( 'skipped test' , test . title )
1055+ return _runTest . apply ( this , arguments )
1056+ }
10101057 steps = [ ]
10111058
10121059 const {
0 commit comments