Skip to content

Commit 9fc9c5c

Browse files
committed
fix: clean up setTimeout timers in MockEventSource to prevent test hangs
The MockEventSource was creating setTimeout calls that weren't being cleaned up. These orphaned timers kept the Node.js event loop alive, causing the test suite to hang with a 30+ second timeout. Now we track all timeout IDs and clear them in the close() method to ensure proper cleanup.
1 parent b468cb6 commit 9fc9c5c

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

test/unit/lib/run/log-displayer.unit.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ describe('logDisplayer', function () {
3636
public readyState: number = 0 // CONNECTING
3737
public url: string
3838
private errorCode: number
39+
private timeouts: NodeJS.Timeout[] = []
3940

4041
constructor(url: string, options?: any) {
4142
this.url = url
@@ -48,7 +49,7 @@ describe('logDisplayer', function () {
4849
}
4950

5051
// Simulate connection attempt
51-
setTimeout(() => {
52+
const timeout1 = setTimeout(() => {
5253
// Check if this is the test that expects success (specific URL pattern for non-tail mode)
5354
const isSuccessTest = this.url.includes('logs.heroku.com') && this.url.includes('tail=false')
5455

@@ -74,7 +75,7 @@ describe('logDisplayer', function () {
7475
}
7576

7677
// Close after sending messages
77-
setTimeout(() => {
78+
const timeout2 = setTimeout(() => {
7879
this.close()
7980
// For non-tail mode, trigger error event to resolve the promise
8081
if (this.onerror) {
@@ -85,6 +86,7 @@ describe('logDisplayer', function () {
8586
this.onerror(closeEvent)
8687
}
8788
}, 20)
89+
this.timeouts.push(timeout2)
8890
} else if (this.onerror) {
8991
// Create a mock error event with status code
9092
const errorEvent = {
@@ -94,6 +96,7 @@ describe('logDisplayer', function () {
9496
this.onerror(errorEvent)
9597
}
9698
}, 10)
99+
this.timeouts.push(timeout1)
97100
}
98101

99102
addEventListener(type: string, listener: (event: any) => void) {
@@ -117,6 +120,11 @@ describe('logDisplayer', function () {
117120

118121
close() {
119122
this.readyState = 2 // CLOSED
123+
// Clear all pending timeouts to prevent them from running after tests complete
124+
for (const timeout of this.timeouts) {
125+
clearTimeout(timeout)
126+
}
127+
this.timeouts = []
120128
}
121129
}
122130

@@ -132,6 +140,10 @@ describe('logDisplayer', function () {
132140
if (createEventSourceStub) {
133141
createEventSourceStub.restore()
134142
}
143+
// Ensure displayer is cleaned up to avoid hanging
144+
if (displayer) {
145+
displayer = null as any
146+
}
135147
})
136148

137149
after(function () {

0 commit comments

Comments
 (0)