codeceptjs 4.0.1-beta.4 → 4.0.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/helper/GraphQL.js +6 -4
- package/lib/helper/JSONResponse.js +3 -4
- package/lib/helper/Playwright.js +19 -35
- package/lib/helper/REST.js +11 -8
- package/package.json +1 -1
package/lib/helper/GraphQL.js
CHANGED
|
@@ -45,6 +45,8 @@ class GraphQL extends Helper {
|
|
|
45
45
|
timeout: 10000,
|
|
46
46
|
defaultHeaders: {},
|
|
47
47
|
endpoint: '',
|
|
48
|
+
onRequest: null,
|
|
49
|
+
onResponse: null,
|
|
48
50
|
}
|
|
49
51
|
this.options = Object.assign(this.options, config)
|
|
50
52
|
this.headers = { ...this.options.defaultHeaders }
|
|
@@ -87,8 +89,8 @@ class GraphQL extends Helper {
|
|
|
87
89
|
|
|
88
90
|
request.headers = { ...this.headers, ...request.headers }
|
|
89
91
|
|
|
90
|
-
if (this.
|
|
91
|
-
await this.
|
|
92
|
+
if (this.options.onRequest) {
|
|
93
|
+
await this.options.onRequest(request)
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
this.debugSection('Request', JSON.stringify(request))
|
|
@@ -102,8 +104,8 @@ class GraphQL extends Helper {
|
|
|
102
104
|
response = err.response
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
if (this.
|
|
106
|
-
await this.
|
|
107
|
+
if (this.options.onResponse) {
|
|
108
|
+
await this.options.onResponse(response)
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
this.debugSection('Response', JSON.stringify(response.data))
|
|
@@ -72,8 +72,8 @@ class JSONResponse extends Helper {
|
|
|
72
72
|
if (!this.helpers[this.options.requestHelper]) {
|
|
73
73
|
throw new Error(`Error setting JSONResponse, helper ${this.options.requestHelper} is not enabled in config, helpers: ${Object.keys(this.helpers)}`)
|
|
74
74
|
}
|
|
75
|
-
const origOnResponse = this.helpers[this.options.requestHelper].
|
|
76
|
-
this.helpers[this.options.requestHelper].
|
|
75
|
+
const origOnResponse = this.helpers[this.options.requestHelper].options.onResponse
|
|
76
|
+
this.helpers[this.options.requestHelper].options.onResponse = response => {
|
|
77
77
|
this.response = response
|
|
78
78
|
if (typeof origOnResponse === 'function') origOnResponse(response)
|
|
79
79
|
}
|
|
@@ -83,7 +83,6 @@ class JSONResponse extends Helper {
|
|
|
83
83
|
this.response = null
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
87
86
|
/**
|
|
88
87
|
* Checks that response code is equal to the provided one
|
|
89
88
|
*
|
|
@@ -372,4 +371,4 @@ class JSONResponse extends Helper {
|
|
|
372
371
|
}
|
|
373
372
|
}
|
|
374
373
|
|
|
375
|
-
export { JSONResponse as default }
|
|
374
|
+
export { JSONResponse, JSONResponse as default }
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -355,7 +355,7 @@ class Playwright extends Helper {
|
|
|
355
355
|
this.recordingWebSocketMessages = false
|
|
356
356
|
this.recordedWebSocketMessagesAtLeastOnce = false
|
|
357
357
|
this.cdpSession = null
|
|
358
|
-
|
|
358
|
+
|
|
359
359
|
// Filter out invalid customLocatorStrategies (empty arrays, objects without functions)
|
|
360
360
|
// This can happen in worker threads where config is serialized/deserialized
|
|
361
361
|
let validCustomLocators = null
|
|
@@ -367,7 +367,7 @@ class Playwright extends Helper {
|
|
|
367
367
|
validCustomLocators = config.customLocatorStrategies
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
this.customLocatorStrategies = validCustomLocators
|
|
372
372
|
this._customLocatorsRegistered = false
|
|
373
373
|
|
|
@@ -416,6 +416,7 @@ class Playwright extends Helper {
|
|
|
416
416
|
ignoreHTTPSErrors: false, // Adding it here o that context can be set up to ignore the SSL errors,
|
|
417
417
|
highlightElement: false,
|
|
418
418
|
storageState: undefined,
|
|
419
|
+
onResponse: null,
|
|
419
420
|
}
|
|
420
421
|
|
|
421
422
|
process.env.testIdAttribute = 'data-testid'
|
|
@@ -794,10 +795,7 @@ class Playwright extends Helper {
|
|
|
794
795
|
await Promise.allSettled(pages.map(p => p.close().catch(() => {})))
|
|
795
796
|
}
|
|
796
797
|
// Use timeout to prevent hanging (10s should be enough for browser cleanup)
|
|
797
|
-
await Promise.race([
|
|
798
|
-
this._stopBrowser(),
|
|
799
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout')), 10000)),
|
|
800
|
-
])
|
|
798
|
+
await Promise.race([this._stopBrowser(), new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout')), 10000))])
|
|
801
799
|
} catch (e) {
|
|
802
800
|
console.warn('Warning during browser restart in _after:', e.message)
|
|
803
801
|
// Force cleanup even on timeout
|
|
@@ -840,10 +838,7 @@ class Playwright extends Helper {
|
|
|
840
838
|
if (this.isRunning) {
|
|
841
839
|
try {
|
|
842
840
|
// Add timeout protection to prevent hanging
|
|
843
|
-
await Promise.race([
|
|
844
|
-
this._stopBrowser(),
|
|
845
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in afterSuite')), 10000)),
|
|
846
|
-
])
|
|
841
|
+
await Promise.race([this._stopBrowser(), new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in afterSuite')), 10000))])
|
|
847
842
|
} catch (e) {
|
|
848
843
|
console.warn('Warning during suite cleanup:', e.message)
|
|
849
844
|
// Track suite cleanup failures
|
|
@@ -954,10 +949,7 @@ class Playwright extends Helper {
|
|
|
954
949
|
if (this.isRunning) {
|
|
955
950
|
try {
|
|
956
951
|
// Add timeout protection to prevent hanging
|
|
957
|
-
await Promise.race([
|
|
958
|
-
this._stopBrowser(),
|
|
959
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in cleanup')), 10000)),
|
|
960
|
-
])
|
|
952
|
+
await Promise.race([this._stopBrowser(), new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in cleanup')), 10000))])
|
|
961
953
|
} catch (e) {
|
|
962
954
|
console.warn('Warning during final cleanup:', e.message)
|
|
963
955
|
// Force cleanup on timeout
|
|
@@ -970,10 +962,7 @@ class Playwright extends Helper {
|
|
|
970
962
|
if (this.browser) {
|
|
971
963
|
try {
|
|
972
964
|
// Add timeout protection to prevent hanging
|
|
973
|
-
await Promise.race([
|
|
974
|
-
this._stopBrowser(),
|
|
975
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in forced cleanup')), 10000)),
|
|
976
|
-
])
|
|
965
|
+
await Promise.race([this._stopBrowser(), new Promise((_, reject) => setTimeout(() => reject(new Error('Browser stop timeout in forced cleanup')), 10000))])
|
|
977
966
|
} catch (e) {
|
|
978
967
|
console.warn('Warning during forced cleanup:', e.message)
|
|
979
968
|
// Force cleanup on timeout
|
|
@@ -1390,7 +1379,7 @@ class Playwright extends Helper {
|
|
|
1390
1379
|
this.context = null
|
|
1391
1380
|
this.frame = null
|
|
1392
1381
|
popupStore.clear()
|
|
1393
|
-
|
|
1382
|
+
|
|
1394
1383
|
// Remove all event listeners to prevent hanging
|
|
1395
1384
|
if (this.browser) {
|
|
1396
1385
|
try {
|
|
@@ -1399,7 +1388,7 @@ class Playwright extends Helper {
|
|
|
1399
1388
|
// Ignore errors if browser is already closed
|
|
1400
1389
|
}
|
|
1401
1390
|
}
|
|
1402
|
-
|
|
1391
|
+
|
|
1403
1392
|
if (this.options.recordHar && this.browserContext) {
|
|
1404
1393
|
try {
|
|
1405
1394
|
await this.browserContext.close()
|
|
@@ -1408,16 +1397,11 @@ class Playwright extends Helper {
|
|
|
1408
1397
|
}
|
|
1409
1398
|
}
|
|
1410
1399
|
this.browserContext = null
|
|
1411
|
-
|
|
1400
|
+
|
|
1412
1401
|
if (this.browser) {
|
|
1413
1402
|
try {
|
|
1414
1403
|
// Add timeout to prevent browser.close() from hanging indefinitely
|
|
1415
|
-
await Promise.race([
|
|
1416
|
-
this.browser.close(),
|
|
1417
|
-
new Promise((_, reject) =>
|
|
1418
|
-
setTimeout(() => reject(new Error('Browser close timeout')), 5000)
|
|
1419
|
-
)
|
|
1420
|
-
])
|
|
1404
|
+
await Promise.race([this.browser.close(), new Promise((_, reject) => setTimeout(() => reject(new Error('Browser close timeout')), 5000))])
|
|
1421
1405
|
} catch (e) {
|
|
1422
1406
|
// Ignore errors if browser is already closed or timeout
|
|
1423
1407
|
if (!e.message?.includes('Browser close timeout')) {
|
|
@@ -1539,7 +1523,7 @@ class Playwright extends Helper {
|
|
|
1539
1523
|
acceptDownloads: true,
|
|
1540
1524
|
...this.options.emulate,
|
|
1541
1525
|
}
|
|
1542
|
-
|
|
1526
|
+
|
|
1543
1527
|
try {
|
|
1544
1528
|
this.browserContext = await this.browser.newContext(contextOptions)
|
|
1545
1529
|
} catch (err) {
|
|
@@ -3183,14 +3167,14 @@ class Playwright extends Helper {
|
|
|
3183
3167
|
this.debugSection('Response', await response.text())
|
|
3184
3168
|
|
|
3185
3169
|
// hook to allow JSON response handle this
|
|
3186
|
-
if (this.
|
|
3170
|
+
if (this.options.onResponse) {
|
|
3187
3171
|
const axiosResponse = {
|
|
3188
3172
|
data: await response.json(),
|
|
3189
3173
|
status: response.status(),
|
|
3190
3174
|
statusText: response.statusText(),
|
|
3191
3175
|
headers: response.headers(),
|
|
3192
3176
|
}
|
|
3193
|
-
this.
|
|
3177
|
+
this.options.onResponse(axiosResponse)
|
|
3194
3178
|
}
|
|
3195
3179
|
|
|
3196
3180
|
return response
|
|
@@ -4337,11 +4321,11 @@ function isRoleLocatorObject(locator) {
|
|
|
4337
4321
|
*/
|
|
4338
4322
|
async function handleRoleLocator(context, locator) {
|
|
4339
4323
|
if (!isRoleLocatorObject(locator)) return null
|
|
4340
|
-
|
|
4324
|
+
|
|
4341
4325
|
const options = {}
|
|
4342
4326
|
if (locator.text) options.name = locator.text
|
|
4343
4327
|
if (locator.exact !== undefined) options.exact = locator.exact
|
|
4344
|
-
|
|
4328
|
+
|
|
4345
4329
|
return context.getByRole(locator.role, Object.keys(options).length > 0 ? options : undefined).all()
|
|
4346
4330
|
}
|
|
4347
4331
|
|
|
@@ -4350,7 +4334,7 @@ async function findElements(matcher, locator) {
|
|
|
4350
4334
|
const isReactLocator = locator.type === 'react' || (locator.locator && locator.locator.react) || locator.react
|
|
4351
4335
|
const isVueLocator = locator.type === 'vue' || (locator.locator && locator.locator.vue) || locator.vue
|
|
4352
4336
|
const isPwLocator = locator.type === 'pw' || (locator.locator && locator.locator.pw) || locator.pw
|
|
4353
|
-
|
|
4337
|
+
|
|
4354
4338
|
if (isReactLocator) return findReact(matcher, locator)
|
|
4355
4339
|
if (isVueLocator) return findVue(matcher, locator)
|
|
4356
4340
|
if (isPwLocator) return findByPlaywrightLocator.call(this, matcher, locator)
|
|
@@ -4391,7 +4375,7 @@ async function findCustomElements(matcher, locator) {
|
|
|
4391
4375
|
// Always prioritize this.customLocatorStrategies which is set in constructor from config
|
|
4392
4376
|
// and persists in every worker thread instance
|
|
4393
4377
|
let strategyFunction = null
|
|
4394
|
-
|
|
4378
|
+
|
|
4395
4379
|
if (this.customLocatorStrategies && this.customLocatorStrategies[locator.type]) {
|
|
4396
4380
|
strategyFunction = this.customLocatorStrategies[locator.type]
|
|
4397
4381
|
} else if (globalCustomLocatorStrategies.has(locator.type)) {
|
|
@@ -4967,7 +4951,7 @@ async function refreshContextSession() {
|
|
|
4967
4951
|
this.debugSection('Session', 'Skipping storage cleanup - no active page/context')
|
|
4968
4952
|
return
|
|
4969
4953
|
}
|
|
4970
|
-
|
|
4954
|
+
|
|
4971
4955
|
const currentUrl = await this.grabCurrentUrl()
|
|
4972
4956
|
|
|
4973
4957
|
if (currentUrl.startsWith('http')) {
|
package/lib/helper/REST.js
CHANGED
|
@@ -94,7 +94,9 @@ const config = {}
|
|
|
94
94
|
class REST extends Helper {
|
|
95
95
|
constructor(config) {
|
|
96
96
|
super(config)
|
|
97
|
-
|
|
97
|
+
|
|
98
|
+
// Set defaults first
|
|
99
|
+
const defaults = {
|
|
98
100
|
timeout: 10000,
|
|
99
101
|
defaultHeaders: {},
|
|
100
102
|
endpoint: '',
|
|
@@ -103,15 +105,16 @@ class REST extends Helper {
|
|
|
103
105
|
onResponse: null,
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
// Merge config with defaults
|
|
109
|
+
this._setConfig(config)
|
|
110
|
+
this.options = { ...defaults, ...this.options }
|
|
111
|
+
|
|
106
112
|
if (this.options.maxContentLength) {
|
|
107
113
|
const maxContentLength = this.options.maxUploadFileSize * 1024 * 1024
|
|
108
114
|
this.options.maxContentLength = maxContentLength
|
|
109
115
|
this.options.maxBodyLength = maxContentLength
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
// override defaults with config
|
|
113
|
-
this._setConfig(config)
|
|
114
|
-
|
|
115
118
|
this.headers = { ...this.options.defaultHeaders }
|
|
116
119
|
|
|
117
120
|
// Create an agent with SSL certificate
|
|
@@ -215,8 +218,8 @@ class REST extends Helper {
|
|
|
215
218
|
}
|
|
216
219
|
}
|
|
217
220
|
|
|
218
|
-
if (this.
|
|
219
|
-
await this.
|
|
221
|
+
if (this.options.onRequest) {
|
|
222
|
+
await this.options.onRequest(request)
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
try {
|
|
@@ -245,8 +248,8 @@ class REST extends Helper {
|
|
|
245
248
|
}
|
|
246
249
|
response = err.response
|
|
247
250
|
}
|
|
248
|
-
if (this.
|
|
249
|
-
await this.
|
|
251
|
+
if (this.options.onResponse) {
|
|
252
|
+
await this.options.onResponse(response)
|
|
250
253
|
}
|
|
251
254
|
try {
|
|
252
255
|
this.options.prettyPrintJson ? this.debugSection('Response', beautify(JSON.stringify(response.data))) : this.debugSection('Response', JSON.stringify(response.data))
|