@@ -4038,6 +4038,87 @@ describe(`mocha@${MOCHA_VERSION}`, function () {
40384038 ] )
40394039 assert . match ( testOutput , / T e s t m a n a g e m e n t t e s t s c o u l d n o t b e f e t c h e d / )
40404040 } )
4041+
4042+ onlyLatestIt (
4043+ 'works in parallel mode with test management enabled but ITR and suite skipping disabled' ,
4044+ async ( ) => {
4045+ // This test reproduces the bug from issue #7222 where a missing 'else' keyword
4046+ // caused onFinishRequest() to be called twice when test management is enabled
4047+ // but ITR and suite skipping are disabled, resulting in the error:
4048+ // "invalid state transition: RUNNING => RUNNING"
4049+ let testOutput = ''
4050+ receiver . setSettings ( {
4051+ test_management : { enabled : true } ,
4052+ itr_enabled : false ,
4053+ code_coverage : false ,
4054+ tests_skipping : false ,
4055+ flaky_test_retries_enabled : false ,
4056+ known_tests_enabled : true
4057+ } )
4058+ receiver . setTestManagementTests ( {
4059+ mocha : {
4060+ suites : { }
4061+ }
4062+ } )
4063+
4064+ const eventsPromise = receiver
4065+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
4066+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
4067+ const testSession = events . find ( event => event . type === 'test_session_end' ) . content
4068+ assert . strictEqual ( testSession . meta [ TEST_MANAGEMENT_ENABLED ] , 'true' )
4069+ assert . strictEqual ( testSession . meta [ MOCHA_IS_PARALLEL ] , 'true' )
4070+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
4071+ assert . ok ( tests . length > 0 )
4072+ const suiteEvents = events . filter ( event => event . type === 'test_suite_end' )
4073+ assert . strictEqual ( suiteEvents . length , 2 , 'Expected exactly 2 suites to be reported' )
4074+ // Verify that tests have different runtime IDs, confirming parallel execution in different processes
4075+ // Group tests by their suite to get one test from each worker
4076+ const testsBySuite = { }
4077+ for ( const test of tests ) {
4078+ const suiteName = test . meta [ TEST_SUITE ]
4079+ if ( ! testsBySuite [ suiteName ] ) {
4080+ testsBySuite [ suiteName ] = test
4081+ }
4082+ }
4083+ const testFromEachWorker = Object . values ( testsBySuite )
4084+ assert . strictEqual ( testFromEachWorker . length , 2 , 'Expected tests from 2 different suites' )
4085+ const testRuntimeIds = testFromEachWorker . map ( test => test . meta [ 'runtime-id' ] )
4086+ assert . ok ( testRuntimeIds [ 0 ] , 'First test should have a runtime-id' )
4087+ assert . ok ( testRuntimeIds [ 1 ] , 'Second test should have a runtime-id' )
4088+ // This checks that the two tests come from different workers/processes
4089+ assert . notStrictEqual (
4090+ testRuntimeIds [ 0 ] ,
4091+ testRuntimeIds [ 1 ] ,
4092+ 'Tests from different workers should have different runtime-ids'
4093+ )
4094+ } )
4095+
4096+ childProcess = exec (
4097+ 'node node_modules/mocha/bin/mocha --parallel --jobs 2 ./ci-visibility/test/ci-visibility-test*' ,
4098+ {
4099+ cwd,
4100+ env : getCiVisAgentlessConfig ( receiver . port ) ,
4101+ stdio : 'inherit'
4102+ }
4103+ )
4104+
4105+ childProcess . stdout . on ( 'data' , ( chunk ) => {
4106+ testOutput += chunk . toString ( )
4107+ } )
4108+ childProcess . stderr . on ( 'data' , ( chunk ) => {
4109+ testOutput += chunk . toString ( )
4110+ } )
4111+
4112+ await Promise . all ( [
4113+ once ( childProcess , 'exit' ) ,
4114+ once ( childProcess . stdout , 'end' ) ,
4115+ once ( childProcess . stderr , 'end' ) ,
4116+ eventsPromise
4117+ ] )
4118+
4119+ // Verify no "invalid state transition" error occurred
4120+ assert . doesNotMatch ( testOutput , / i n v a l i d s t a t e t r a n s i t i o n / )
4121+ } )
40414122 } )
40424123
40434124 context ( 'libraries capabilities' , ( ) => {
0 commit comments