Skip to content

Commit d92c929

Browse files
DavertMikclaude
andcommitted
feat: add setBrowserConfig universal hook
One call to apply a bag of overrides — `browser`, `show`, `windowSize` are dispatched through their dedicated hooks so per-helper key translation is correct (Puppeteer gets `product` instead of `browser`, WebDriver gets `--headless` injected/stripped, etc). Any other key is shallow-merged onto every browser helper present in config. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d0b009e commit d92c929

5 files changed

Lines changed: 141 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
4.0.0
22

33
* ESM-only release targeting CodeceptJS 4.x. Convert package + all hooks + bridge to native ESM (`type: module`).
4+
* Added `setBrowserConfig({ browser, show, windowSize, ... })` — universal helper that dispatches options through the right primitive (so Puppeteer gets `product`, Playwright gets `browser`, WebDriver gets `--headless` chrome args, etc.) and shallow-merges any extra keys onto every browser helper.
45
* Fix Config singleton sharing: bridge now imports `codeceptjs` via ESM, so hooks register on the host's Config instance instead of a stale CJS-resolved copy.
56
* Mark the `codeceptjs` peer dependency as optional so npm doesn't pull a parallel 3.x copy alongside a 4.x host.
67
* Drop the `tryTo` / `retryTo` plugin enable in `setCommonPlugins` — in CodeceptJS 4 those are imported from `codeceptjs/effects`, not enabled as plugins.

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,21 @@ exports.config = {
145145
}
146146
```
147147

148+
### setBrowserConfig
149+
150+
Apply a bag of browser-helper overrides in one call. Routes `browser`, `show`, and `windowSize` through their dedicated hooks (so per-helper key translation like Puppeteer's `product` vs Playwright's `browser`, and WebDriver `--headless` capability args, are handled correctly). Any other key is shallow-merged onto every browser helper present in config.
151+
152+
```js
153+
import { setBrowserConfig } from '@codeceptjs/configure'
154+
155+
setBrowserConfig({
156+
browser: process.env.BROWSER, // -> setBrowser
157+
show: !process.env.HEADLESS, // -> setHeadedWhen / setHeadlessWhen
158+
windowSize: '1280x720', // -> setWindowSize
159+
waitForTimeout: 10000, // -> merged onto each helper
160+
})
161+
```
162+
148163
### setTestHost
149164

150165
Changes url in config for Playwright, Puppeteer, WebDriver & TestCafe:

hooks/setBrowserConfig.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { config } from '../codeceptjs.js'
2+
import setBrowser from './setBrowser.js'
3+
import setWindowSize from './setWindowSize.js'
4+
import setHeadedWhen from './setHeadedWhen.js'
5+
import setHeadlessWhen from './setHeadlessWhen.js'
6+
7+
const BROWSER_HELPERS = ['Playwright', 'Puppeteer', 'WebDriver', 'Appium', 'TestCafe', 'Protractor', 'Nightmare']
8+
9+
/**
10+
* Apply a bag of browser helper overrides in a single call. Dispatches the
11+
* options that have dedicated hooks (browser, show, windowSize) through them
12+
* — so per-helper key translation (e.g. Puppeteer `product` vs Playwright
13+
* `browser`) and capability-arg surgery (WebDriver `--headless` chrome args)
14+
* are handled correctly. Anything else is shallow-merged onto every browser
15+
* helper present in config.
16+
*
17+
* @example
18+
* setBrowserConfig({
19+
* browser: process.env.BROWSER, // -> setBrowser
20+
* show: !process.env.HEADLESS, // -> setHeadedWhen / setHeadlessWhen
21+
* windowSize: '1280x720', // -> setWindowSize
22+
* waitForTimeout: 10000, // -> Object.assign onto each helper
23+
* })
24+
*
25+
* @param {object} [opts]
26+
*/
27+
export default function setBrowserConfig(opts) {
28+
if (!opts || typeof opts !== 'object') return
29+
30+
const { browser, show, windowSize, ...rest } = opts
31+
32+
if (browser !== undefined && browser !== null && browser !== '') {
33+
setBrowser(browser)
34+
}
35+
36+
if (show === true) setHeadedWhen(true)
37+
else if (show === false) setHeadlessWhen(true)
38+
39+
if (windowSize) {
40+
const m = /^(\d+)x(\d+)$/.exec(String(windowSize))
41+
if (m) setWindowSize(Number(m[1]), Number(m[2]))
42+
}
43+
44+
if (Object.keys(rest).length === 0) return
45+
46+
config.addHook(cfg => {
47+
if (!cfg.helpers) return
48+
for (const helperName of BROWSER_HELPERS) {
49+
if (cfg.helpers[helperName]) Object.assign(cfg.helpers[helperName], rest)
50+
}
51+
})
52+
}

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export { default as setHeadedWhen } from './hooks/setHeadedWhen.js'
33
export { default as setSharedCookies } from './hooks/setSharedCookies.js'
44
export { default as setWindowSize } from './hooks/setWindowSize.js'
55
export { default as setBrowser } from './hooks/setBrowser.js'
6+
export { default as setBrowserConfig } from './hooks/setBrowserConfig.js'
67
export { default as setTestHost } from './hooks/setTestHost.js'
78
export { default as setCommonPlugins } from './hooks/setCommonPlugins.js'

test/index.test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
setSharedCookies,
88
setWindowSize,
99
setBrowser,
10+
setBrowserConfig,
1011
setTestHost,
1112
setCommonPlugins,
1213
} from '../index.js'
@@ -161,6 +162,77 @@ describe('Hooks tests', () => {
161162
}
162163
})
163164

165+
describe('#setBrowserConfig', () => {
166+
test('no-ops when called with no args / non-object', () => {
167+
Config.reset()
168+
const config = { helpers: { Playwright: { show: true } } }
169+
setBrowserConfig()
170+
setBrowserConfig(null)
171+
Config.create(config)
172+
assert.equal(Config.get().helpers.Playwright.show, true)
173+
})
174+
175+
test('routes browser through setBrowser (Puppeteer gets product, not browser)', () => {
176+
Config.reset()
177+
const config = { helpers: { Puppeteer: {}, Playwright: {} } }
178+
setBrowserConfig({ browser: 'firefox' })
179+
Config.create(config)
180+
assert.equal(Config.get().helpers.Puppeteer.product, 'firefox')
181+
assert.equal(Config.get().helpers.Puppeteer.browser, undefined)
182+
assert.equal(Config.get().helpers.Playwright.browser, 'firefox')
183+
})
184+
185+
test('show:true -> headed; show:false -> headless on Playwright/Puppeteer', () => {
186+
Config.reset()
187+
let config = { helpers: { Playwright: { show: false }, Puppeteer: { show: false } } }
188+
setBrowserConfig({ show: true })
189+
Config.create(config)
190+
assert.equal(Config.get().helpers.Playwright.show, true)
191+
assert.equal(Config.get().helpers.Puppeteer.show, true)
192+
193+
Config.reset()
194+
config = { helpers: { Playwright: { show: true }, WebDriver: { browser: 'chrome' } } }
195+
setBrowserConfig({ show: false })
196+
Config.create(config)
197+
assert.equal(Config.get().helpers.Playwright.show, false)
198+
assert.ok(Config.get().helpers.WebDriver.desiredCapabilities.chromeOptions.args.includes('--headless'))
199+
})
200+
201+
test('windowSize string is parsed and setWindowSize fires', () => {
202+
Config.reset()
203+
const config = { helpers: { Playwright: {}, WebDriver: {} } }
204+
setBrowserConfig({ windowSize: '1280x720' })
205+
Config.create(config)
206+
assert.equal(Config.get().helpers.Playwright.windowSize, '1280x720')
207+
assert.ok(Config.get().helpers.Playwright.chromium.args.includes('--window-size=1280,720'))
208+
assert.equal(Config.get().helpers.WebDriver.windowSize, '1280x720')
209+
})
210+
211+
test('extra keys are shallow-merged onto every browser helper', () => {
212+
Config.reset()
213+
const config = { helpers: { Playwright: {}, Puppeteer: {}, WebDriver: {}, REST: {} } }
214+
setBrowserConfig({ video: false, waitForTimeout: 9000 })
215+
Config.create(config)
216+
assert.equal(Config.get().helpers.Playwright.video, false)
217+
assert.equal(Config.get().helpers.Playwright.waitForTimeout, 9000)
218+
assert.equal(Config.get().helpers.Puppeteer.video, false)
219+
assert.equal(Config.get().helpers.WebDriver.waitForTimeout, 9000)
220+
assert.equal(Config.get().helpers.REST.video, undefined)
221+
})
222+
223+
test('combined options applied in one call', () => {
224+
Config.reset()
225+
const config = { helpers: { Playwright: { show: false } } }
226+
setBrowserConfig({ browser: 'webkit', show: true, windowSize: '800x600', video: true })
227+
Config.create(config)
228+
const pw = Config.get().helpers.Playwright
229+
assert.equal(pw.browser, 'webkit')
230+
assert.equal(pw.show, true)
231+
assert.equal(pw.windowSize, '800x600')
232+
assert.equal(pw.video, true)
233+
})
234+
})
235+
164236
describe('#setCommonPlugins', () => {
165237
test('create standard plugins', () => {
166238
Config.reset()

0 commit comments

Comments
 (0)