Skip to content

Commit 2047cf2

Browse files
Copilotkobenguyent
andauthored
Fix tryTo steps appearing in test failure traces (#5088)
* Initial plan * Changes before error encountered Co-authored-by: kobenguyent <[email protected]> * Changes before error encountered Co-authored-by: kobenguyent <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: kobenguyent <[email protected]>
1 parent ce16e92 commit 2047cf2

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

lib/listener/steps.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ const event = require('../event')
33
const store = require('../store')
44
const output = require('../output')
55
const { BeforeHook, AfterHook, BeforeSuiteHook, AfterSuiteHook } = require('../mocha/hooks')
6+
const recorder = require('../recorder')
67

78
let currentTest
89
let currentHook
910

11+
// Session names that should not contribute steps to the main test trace
12+
const EXCLUDED_SESSIONS = ['tryTo', 'hopeThat']
13+
1014
/**
1115
* Register steps inside tests
1216
*/
@@ -75,6 +79,14 @@ module.exports = function () {
7579
return currentHook.steps.push(step)
7680
}
7781
if (!currentTest || !currentTest.steps) return
82+
83+
// Check if we're in a session that should be excluded from main test steps
84+
const currentSessionId = recorder.getCurrentSessionId()
85+
if (currentSessionId && EXCLUDED_SESSIONS.includes(currentSessionId)) {
86+
// Skip adding this step to the main test steps
87+
return
88+
}
89+
7890
currentTest.steps.push(step)
7991
})
8092

lib/recorder.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,15 @@ module.exports = {
379379
toString() {
380380
return `Queue: ${currentQueue()}\n\nTasks: ${this.scheduled()}`
381381
},
382+
383+
/**
384+
* Get current session ID
385+
* @return {string|null}
386+
* @inner
387+
*/
388+
getCurrentSessionId() {
389+
return sessionId
390+
},
382391
}
383392

384393
function getTimeoutPromise(timeoutMs, taskName) {
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
const { expect } = require('chai')
2+
const sinon = require('sinon')
3+
const event = require('../../../lib/event')
4+
const recorder = require('../../../lib/recorder')
5+
const { tryTo, hopeThat } = require('../../../lib/effects')
6+
const Step = require('../../../lib/step')
7+
8+
// Import and initialize the steps listener
9+
const stepsListener = require('../../../lib/listener/steps')
10+
11+
describe('Steps Listener - Issue Fix #4619', () => {
12+
let currentTest
13+
14+
beforeEach(() => {
15+
// Reset everything
16+
recorder.reset()
17+
recorder.start()
18+
event.cleanDispatcher()
19+
20+
// Initialize the steps listener (it needs to be called as a function)
21+
stepsListener()
22+
23+
// Create a mock test object
24+
currentTest = {
25+
title: 'Test Case for Issue #4619',
26+
steps: [],
27+
}
28+
29+
// Emit test started event to properly initialize the listener
30+
event.emit(event.test.started, currentTest)
31+
})
32+
33+
afterEach(() => {
34+
event.cleanDispatcher()
35+
recorder.reset()
36+
})
37+
38+
it('should exclude steps emitted during tryTo sessions from main test trace', async () => {
39+
// This is the core fix: steps emitted inside tryTo should not pollute the main test trace
40+
41+
const stepCountBefore = currentTest.steps.length
42+
43+
// Execute tryTo and emit a step inside it
44+
await tryTo(() => {
45+
const tryToStep = new Step(
46+
{
47+
optionalAction: () => {
48+
throw new Error('Expected to fail')
49+
},
50+
},
51+
'optionalAction',
52+
)
53+
event.emit(event.step.started, tryToStep)
54+
recorder.add(() => {
55+
throw new Error('Expected to fail')
56+
})
57+
})
58+
59+
const stepCountAfter = currentTest.steps.length
60+
61+
// The manually emitted step should not appear in the main test trace
62+
const stepNames = currentTest.steps.map(step => step.name)
63+
expect(stepNames).to.not.include('optionalAction')
64+
65+
return recorder.promise()
66+
})
67+
68+
it('should exclude steps emitted during hopeThat sessions from main test trace', async () => {
69+
await hopeThat(() => {
70+
const hopeThatStep = new Step({ softAssertion: () => 'done' }, 'softAssertion')
71+
event.emit(event.step.started, hopeThatStep)
72+
})
73+
74+
// The manually emitted step should not appear in the main test trace
75+
const stepNames = currentTest.steps.map(step => step.name)
76+
expect(stepNames).to.not.include('softAssertion')
77+
78+
return recorder.promise()
79+
})
80+
81+
it('should still allow regular steps to be added normally', () => {
82+
// Regular steps outside of special sessions should work normally
83+
const regularStep = new Step({ normalAction: () => 'done' }, 'normalAction')
84+
event.emit(event.step.started, regularStep)
85+
86+
const stepNames = currentTest.steps.map(step => step.name)
87+
expect(stepNames).to.include('normalAction')
88+
})
89+
90+
it('should validate the session filtering logic works correctly', async () => {
91+
// This test validates that the core logic in the fix is working
92+
93+
// Add a regular step
94+
const regularStep = new Step({ regularAction: () => 'done' }, 'regularAction')
95+
event.emit(event.step.started, regularStep)
96+
97+
// Execute tryTo and verify the filtering works
98+
await tryTo(() => {
99+
const filteredStep = new Step({ filteredAction: () => 'done' }, 'filteredAction')
100+
event.emit(event.step.started, filteredStep)
101+
})
102+
103+
// Add another regular step
104+
const anotherRegularStep = new Step({ anotherRegularAction: () => 'done' }, 'anotherRegularAction')
105+
event.emit(event.step.started, anotherRegularStep)
106+
107+
const stepNames = currentTest.steps.map(step => step.name)
108+
109+
// Regular steps should be present
110+
expect(stepNames).to.include('regularAction')
111+
expect(stepNames).to.include('anotherRegularAction')
112+
113+
// Filtered step should not be present
114+
expect(stepNames).to.not.include('filteredAction')
115+
116+
return recorder.promise()
117+
})
118+
})

0 commit comments

Comments
 (0)