Skip to content

Commit 4968282

Browse files
committed
feat(Playwright): Add browser restart strategy support
- Add 'browser' as valid restart option in PlaywrightRestartOpts - Add restartsBrowser() function to check browser restart strategy - Update Playwright helper to restart browser between tests when BROWSER_RESTART=browser - Add timeout protection (5s) to prevent hanging during browser stop - Close all pages before stopping browser for cleaner shutdown - Update _before(), _after(), _afterSuite(), and _finishTest() methods Fixes support for BROWSER_RESTART=browser environment variable to completely restart the browser between each test, providing maximum isolation.
1 parent ab84a94 commit 4968282

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

lib/helper/Playwright.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const popupStore = new Popup()
4343
const consoleLogStore = new Console()
4444
const availableBrowsers = ['chromium', 'webkit', 'firefox', 'electron']
4545

46-
import { setRestartStrategy, restartsSession, restartsContext } from './extras/PlaywrightRestartOpts.js'
46+
import { setRestartStrategy, restartsSession, restartsContext, restartsBrowser } from './extras/PlaywrightRestartOpts.js'
4747
import { createValueEngine, createDisabledEngine } from './extras/PlaywrightPropEngine.js'
4848
import { seeElementError, dontSeeElementError, dontSeeElementInDOMError, seeElementInDOMError } from './errors/ElementAssertion.js'
4949
import { dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics } from './network/actions.js'
@@ -600,7 +600,12 @@ class Playwright extends Helper {
600600
},
601601
})
602602

603+
// Start browser if needed (initial start or browser restart strategy)
603604
if (!this.isRunning && !this.options.manualStart) await this._startBrowser()
605+
else if (restartsBrowser() && !this.options.manualStart) {
606+
// Browser restart strategy: start browser for each test
607+
await this._startBrowser()
608+
}
604609

605610
this.isAuthenticated = false
606611
if (this.isElectron) {
@@ -704,6 +709,31 @@ class Playwright extends Helper {
704709
return refreshContextSession.bind(this)()
705710
}
706711

712+
if (restartsBrowser()) {
713+
// Close browser completely for restart strategy
714+
if (this.isRunning) {
715+
try {
716+
// Close all pages first to release resources
717+
if (this.browserContext) {
718+
const pages = await this.browserContext.pages()
719+
await Promise.allSettled(pages.map(p => p.close().catch(() => {})))
720+
}
721+
// Use timeout to prevent hanging
722+
await Promise.race([
723+
this._stopBrowser(),
724+
new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout')), 5000)),
725+
])
726+
} catch (e) {
727+
console.warn('Warning during browser restart in _after:', e.message)
728+
// Force cleanup even on timeout
729+
this.browser = null
730+
this.browserContext = null
731+
this.isRunning = false
732+
}
733+
}
734+
return
735+
}
736+
707737
// close other sessions with timeout protection, but only if restartsContext() is true
708738
if (restartsContext()) {
709739
try {
@@ -730,7 +760,7 @@ class Playwright extends Helper {
730760

731761
async _afterSuite() {
732762
// Only stop browser if restart strategy requires it
733-
if ((restartsSession() || restartsContext()) && this.isRunning) {
763+
if ((restartsSession() || restartsContext() || restartsBrowser()) && this.isRunning) {
734764
try {
735765
await this._stopBrowser()
736766
} catch (e) {
@@ -813,7 +843,7 @@ class Playwright extends Helper {
813843
}
814844

815845
async _finishTest() {
816-
if ((restartsSession() || restartsContext()) && this.isRunning) {
846+
if ((restartsSession() || restartsContext() || restartsBrowser()) && this.isRunning) {
817847
try {
818848
await Promise.race([this._stopBrowser(), new Promise((_, reject) => setTimeout(() => reject(new Error('Test finish timeout')), 10000))])
819849
} catch (e) {

lib/helper/extras/PlaywrightRestartOpts.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const RESTART_OPTS = {
22
session: 'keep',
33
context: false,
4+
browser: true,
45
}
56

67
let restarts = null
@@ -19,9 +20,15 @@ export function setRestartStrategy(options) {
1920
return
2021
}
2122

23+
// When restart is true, map to 'browser' restart
24+
if (restart === true) {
25+
restarts = 'browser'
26+
return
27+
}
28+
2229
restarts = Object.keys(RESTART_OPTS).find(key => RESTART_OPTS[key] === restart)
2330

24-
if (restarts === null || restarts === undefined) throw new Error('No restart strategy set, use the following values for restart: session, context')
31+
if (restarts === null || restarts === undefined) throw new Error('No restart strategy set, use the following values for restart: session, context, browser')
2532
}
2633

2734
export function restartsSession() {
@@ -31,3 +38,7 @@ export function restartsSession() {
3138
export function restartsContext() {
3239
return restarts === 'context'
3340
}
41+
42+
export function restartsBrowser() {
43+
return restarts === 'browser'
44+
}

0 commit comments

Comments
 (0)