@@ -2594,7 +2594,7 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
25942594 } )
25952595 } )
25962596
2597- it ( 'retries flaky tests and sets exit code to 0 as long as one attempt passes' , ( done ) => {
2597+ it ( 'retries flaky tests and sets exit code to 0 as long as one attempt passes' , async ( ) => {
25982598 receiver . setInfoResponse ( { endpoints : [ '/evp_proxy/v4' ] } )
25992599 // Tests from ci-visibility/test/occasionally-failing-test will be considered new
26002600 receiver . setKnownTests ( { jest : { } } )
@@ -2617,6 +2617,8 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
26172617
26182618 const testSession = events . find ( event => event . type === 'test_session_end' ) . content
26192619 assert . strictEqual ( testSession . meta [ TEST_EARLY_FLAKE_ENABLED ] , 'true' )
2620+ // Session is passed because at least one retry of the new flaky test passes
2621+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'pass' )
26202622
26212623 const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
26222624
@@ -2636,14 +2638,16 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
26362638 } )
26372639 } )
26382640
2641+ let testOutput = ''
26392642 childProcess = exec (
26402643 'node ./node_modules/jest/bin/jest --config config-jest.js' ,
26412644 {
26422645 cwd,
26432646 env : {
26442647 ...getCiVisEvpProxyConfig ( receiver . port ) ,
2645- TESTS_TO_RUN : '**/ci-visibility/test-early-flake-detection/occasionally-failing-test*'
2646- } ,
2648+ TESTS_TO_RUN : '**/ci-visibility/test-early-flake-detection/occasionally-failing-test*' ,
2649+ SHOULD_CHECK_RESULTS : '1'
2650+ }
26472651 }
26482652 )
26492653
@@ -2654,13 +2658,11 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
26542658 testOutput += chunk . toString ( )
26552659 } )
26562660
2657- childProcess . on ( 'exit' , ( exitCode ) => {
2658- assert . match ( testOutput , / 2 f a i l e d , 2 p a s s e d / )
2659- assert . strictEqual ( exitCode , 0 )
2660- eventsPromise . then ( ( ) => {
2661- done ( )
2662- } ) . catch ( done )
2663- } )
2661+ const [ [ exitCode ] ] = await Promise . all ( [ once ( childProcess , 'exit' ) , eventsPromise ] )
2662+
2663+ assert . match ( testOutput , / 2 f a i l e d , 2 p a s s e d / )
2664+ // Exit code is 0 because at least one retry of the new flaky test passes
2665+ assert . strictEqual ( exitCode , 0 )
26642666 } )
26652667
26662668 // resetting snapshot state logic only works in latest versions
@@ -2694,6 +2696,8 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
26942696
26952697 const testSession = events . find ( event => event . type === 'test_session_end' ) . content
26962698 assert . strictEqual ( testSession . meta [ TEST_EARLY_FLAKE_ENABLED ] , 'true' )
2699+ // Session is passed because at least one retry of each new flaky test passes
2700+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'pass' )
26972701
26982702 const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
26992703 // 6 tests, 4 of which are new: 4*(1 test + 3 retries) + 2*(1 test) = 18
@@ -2720,14 +2724,16 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
27202724 env : {
27212725 ...getCiVisEvpProxyConfig ( receiver . port ) ,
27222726 TESTS_TO_RUN : 'ci-visibility/test-early-flake-detection/jest-snapshot' ,
2723- CI : '1' // needs to be run as CI so snapshots are not written
2724- } ,
2727+ CI : '1' , // needs to be run as CI so snapshots are not written
2728+ SHOULD_CHECK_RESULTS : '1'
2729+ }
27252730 } )
27262731
27272732 const [ [ exitCode ] ] = await Promise . all ( [
27282733 once ( childProcess , 'exit' ) ,
27292734 eventsPromise
27302735 ] )
2736+ // Exit code is 0 because at least one retry of each new flaky test passes
27312737 assert . strictEqual ( exitCode , 0 )
27322738 } )
27332739
@@ -2757,6 +2763,8 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
27572763
27582764 const testSession = events . find ( event => event . type === 'test_session_end' ) . content
27592765 assert . strictEqual ( testSession . meta [ TEST_EARLY_FLAKE_ENABLED ] , 'true' )
2766+ // Session is passed because at least one retry of the new flaky test passes
2767+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'pass' )
27602768
27612769 const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
27622770 // 1 new test
@@ -2779,14 +2787,16 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
27792787 env : {
27802788 ...getCiVisEvpProxyConfig ( receiver . port ) ,
27812789 TESTS_TO_RUN : 'ci-visibility/test-early-flake-detection/jest-image-snapshot' ,
2782- CI : '1'
2783- } ,
2790+ CI : '1' ,
2791+ SHOULD_CHECK_RESULTS : '1'
2792+ }
27842793 } )
27852794
27862795 const [ [ exitCode ] ] = await Promise . all ( [
27872796 once ( childProcess , 'exit' ) ,
27882797 eventsPromise
27892798 ] )
2799+ // Exit code is 0 because at least one retry of the new flaky test passes
27902800 assert . strictEqual ( exitCode , 0 )
27912801 } )
27922802
@@ -4820,8 +4830,11 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
48204830
48214831 if ( isQuarantining ) {
48224832 assert . strictEqual ( testSession . meta [ TEST_MANAGEMENT_ENABLED ] , 'true' )
4833+ // test session is passed even though a test fails because the test is quarantined
4834+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'pass' )
48234835 } else {
48244836 assert . ok ( ! ( 'TEST_MANAGEMENT_ENABLED' in testSession . meta ) )
4837+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'fail' )
48254838 }
48264839
48274840 const resourceNames = tests . map ( span => span . resource )
@@ -4855,7 +4868,7 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
48554868 }
48564869 } )
48574870
4858- const runQuarantineTest = ( done , isQuarantining , extraEnvVars = { } , isParallel = false ) => {
4871+ const runQuarantineTest = async ( isQuarantining , extraEnvVars = { } , isParallel = false ) => {
48594872 let stdout = ''
48604873 const testAssertionsPromise = getTestAssertions ( isQuarantining , isParallel )
48614874
@@ -4868,7 +4881,7 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
48684881 TESTS_TO_RUN : 'test-management/test-quarantine-1' ,
48694882 SHOULD_CHECK_RESULTS : '1' ,
48704883 ...extraEnvVars
4871- } ,
4884+ }
48724885 }
48734886 )
48744887
@@ -4877,44 +4890,40 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
48774890 stdout += chunk . toString ( )
48784891 } )
48794892
4880- childProcess . on ( 'exit' , exitCode => {
4881- testAssertionsPromise . then ( ( ) => {
4882- // it runs regardless of quarantine status
4883- assert . match ( stdout , / I a m r u n n i n g w h e n q u a r a n t i n e d / )
4884- if ( isQuarantining ) {
4885- // even though a test fails, the exit code is 0 because the test is quarantined
4886- assert . strictEqual ( exitCode , 0 )
4887- } else {
4888- assert . strictEqual ( exitCode , 1 )
4889- }
4890- done ( )
4891- } ) . catch ( done )
4892- } )
4893+ const [ [ exitCode ] ] = await Promise . all ( [ once ( childProcess , 'exit' ) , testAssertionsPromise ] )
4894+
4895+ // it runs regardless of quarantine status
4896+ assert . match ( stdout , / I a m r u n n i n g w h e n q u a r a n t i n e d / )
4897+ if ( isQuarantining ) {
4898+ // even though a test fails, the exit code is 0 because the test is quarantined
4899+ assert . strictEqual ( exitCode , 0 )
4900+ } else {
4901+ assert . strictEqual ( exitCode , 1 )
4902+ }
48934903 }
48944904
4895- it ( 'can quarantine tests' , ( done ) => {
4905+ it ( 'can quarantine tests' , async ( ) => {
48964906 receiver . setSettings ( { test_management : { enabled : true } } )
48974907
4898- runQuarantineTest ( done , true )
4908+ await runQuarantineTest ( true )
48994909 } )
49004910
4901- it ( 'fails if quarantine is not enabled' , ( done ) => {
4911+ it ( 'fails if quarantine is not enabled' , async ( ) => {
49024912 receiver . setSettings ( { test_management : { enabled : false } } )
49034913
4904- runQuarantineTest ( done , false )
4914+ await runQuarantineTest ( false )
49054915 } )
49064916
4907- it ( 'does not enable quarantine tests if DD_TEST_MANAGEMENT_ENABLED is set to false' , ( done ) => {
4917+ it ( 'does not enable quarantine tests if DD_TEST_MANAGEMENT_ENABLED is set to false' , async ( ) => {
49084918 receiver . setSettings ( { test_management : { enabled : true } } )
49094919
4910- runQuarantineTest ( done , false , { DD_TEST_MANAGEMENT_ENABLED : '0' } )
4920+ await runQuarantineTest ( false , { DD_TEST_MANAGEMENT_ENABLED : '0' } )
49114921 } )
49124922
4913- it ( 'can quarantine in parallel mode' , ( done ) => {
4923+ it ( 'can quarantine in parallel mode' , async ( ) => {
49144924 receiver . setSettings ( { test_management : { enabled : true } } )
49154925
4916- runQuarantineTest (
4917- done ,
4926+ await runQuarantineTest (
49184927 true ,
49194928 {
49204929 // we need to run more than 1 suite for parallel mode to kick in
@@ -4924,6 +4933,73 @@ describe(`jest@${JEST_VERSION} commonJS`, () => {
49244933 true
49254934 )
49264935 } )
4936+
4937+ it ( 'fails if a non-quarantined test fails even when a quarantined test also fails' , async ( ) => {
4938+ receiver . setSettings ( { test_management : { enabled : true } } )
4939+
4940+ // Only quarantine one of the failing tests, leaving another failing test non-quarantined
4941+ receiver . setTestManagementTests ( {
4942+ jest : {
4943+ suites : {
4944+ 'ci-visibility/test-management/test-partial-quarantine.js' : {
4945+ tests : {
4946+ 'partial quarantine tests quarantined failing test' : {
4947+ properties : {
4948+ quarantined : true
4949+ }
4950+ }
4951+ // Note: 'partial quarantine tests non-quarantined failing test' is NOT quarantined
4952+ }
4953+ }
4954+ }
4955+ }
4956+ } )
4957+
4958+ const testAssertionsPromise = receiver
4959+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
4960+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
4961+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
4962+ const testSession = events . find ( event => event . type === 'test_session_end' ) . content
4963+
4964+ // Session should be marked as failed because a non-quarantined test failed
4965+ assert . strictEqual ( testSession . meta [ TEST_MANAGEMENT_ENABLED ] , 'true' )
4966+ assert . strictEqual ( testSession . meta [ TEST_STATUS ] , 'fail' )
4967+
4968+ // Verify the quarantined test has the quarantine tag
4969+ const quarantinedTest = tests . find (
4970+ test => test . meta [ TEST_NAME ] === 'partial quarantine tests quarantined failing test'
4971+ )
4972+ assert . strictEqual ( quarantinedTest . meta [ TEST_STATUS ] , 'fail' )
4973+ assert . strictEqual ( quarantinedTest . meta [ TEST_MANAGEMENT_IS_QUARANTINED ] , 'true' )
4974+
4975+ // Verify the non-quarantined test does NOT have the quarantine tag
4976+ const nonQuarantinedTest = tests . find (
4977+ test => test . meta [ TEST_NAME ] === 'partial quarantine tests non-quarantined failing test'
4978+ )
4979+ assert . strictEqual ( nonQuarantinedTest . meta [ TEST_STATUS ] , 'fail' )
4980+ assert . ok (
4981+ ! ( TEST_MANAGEMENT_IS_QUARANTINED in nonQuarantinedTest . meta ) ,
4982+ 'Non-quarantined test should not have quarantine tag'
4983+ )
4984+ } )
4985+
4986+ childProcess = exec (
4987+ runTestsCommand ,
4988+ {
4989+ cwd,
4990+ env : {
4991+ ...getCiVisAgentlessConfig ( receiver . port ) ,
4992+ TESTS_TO_RUN : 'test-management/test-partial-quarantine' ,
4993+ SHOULD_CHECK_RESULTS : '1'
4994+ }
4995+ }
4996+ )
4997+
4998+ const [ [ exitCode ] ] = await Promise . all ( [ once ( childProcess , 'exit' ) , testAssertionsPromise ] )
4999+
5000+ // Exit code should be 1 because a non-quarantined test failed
5001+ assert . strictEqual ( exitCode , 1 )
5002+ } )
49275003 } )
49285004
49295005 it ( 'does not crash if the request to get test management tests fails' , async ( ) => {
0 commit comments