Skip to content

Commit 34ba60f

Browse files
committed
fix: prevent retry config accumulation by having helpers and plugin cleanup their own config after each test
- Playwright & Puppeteer: store retry config in this._retryConfig and remove in _after() - retryFailedStep plugin: avoid duplicate pushes and clean config on event.test.after
1 parent 06cdb0c commit 34ba60f

3 files changed

Lines changed: 27 additions & 5 deletions

File tree

lib/helper/Playwright.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ class Playwright extends Helper {
575575
// Clear popup state to ensure clean state for each test
576576
popupStore.clear()
577577

578-
recorder.retry({
578+
// Configure retry for this test; will clean up after test completes
579+
this._retryConfig = {
579580
retries: test?.opts?.conditionalRetries || 3,
580581
when: err => {
581582
if (!err || typeof err.message !== 'string') {
@@ -584,7 +585,8 @@ class Playwright extends Helper {
584585
// ignore context errors
585586
return err.message.includes('context')
586587
},
587-
})
588+
}
589+
recorder.retry(this._retryConfig)
588590

589591
// Start browser if needed (initial start or browser restart strategy)
590592
if (!this.isRunning && !this.options.manualStart) await this._startBrowser()
@@ -689,6 +691,12 @@ class Playwright extends Helper {
689691
}
690692

691693
async _after() {
694+
// Clean up our retry config to prevent accumulation
695+
if (this._retryConfig) {
696+
recorder.retries = recorder.retries.filter(r => r !== this._retryConfig)
697+
this._retryConfig = null
698+
}
699+
692700
if (!this.isRunning) return
693701

694702
// Clear popup state to prevent leakage between tests

lib/helper/Puppeteer.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ class Puppeteer extends Helper {
354354
async _before(test) {
355355
this.sessionPages = {}
356356
this.currentRunningTest = test
357-
recorder.retry({
357+
// Configure retry for this test; will clean up after test completes
358+
this._retryConfig = {
358359
retries: test?.opts?.conditionalRetries || 3,
359360
when: err => {
360361
if (!err || typeof err.message !== 'string') {
@@ -363,13 +364,20 @@ class Puppeteer extends Helper {
363364
// ignore context errors
364365
return err.message.includes('context')
365366
},
366-
})
367+
}
368+
recorder.retry(this._retryConfig)
367369
if (this.options.restart && !this.options.manualStart) return this._startBrowser()
368370
if (!this.isRunning && !this.options.manualStart) return this._startBrowser()
369371
return this.browser
370372
}
371373

372374
async _after() {
375+
// Clean up our retry config to prevent accumulation
376+
if (this._retryConfig) {
377+
recorder.retries = recorder.retries.filter(r => r !== this._retryConfig)
378+
this._retryConfig = null
379+
}
380+
373381
if (!this.isRunning) return
374382

375383
// Clear popup state to prevent leakage between tests

lib/plugin/retryFailedStep.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ export default function (config) {
152152
test.opts.stepRetryPriority = stepRetryPriority
153153

154154
debug('applying retries = %d for test %s', config.retries, test.title)
155-
recorder.retry(config)
155+
if (!recorder.retries.find(r => r === config)) {
156+
recorder.retry(config)
157+
}
156158
})
157159

158160
event.dispatcher.on(event.test.started, test => {
@@ -171,4 +173,8 @@ export default function (config) {
171173
test.opts.conditionalRetries = test.opts.conditionalRetries || config.retries
172174
}
173175
})
176+
177+
event.dispatcher.on(event.test.after, () => {
178+
recorder.retries = recorder.retries.filter(r => r !== config)
179+
})
174180
}

0 commit comments

Comments
 (0)