codeceptjs 3.7.6-beta.2 → 3.7.6-beta.3
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/event.js +10 -1
- package/lib/helper/Appium.js +145 -25
- package/lib/helper/Playwright.js +2 -3
- package/lib/helper/Puppeteer.js +6 -6
- package/lib/output.js +51 -5
- package/lib/plugin/htmlReporter.js +31 -31
- package/lib/result.js +100 -23
- package/package.json +2 -2
- package/typings/promiseBasedTypes.d.ts +37 -25
- package/typings/types.d.ts +127 -30
package/lib/event.js
CHANGED
|
@@ -2,13 +2,22 @@ const debug = require('debug')('codeceptjs:event')
|
|
|
2
2
|
const events = require('events')
|
|
3
3
|
const { error } = require('./output')
|
|
4
4
|
|
|
5
|
+
const MAX_LISTENERS = 200
|
|
6
|
+
|
|
5
7
|
const dispatcher = new events.EventEmitter()
|
|
6
8
|
|
|
7
|
-
dispatcher.setMaxListeners(
|
|
9
|
+
dispatcher.setMaxListeners(MAX_LISTENERS)
|
|
10
|
+
|
|
11
|
+
// Increase process max listeners to prevent warnings for beforeExit and other events
|
|
12
|
+
if (typeof process.setMaxListeners === 'function') {
|
|
13
|
+
process.setMaxListeners(MAX_LISTENERS)
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* @namespace
|
|
10
18
|
* @alias event
|
|
11
19
|
*/
|
|
20
|
+
|
|
12
21
|
module.exports = {
|
|
13
22
|
/**
|
|
14
23
|
* @type {NodeJS.EventEmitter}
|
package/lib/helper/Appium.js
CHANGED
|
@@ -391,6 +391,29 @@ class Appium extends Webdriver {
|
|
|
391
391
|
return `${protocol}://${hostname}:${port}${normalizedPath}/session/${this.browser.sessionId}`
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Helper method to safely call isDisplayed() on mobile elements.
|
|
396
|
+
* Handles the case where webdriverio tries to use execute/sync which isn't supported in Appium.
|
|
397
|
+
* @private
|
|
398
|
+
*/
|
|
399
|
+
async _isDisplayedSafe(element) {
|
|
400
|
+
if (this.isWeb) {
|
|
401
|
+
// For web contexts, use the normal isDisplayed
|
|
402
|
+
return element.isDisplayed()
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
try {
|
|
406
|
+
return await element.isDisplayed()
|
|
407
|
+
} catch (err) {
|
|
408
|
+
// If isDisplayed fails due to execute/sync not being supported in native mobile contexts,
|
|
409
|
+
// fall back to assuming the element is displayed (since we found it)
|
|
410
|
+
if (err.message && err.message.includes('Method is not implemented')) {
|
|
411
|
+
return true
|
|
412
|
+
}
|
|
413
|
+
throw err
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
394
417
|
/**
|
|
395
418
|
* Execute code only on iOS
|
|
396
419
|
*
|
|
@@ -619,6 +642,7 @@ class Appium extends Webdriver {
|
|
|
619
642
|
*/
|
|
620
643
|
async resetApp() {
|
|
621
644
|
onlyForApps.call(this)
|
|
645
|
+
this.isWeb = false // Reset to native context after app reset
|
|
622
646
|
return this.axios({
|
|
623
647
|
method: 'post',
|
|
624
648
|
url: `${this._buildAppiumEndpoint()}/appium/app/reset`,
|
|
@@ -1134,7 +1158,7 @@ class Appium extends Webdriver {
|
|
|
1134
1158
|
],
|
|
1135
1159
|
},
|
|
1136
1160
|
])
|
|
1137
|
-
await this.browser.pause(
|
|
1161
|
+
await this.browser.pause(2000)
|
|
1138
1162
|
}
|
|
1139
1163
|
|
|
1140
1164
|
/**
|
|
@@ -1296,28 +1320,26 @@ class Appium extends Webdriver {
|
|
|
1296
1320
|
let currentSource
|
|
1297
1321
|
return browser
|
|
1298
1322
|
.waitUntil(
|
|
1299
|
-
() => {
|
|
1323
|
+
async () => {
|
|
1300
1324
|
if (err) {
|
|
1301
1325
|
return new Error(`Scroll to the end and element ${searchableLocator} was not found`)
|
|
1302
1326
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
})
|
|
1320
|
-
})
|
|
1327
|
+
const els = await browser.$$(parseLocator.call(this, searchableLocator))
|
|
1328
|
+
if (els.length) {
|
|
1329
|
+
const displayed = await this._isDisplayedSafe(els[0])
|
|
1330
|
+
if (displayed) {
|
|
1331
|
+
return true
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
await this[direction](scrollLocator, offset, speed)
|
|
1336
|
+
const source = await this.browser.getPageSource()
|
|
1337
|
+
if (source === currentSource) {
|
|
1338
|
+
err = true
|
|
1339
|
+
} else {
|
|
1340
|
+
currentSource = source
|
|
1341
|
+
return false
|
|
1342
|
+
}
|
|
1321
1343
|
},
|
|
1322
1344
|
timeout * 1000,
|
|
1323
1345
|
errorMsg,
|
|
@@ -1523,7 +1545,28 @@ class Appium extends Webdriver {
|
|
|
1523
1545
|
*/
|
|
1524
1546
|
async dontSeeElement(locator) {
|
|
1525
1547
|
if (this.isWeb) return super.dontSeeElement(locator)
|
|
1526
|
-
|
|
1548
|
+
|
|
1549
|
+
// For mobile native apps, use safe isDisplayed wrapper
|
|
1550
|
+
const parsedLocator = parseLocator.call(this, locator)
|
|
1551
|
+
const res = await this._locate(parsedLocator, false)
|
|
1552
|
+
const { truth } = require('../assert/truth')
|
|
1553
|
+
const Locator = require('../locator')
|
|
1554
|
+
|
|
1555
|
+
if (!res || res.length === 0) {
|
|
1556
|
+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').negate(false)
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
const selected = []
|
|
1560
|
+
for (const el of res) {
|
|
1561
|
+
const displayed = await this._isDisplayedSafe(el)
|
|
1562
|
+
if (displayed) selected.push(true)
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
try {
|
|
1566
|
+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').negate(selected)
|
|
1567
|
+
} catch (err) {
|
|
1568
|
+
throw err
|
|
1569
|
+
}
|
|
1527
1570
|
}
|
|
1528
1571
|
|
|
1529
1572
|
/**
|
|
@@ -1577,7 +1620,18 @@ class Appium extends Webdriver {
|
|
|
1577
1620
|
*/
|
|
1578
1621
|
async grabNumberOfVisibleElements(locator) {
|
|
1579
1622
|
if (this.isWeb) return super.grabNumberOfVisibleElements(locator)
|
|
1580
|
-
|
|
1623
|
+
|
|
1624
|
+
// For mobile native apps, use safe isDisplayed wrapper
|
|
1625
|
+
const parsedLocator = parseLocator.call(this, locator)
|
|
1626
|
+
const res = await this._locate(parsedLocator)
|
|
1627
|
+
|
|
1628
|
+
const selected = []
|
|
1629
|
+
for (const el of res) {
|
|
1630
|
+
const displayed = await this._isDisplayedSafe(el)
|
|
1631
|
+
if (displayed) selected.push(true)
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
return selected.length
|
|
1581
1635
|
}
|
|
1582
1636
|
|
|
1583
1637
|
/**
|
|
@@ -1656,7 +1710,30 @@ class Appium extends Webdriver {
|
|
|
1656
1710
|
*/
|
|
1657
1711
|
async seeElement(locator) {
|
|
1658
1712
|
if (this.isWeb) return super.seeElement(locator)
|
|
1659
|
-
|
|
1713
|
+
|
|
1714
|
+
// For mobile native apps, use safe isDisplayed wrapper
|
|
1715
|
+
const parsedLocator = parseLocator.call(this, locator)
|
|
1716
|
+
const res = await this._locate(parsedLocator, true)
|
|
1717
|
+
const ElementNotFound = require('./errors/ElementNotFound')
|
|
1718
|
+
const { truth } = require('../assert/truth')
|
|
1719
|
+
const { dontSeeElementError } = require('./errors/ElementAssertion')
|
|
1720
|
+
const Locator = require('../locator')
|
|
1721
|
+
|
|
1722
|
+
if (!res || res.length === 0) {
|
|
1723
|
+
throw new ElementNotFound(parsedLocator)
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
const selected = []
|
|
1727
|
+
for (const el of res) {
|
|
1728
|
+
const displayed = await this._isDisplayedSafe(el)
|
|
1729
|
+
if (displayed) selected.push(true)
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
try {
|
|
1733
|
+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').assert(selected)
|
|
1734
|
+
} catch (e) {
|
|
1735
|
+
dontSeeElementError(parsedLocator)
|
|
1736
|
+
}
|
|
1660
1737
|
}
|
|
1661
1738
|
|
|
1662
1739
|
/**
|
|
@@ -1703,7 +1780,30 @@ class Appium extends Webdriver {
|
|
|
1703
1780
|
*/
|
|
1704
1781
|
async waitForVisible(locator, sec = null) {
|
|
1705
1782
|
if (this.isWeb) return super.waitForVisible(locator, sec)
|
|
1706
|
-
|
|
1783
|
+
|
|
1784
|
+
// For mobile native apps, use safe isDisplayed wrapper
|
|
1785
|
+
const parsedLocator = parseLocator.call(this, locator)
|
|
1786
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1787
|
+
const Locator = require('../locator')
|
|
1788
|
+
|
|
1789
|
+
return this.browser.waitUntil(
|
|
1790
|
+
async () => {
|
|
1791
|
+
const res = await this._res(parsedLocator)
|
|
1792
|
+
if (!res || res.length === 0) return false
|
|
1793
|
+
|
|
1794
|
+
const selected = []
|
|
1795
|
+
for (const el of res) {
|
|
1796
|
+
const displayed = await this._isDisplayedSafe(el)
|
|
1797
|
+
if (displayed) selected.push(true)
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
return selected.length > 0
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
timeout: aSec * 1000,
|
|
1804
|
+
timeoutMsg: `element (${new Locator(parsedLocator)}) still not visible after ${aSec} sec`,
|
|
1805
|
+
},
|
|
1806
|
+
)
|
|
1707
1807
|
}
|
|
1708
1808
|
|
|
1709
1809
|
/**
|
|
@@ -1712,7 +1812,27 @@ class Appium extends Webdriver {
|
|
|
1712
1812
|
*/
|
|
1713
1813
|
async waitForInvisible(locator, sec = null) {
|
|
1714
1814
|
if (this.isWeb) return super.waitForInvisible(locator, sec)
|
|
1715
|
-
|
|
1815
|
+
|
|
1816
|
+
// For mobile native apps, use safe isDisplayed wrapper
|
|
1817
|
+
const parsedLocator = parseLocator.call(this, locator)
|
|
1818
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1819
|
+
const Locator = require('../locator')
|
|
1820
|
+
|
|
1821
|
+
return this.browser.waitUntil(
|
|
1822
|
+
async () => {
|
|
1823
|
+
const res = await this._res(parsedLocator)
|
|
1824
|
+
if (!res || res.length === 0) return true
|
|
1825
|
+
|
|
1826
|
+
const selected = []
|
|
1827
|
+
for (const el of res) {
|
|
1828
|
+
const displayed = await this._isDisplayedSafe(el)
|
|
1829
|
+
if (displayed) selected.push(true)
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
return selected.length === 0
|
|
1833
|
+
},
|
|
1834
|
+
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(parsedLocator)}) still visible after ${aSec} sec` },
|
|
1835
|
+
)
|
|
1716
1836
|
}
|
|
1717
1837
|
|
|
1718
1838
|
/**
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -370,7 +370,6 @@ class Playwright extends Helper {
|
|
|
370
370
|
if (typeof config.storageState !== 'undefined') {
|
|
371
371
|
this.storageState = config.storageState
|
|
372
372
|
}
|
|
373
|
-
|
|
374
373
|
}
|
|
375
374
|
|
|
376
375
|
_validateConfig(config) {
|
|
@@ -1844,7 +1843,7 @@ class Playwright extends Helper {
|
|
|
1844
1843
|
|
|
1845
1844
|
/**
|
|
1846
1845
|
*
|
|
1847
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
1846
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
1848
1847
|
*
|
|
1849
1848
|
* {{> pressKeyWithKeyNormalization }}
|
|
1850
1849
|
*/
|
|
@@ -3191,7 +3190,7 @@ class Playwright extends Helper {
|
|
|
3191
3190
|
/**
|
|
3192
3191
|
* Waits for navigation to finish. By default, it takes configured `waitForNavigation` option.
|
|
3193
3192
|
*
|
|
3194
|
-
* See [Playwright's reference](https://playwright.dev/docs/api/class-page
|
|
3193
|
+
* See [Playwright's reference](https://playwright.dev/docs/api/class-page#page-wait-for-navigation)
|
|
3195
3194
|
*
|
|
3196
3195
|
* @param {*} options
|
|
3197
3196
|
*/
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -64,7 +64,7 @@ const consoleLogStore = new Console()
|
|
|
64
64
|
* @prop {boolean} [keepBrowserState=false] - keep browser state between tests when `restart` is set to false.
|
|
65
65
|
* @prop {boolean} [keepCookies=false] - keep cookies between tests when `restart` is set to false.
|
|
66
66
|
* @prop {number} [waitForAction=100] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
67
|
-
* @prop {string} [waitForNavigation=load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/
|
|
67
|
+
* @prop {string|string[]} [waitForNavigation=load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.waitforoptions.md). Array values are accepted as well.
|
|
68
68
|
* @prop {number} [pressKeyDelay=10] - delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
|
|
69
69
|
* @prop {number} [getPageTimeout=30000] - config option to set maximum navigation time in milliseconds. If the timeout is set to 0, then timeout will be disabled.
|
|
70
70
|
* @prop {number} [waitForTimeout=1000] - default wait* timeout in ms.
|
|
@@ -72,13 +72,13 @@ const consoleLogStore = new Console()
|
|
|
72
72
|
* @prop {string} [userAgent] - user-agent string.
|
|
73
73
|
* @prop {boolean} [manualStart=false] - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
|
|
74
74
|
* @prop {string} [browser=chrome] - can be changed to `firefox` when using [puppeteer-firefox](https://codecept.io/helpers/Puppeteer-firefox).
|
|
75
|
-
* @prop {object} [chrome] - pass additional [Puppeteer run options](https://github.com/
|
|
75
|
+
* @prop {object} [chrome] - pass additional [Puppeteer run options](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.launchoptions.md).
|
|
76
76
|
* @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
77
77
|
*/
|
|
78
78
|
const config = {}
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* Uses [Google Chrome's Puppeteer](https://github.com/
|
|
81
|
+
* Uses [Google Chrome's Puppeteer](https://github.com/puppeteer/puppeteer) library to run tests inside headless Chrome.
|
|
82
82
|
* Browser control is executed via DevTools Protocol (instead of Selenium).
|
|
83
83
|
* This helper works with a browser out of the box with no additional tools required to install.
|
|
84
84
|
*
|
|
@@ -1349,7 +1349,7 @@ class Puppeteer extends Helper {
|
|
|
1349
1349
|
}
|
|
1350
1350
|
|
|
1351
1351
|
/**
|
|
1352
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
1352
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
1353
1353
|
*
|
|
1354
1354
|
* {{> pressKeyWithKeyNormalization }}
|
|
1355
1355
|
*/
|
|
@@ -2463,7 +2463,7 @@ class Puppeteer extends Helper {
|
|
|
2463
2463
|
/**
|
|
2464
2464
|
* Waits for navigation to finish. By default, takes configured `waitForNavigation` option.
|
|
2465
2465
|
*
|
|
2466
|
-
* See [Puppeteer's reference](https://github.com/
|
|
2466
|
+
* See [Puppeteer's reference](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.page.waitfornavigation.md)
|
|
2467
2467
|
*
|
|
2468
2468
|
* @param {*} opts
|
|
2469
2469
|
*/
|
|
@@ -3093,7 +3093,7 @@ async function getClickablePoint(el) {
|
|
|
3093
3093
|
}
|
|
3094
3094
|
|
|
3095
3095
|
// List of key values to key definitions
|
|
3096
|
-
// https://github.com/
|
|
3096
|
+
// https://github.com/puppeteer/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
|
|
3097
3097
|
const keyDefinitionMap = {
|
|
3098
3098
|
0: 'Digit0',
|
|
3099
3099
|
1: 'Digit1',
|
package/lib/output.js
CHANGED
|
@@ -50,7 +50,40 @@ module.exports = {
|
|
|
50
50
|
*/
|
|
51
51
|
process(process) {
|
|
52
52
|
if (process === null) return (outputProcess = '')
|
|
53
|
-
if (process)
|
|
53
|
+
if (process) {
|
|
54
|
+
// Handle objects by converting to empty string or extracting properties
|
|
55
|
+
let processValue = process
|
|
56
|
+
if (typeof process === 'object') {
|
|
57
|
+
// If it's an object, try to extract a numeric value or use empty string
|
|
58
|
+
processValue = process.id || process.index || process.worker || ''
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check if this is a run-multiple process (contains : or .)
|
|
62
|
+
// Format: "1.runName:browserName" from run-multiple
|
|
63
|
+
if (String(processValue).includes(':') || (String(processValue).includes('.') && String(processValue).split('.').length > 1)) {
|
|
64
|
+
// Keep original format for run-multiple
|
|
65
|
+
outputProcess = colors.cyan.bold(`[${processValue}]`)
|
|
66
|
+
} else {
|
|
67
|
+
// Standard worker format for run-workers
|
|
68
|
+
const processNum = parseInt(processValue, 10)
|
|
69
|
+
const processStr = !isNaN(processNum) ? String(processNum).padStart(2, '0') : String(processValue).padStart(2, '0')
|
|
70
|
+
|
|
71
|
+
// Assign different colors to different workers for better identification
|
|
72
|
+
const workerColors = [
|
|
73
|
+
colors.cyan, // Worker 01 - Cyan
|
|
74
|
+
colors.magenta, // Worker 02 - Magenta
|
|
75
|
+
colors.green, // Worker 03 - Green
|
|
76
|
+
colors.yellow, // Worker 04 - Yellow
|
|
77
|
+
colors.blue, // Worker 05 - Blue
|
|
78
|
+
colors.red, // Worker 06 - Red
|
|
79
|
+
colors.white, // Worker 07 - White
|
|
80
|
+
colors.gray, // Worker 08 - Gray
|
|
81
|
+
]
|
|
82
|
+
const workerIndex = !isNaN(processNum) ? processNum - 1 : -1
|
|
83
|
+
const colorFn = workerIndex >= 0 && workerColors[workerIndex % workerColors.length] ? workerColors[workerIndex % workerColors.length] : colors.cyan
|
|
84
|
+
outputProcess = colorFn.bold(`[Worker ${processStr}]`)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
54
87
|
return outputProcess
|
|
55
88
|
},
|
|
56
89
|
|
|
@@ -149,25 +182,38 @@ module.exports = {
|
|
|
149
182
|
* @param {Mocha.Test} test
|
|
150
183
|
*/
|
|
151
184
|
started(test) {
|
|
152
|
-
|
|
185
|
+
// Only show feature name in workers mode (when outputProcess is set)
|
|
186
|
+
const featureName = outputProcess && test.parent?.title ? `${colors.cyan.bold(test.parent.title)} › ` : ''
|
|
187
|
+
print(` ${featureName}${colors.magenta.bold(test.title)}`)
|
|
153
188
|
},
|
|
154
189
|
/**
|
|
155
190
|
* @param {Mocha.Test} test
|
|
156
191
|
*/
|
|
157
192
|
passed(test) {
|
|
158
|
-
|
|
193
|
+
// Only show feature name in workers mode (when outputProcess is set)
|
|
194
|
+
const featureName = outputProcess && test.parent?.title ? `${colors.cyan(test.parent.title)} › ` : ''
|
|
195
|
+
const scenarioName = colors.bold(test.title)
|
|
196
|
+
const executionTime = colors.cyan(`in ${test.duration}ms`)
|
|
197
|
+
print(` ${colors.green.bold(figures.tick)} ${featureName}${scenarioName} ${executionTime}`)
|
|
159
198
|
},
|
|
160
199
|
/**
|
|
161
200
|
* @param {Mocha.Test} test
|
|
162
201
|
*/
|
|
163
202
|
failed(test) {
|
|
164
|
-
|
|
203
|
+
// Only show feature name in workers mode (when outputProcess is set)
|
|
204
|
+
const featureName = outputProcess && test.parent?.title ? `${colors.yellow(test.parent.title)} › ` : ''
|
|
205
|
+
const scenarioName = colors.bold(test.title)
|
|
206
|
+
const executionTime = colors.yellow(`in ${test.duration}ms`)
|
|
207
|
+
print(` ${colors.red.bold(figures.cross)} ${featureName}${scenarioName} ${executionTime}`)
|
|
165
208
|
},
|
|
166
209
|
/**
|
|
167
210
|
* @param {Mocha.Test} test
|
|
168
211
|
*/
|
|
169
212
|
skipped(test) {
|
|
170
|
-
|
|
213
|
+
// Only show feature name in workers mode (when outputProcess is set)
|
|
214
|
+
const featureName = outputProcess && test.parent?.title ? `${colors.gray(test.parent.title)} › ` : ''
|
|
215
|
+
const scenarioName = colors.bold(test.title)
|
|
216
|
+
print(` ${colors.yellow.bold('S')} ${featureName}${scenarioName}`)
|
|
171
217
|
},
|
|
172
218
|
},
|
|
173
219
|
|
|
@@ -103,12 +103,12 @@ module.exports = function (config) {
|
|
|
103
103
|
// Method 1: Check retryNum property (most reliable)
|
|
104
104
|
if (test.retryNum && test.retryNum > 0) {
|
|
105
105
|
testRetryAttempts.set(testId, test.retryNum)
|
|
106
|
-
output.
|
|
106
|
+
output.debug(`HTML Reporter: Retry count detected (retryNum) for ${test.title}, attempts: ${test.retryNum}`)
|
|
107
107
|
}
|
|
108
108
|
// Method 2: Check currentRetry property
|
|
109
109
|
else if (test.currentRetry && test.currentRetry > 0) {
|
|
110
110
|
testRetryAttempts.set(testId, test.currentRetry)
|
|
111
|
-
output.
|
|
111
|
+
output.debug(`HTML Reporter: Retry count detected (currentRetry) for ${test.title}, attempts: ${test.currentRetry}`)
|
|
112
112
|
}
|
|
113
113
|
// Method 3: Check if this is a retried test
|
|
114
114
|
else if (test.retriedTest && test.retriedTest()) {
|
|
@@ -119,12 +119,12 @@ module.exports = function (config) {
|
|
|
119
119
|
} else {
|
|
120
120
|
testRetryAttempts.set(originalTestId, testRetryAttempts.get(originalTestId) + 1)
|
|
121
121
|
}
|
|
122
|
-
output.
|
|
122
|
+
output.debug(`HTML Reporter: Retry detected (retriedTest) for ${originalTest.title}, attempts: ${testRetryAttempts.get(originalTestId)}`)
|
|
123
123
|
}
|
|
124
124
|
// Method 4: Check if test has been seen before (indicating a retry)
|
|
125
125
|
else if (reportData.tests.some(t => t.id === testId)) {
|
|
126
126
|
testRetryAttempts.set(testId, 1) // First retry detected
|
|
127
|
-
output.
|
|
127
|
+
output.debug(`HTML Reporter: Retry detected (duplicate test) for ${test.title}, attempts: 1`)
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
})
|
|
@@ -196,20 +196,20 @@ module.exports = function (config) {
|
|
|
196
196
|
if (test.retryNum && test.retryNum > 0) {
|
|
197
197
|
retryAttempts = test.retryNum
|
|
198
198
|
testRetryAttempts.set(testId, retryAttempts)
|
|
199
|
-
output.
|
|
199
|
+
output.debug(`HTML Reporter: Late retry detection (retryNum) for ${test.title}, attempts: ${retryAttempts}`)
|
|
200
200
|
} else if (test.currentRetry && test.currentRetry > 0) {
|
|
201
201
|
retryAttempts = test.currentRetry
|
|
202
202
|
testRetryAttempts.set(testId, retryAttempts)
|
|
203
|
-
output.
|
|
203
|
+
output.debug(`HTML Reporter: Late retry detection (currentRetry) for ${test.title}, attempts: ${retryAttempts}`)
|
|
204
204
|
} else if (test._retries && test._retries > 0) {
|
|
205
205
|
retryAttempts = test._retries
|
|
206
206
|
testRetryAttempts.set(testId, retryAttempts)
|
|
207
|
-
output.
|
|
207
|
+
output.debug(`HTML Reporter: Late retry detection (_retries) for ${test.title}, attempts: ${retryAttempts}`)
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
// Debug logging
|
|
212
|
-
output.
|
|
212
|
+
output.debug(`HTML Reporter: Test finished - ${test.title}, State: ${test.state}, Retries: ${retryAttempts}`)
|
|
213
213
|
|
|
214
214
|
// Detect if this is a BDD/Gherkin test
|
|
215
215
|
const isBddTest = isBddGherkinTest(test, currentSuite)
|
|
@@ -222,7 +222,7 @@ module.exports = function (config) {
|
|
|
222
222
|
const currentlyFailed = test.state === 'failed'
|
|
223
223
|
|
|
224
224
|
// Debug artifacts collection (but don't process them yet - screenshots may not be ready)
|
|
225
|
-
output.
|
|
225
|
+
output.debug(`HTML Reporter: Test ${test.title} artifacts at test.finished: ${JSON.stringify(test.artifacts)}`)
|
|
226
226
|
|
|
227
227
|
const testData = {
|
|
228
228
|
...test,
|
|
@@ -244,11 +244,11 @@ module.exports = function (config) {
|
|
|
244
244
|
if (existingTestIndex >= 0) {
|
|
245
245
|
// Update existing test with final result (including failed state)
|
|
246
246
|
reportData.tests[existingTestIndex] = testData
|
|
247
|
-
output.
|
|
247
|
+
output.debug(`HTML Reporter: Updated existing test - ${test.title}, Final state: ${test.state}`)
|
|
248
248
|
} else {
|
|
249
249
|
// Add new test
|
|
250
250
|
reportData.tests.push(testData)
|
|
251
|
-
output.
|
|
251
|
+
output.debug(`HTML Reporter: Added new test - ${test.title}, State: ${test.state}`)
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
// Track retry information - only add if there were actual retries AND the test failed at some point
|
|
@@ -262,7 +262,7 @@ module.exports = function (config) {
|
|
|
262
262
|
if (retryAttempts === 0 && existingRetryIndex >= 0) {
|
|
263
263
|
retryAttempts = reportData.retries[existingRetryIndex].attempts + 1
|
|
264
264
|
testRetryAttempts.set(testId, retryAttempts)
|
|
265
|
-
output.
|
|
265
|
+
output.debug(`HTML Reporter: Incremented retry count for duplicate test ${test.title}, attempts: ${retryAttempts}`)
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// Remove existing retry info for this test and add updated one
|
|
@@ -274,7 +274,7 @@ module.exports = function (config) {
|
|
|
274
274
|
finalState: test.state,
|
|
275
275
|
duration: test.duration || 0,
|
|
276
276
|
})
|
|
277
|
-
output.
|
|
277
|
+
output.debug(`HTML Reporter: Added retry info for ${test.title}, attempts: ${retryAttempts}, state: ${test.state}`)
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// Fallback: If this test already exists and either failed before or is failing now, it's a retry
|
|
@@ -288,7 +288,7 @@ module.exports = function (config) {
|
|
|
288
288
|
finalState: test.state,
|
|
289
289
|
duration: test.duration || 0,
|
|
290
290
|
})
|
|
291
|
-
|
|
291
|
+
output.debug(`HTML Reporter: Fallback retry detection for failed test ${test.title}, attempts: ${fallbackAttempts}`)
|
|
292
292
|
}
|
|
293
293
|
})
|
|
294
294
|
|
|
@@ -298,40 +298,40 @@ module.exports = function (config) {
|
|
|
298
298
|
reportData.duration = reportData.endTime - reportData.startTime
|
|
299
299
|
|
|
300
300
|
// Process artifacts now that all async tasks (including screenshots) are complete
|
|
301
|
-
output.
|
|
301
|
+
output.debug(`HTML Reporter: Processing artifacts for ${reportData.tests.length} tests after all async tasks complete`)
|
|
302
302
|
|
|
303
303
|
reportData.tests.forEach(test => {
|
|
304
304
|
const originalArtifacts = test.artifacts
|
|
305
305
|
let collectedArtifacts = []
|
|
306
306
|
|
|
307
|
-
output.
|
|
308
|
-
output.
|
|
307
|
+
output.debug(`HTML Reporter: Processing test "${test.title}" (ID: ${test.id})`)
|
|
308
|
+
output.debug(`HTML Reporter: Test ${test.title} final artifacts: ${JSON.stringify(originalArtifacts)}`)
|
|
309
309
|
|
|
310
310
|
if (originalArtifacts) {
|
|
311
311
|
if (Array.isArray(originalArtifacts)) {
|
|
312
312
|
collectedArtifacts = originalArtifacts
|
|
313
|
-
output.
|
|
313
|
+
output.debug(`HTML Reporter: Using array artifacts: ${collectedArtifacts.length} items`)
|
|
314
314
|
} else if (typeof originalArtifacts === 'object') {
|
|
315
315
|
// Convert object properties to array (screenshotOnFail plugin format)
|
|
316
316
|
collectedArtifacts = Object.values(originalArtifacts).filter(artifact => artifact)
|
|
317
|
-
output.
|
|
318
|
-
output.
|
|
317
|
+
output.debug(`HTML Reporter: Converted artifacts object to array: ${collectedArtifacts.length} items`)
|
|
318
|
+
output.debug(`HTML Reporter: Converted artifacts: ${JSON.stringify(collectedArtifacts)}`)
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
// Only use filesystem fallback if no artifacts found from screenshotOnFail plugin
|
|
323
323
|
if (collectedArtifacts.length === 0 && test.state === 'failed') {
|
|
324
|
-
output.
|
|
324
|
+
output.debug(`HTML Reporter: No artifacts from plugin, trying filesystem for test "${test.title}"`)
|
|
325
325
|
collectedArtifacts = collectScreenshotsFromFilesystem(test, test.id)
|
|
326
|
-
output.
|
|
326
|
+
output.debug(`HTML Reporter: Collected ${collectedArtifacts.length} screenshots from filesystem for failed test "${test.title}"`)
|
|
327
327
|
if (collectedArtifacts.length > 0) {
|
|
328
|
-
output.
|
|
328
|
+
output.debug(`HTML Reporter: Filesystem screenshots for "${test.title}": ${JSON.stringify(collectedArtifacts)}`)
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
// Update test with processed artifacts
|
|
333
333
|
test.artifacts = collectedArtifacts
|
|
334
|
-
output.
|
|
334
|
+
output.debug(`HTML Reporter: Final artifacts for "${test.title}": ${JSON.stringify(test.artifacts)}`)
|
|
335
335
|
})
|
|
336
336
|
|
|
337
337
|
// Calculate stats from our collected test data instead of using result.stats
|
|
@@ -384,19 +384,19 @@ module.exports = function (config) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
// Debug logging for final stats
|
|
387
|
-
output.
|
|
388
|
-
output.
|
|
389
|
-
output.
|
|
390
|
-
output.
|
|
391
|
-
output.
|
|
387
|
+
output.debug(`HTML Reporter: Calculated stats - Tests: ${reportData.stats.tests}, Passes: ${reportData.stats.passes}, Failures: ${reportData.stats.failures}`)
|
|
388
|
+
output.debug(`HTML Reporter: Collected ${reportData.tests.length} tests in reportData`)
|
|
389
|
+
output.debug(`HTML Reporter: Failures array has ${reportData.failures.length} items`)
|
|
390
|
+
output.debug(`HTML Reporter: Retries array has ${reportData.retries.length} items`)
|
|
391
|
+
output.debug(`HTML Reporter: testRetryAttempts Map size: ${testRetryAttempts.size}`)
|
|
392
392
|
|
|
393
393
|
// Log retry attempts map contents
|
|
394
394
|
for (const [testId, attempts] of testRetryAttempts.entries()) {
|
|
395
|
-
output.
|
|
395
|
+
output.debug(`HTML Reporter: testRetryAttempts - ${testId}: ${attempts} attempts`)
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
reportData.tests.forEach(test => {
|
|
399
|
-
output.
|
|
399
|
+
output.debug(`HTML Reporter: Test in reportData - ${test.title}, State: ${test.state}, Retries: ${test.retryAttempts}`)
|
|
400
400
|
})
|
|
401
401
|
|
|
402
402
|
// Check if running with workers
|
package/lib/result.js
CHANGED
|
@@ -3,22 +3,21 @@ const path = require('path')
|
|
|
3
3
|
const { serializeTest } = require('./mocha/test')
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @
|
|
9
|
-
* @property {number}
|
|
10
|
-
* @property {number}
|
|
11
|
-
* @property {number}
|
|
12
|
-
* @property {
|
|
13
|
-
* @property {
|
|
14
|
-
* @property {
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
* @typedef {Object} Stats Statistics for a test result.
|
|
7
|
+
* @property {number} passes Number of passed tests.
|
|
8
|
+
* @property {number} failures Number of failed tests.
|
|
9
|
+
* @property {number} tests Total number of tests.
|
|
10
|
+
* @property {number} pending Number of pending tests.
|
|
11
|
+
* @property {number} failedHooks Number of failed hooks.
|
|
12
|
+
* @property {Date} start Start time of the test run.
|
|
13
|
+
* @property {Date} end End time of the test run.
|
|
14
|
+
* @property {number} duration Duration of the test run, in milliseconds.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result of a test run. Will be emitted for example in "event.all.result" events.
|
|
17
19
|
*/
|
|
18
20
|
class Result {
|
|
19
|
-
/**
|
|
20
|
-
* Create Result of the test run
|
|
21
|
-
*/
|
|
22
21
|
constructor() {
|
|
23
22
|
this._startTime = new Date()
|
|
24
23
|
this._endTime = null
|
|
@@ -27,6 +26,9 @@ class Result {
|
|
|
27
26
|
this.start()
|
|
28
27
|
}
|
|
29
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Resets all collected stats, tests, and failure reports.
|
|
31
|
+
*/
|
|
30
32
|
reset() {
|
|
31
33
|
this._stats = {
|
|
32
34
|
passes: 0,
|
|
@@ -39,43 +41,85 @@ class Result {
|
|
|
39
41
|
duration: 0,
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* @type {CodeceptJS.Test[]}
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
43
48
|
this._tests = []
|
|
44
49
|
|
|
45
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* @type {string[][]}
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
46
54
|
this._failures = []
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Sets the start time to the current time.
|
|
59
|
+
*/
|
|
49
60
|
start() {
|
|
50
61
|
this._startTime = new Date()
|
|
51
62
|
}
|
|
52
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Sets the end time to the current time.
|
|
66
|
+
*/
|
|
53
67
|
finish() {
|
|
54
68
|
this._endTime = new Date()
|
|
55
69
|
}
|
|
56
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Whether this result contains any failed tests.
|
|
73
|
+
*
|
|
74
|
+
* @type {boolean}
|
|
75
|
+
* @readonly
|
|
76
|
+
*/
|
|
57
77
|
get hasFailed() {
|
|
58
78
|
return this._stats.failures > 0
|
|
59
79
|
}
|
|
60
80
|
|
|
81
|
+
/**
|
|
82
|
+
* All collected tests.
|
|
83
|
+
*
|
|
84
|
+
* @type {CodeceptJS.Test[]}
|
|
85
|
+
* @readonly
|
|
86
|
+
*/
|
|
61
87
|
get tests() {
|
|
62
88
|
return this._tests
|
|
63
89
|
}
|
|
64
90
|
|
|
91
|
+
/**
|
|
92
|
+
* The failure reports (array of strings per failed test).
|
|
93
|
+
*
|
|
94
|
+
* @type {string[][]}
|
|
95
|
+
* @readonly
|
|
96
|
+
*/
|
|
65
97
|
get failures() {
|
|
66
98
|
return this._failures.filter(f => f && (!Array.isArray(f) || f.length > 0))
|
|
67
99
|
}
|
|
68
100
|
|
|
101
|
+
/**
|
|
102
|
+
* The test statistics.
|
|
103
|
+
*
|
|
104
|
+
* @type {Stats}
|
|
105
|
+
* @readonly
|
|
106
|
+
*/
|
|
69
107
|
get stats() {
|
|
70
108
|
return this._stats
|
|
71
109
|
}
|
|
72
110
|
|
|
111
|
+
/**
|
|
112
|
+
* The start time of the test run.
|
|
113
|
+
*
|
|
114
|
+
* @type {Date}
|
|
115
|
+
* @readonly
|
|
116
|
+
*/
|
|
73
117
|
get startTime() {
|
|
74
118
|
return this._startTime
|
|
75
119
|
}
|
|
76
120
|
|
|
77
121
|
/**
|
|
78
|
-
*
|
|
122
|
+
* Adds a test to this result.
|
|
79
123
|
*
|
|
80
124
|
* @param {CodeceptJS.Test} test
|
|
81
125
|
*/
|
|
@@ -90,34 +134,67 @@ class Result {
|
|
|
90
134
|
}
|
|
91
135
|
|
|
92
136
|
/**
|
|
93
|
-
*
|
|
137
|
+
* Adds failure reports to this result.
|
|
94
138
|
*
|
|
95
|
-
* @param {
|
|
139
|
+
* @param {string[][]} newFailures
|
|
96
140
|
*/
|
|
97
141
|
addFailures(newFailures) {
|
|
98
142
|
this._failures.push(...newFailures)
|
|
99
143
|
}
|
|
100
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Whether this result contains any failed tests.
|
|
147
|
+
*
|
|
148
|
+
* @type {boolean}
|
|
149
|
+
* @readonly
|
|
150
|
+
*/
|
|
101
151
|
get hasFailures() {
|
|
102
152
|
return this.stats.failures > 0
|
|
103
153
|
}
|
|
104
154
|
|
|
155
|
+
/**
|
|
156
|
+
* The duration of the test run, in milliseconds.
|
|
157
|
+
*
|
|
158
|
+
* @type {number}
|
|
159
|
+
* @readonly
|
|
160
|
+
*/
|
|
105
161
|
get duration() {
|
|
106
162
|
return this._endTime ? +this._endTime - +this._startTime : 0
|
|
107
163
|
}
|
|
108
164
|
|
|
165
|
+
/**
|
|
166
|
+
* All failed tests.
|
|
167
|
+
*
|
|
168
|
+
* @type {CodeceptJS.Test[]}
|
|
169
|
+
* readonly
|
|
170
|
+
*/
|
|
109
171
|
get failedTests() {
|
|
110
172
|
return this._tests.filter(test => test.state === 'failed')
|
|
111
173
|
}
|
|
112
174
|
|
|
175
|
+
/**
|
|
176
|
+
* All passed tests.
|
|
177
|
+
*
|
|
178
|
+
* @type {CodeceptJS.Test[]}
|
|
179
|
+
* @readonly
|
|
180
|
+
*/
|
|
113
181
|
get passedTests() {
|
|
114
182
|
return this._tests.filter(test => test.state === 'passed')
|
|
115
183
|
}
|
|
116
184
|
|
|
185
|
+
/**
|
|
186
|
+
* All skipped tests.
|
|
187
|
+
*
|
|
188
|
+
* @type {CodeceptJS.Test[]}
|
|
189
|
+
* @readonly
|
|
190
|
+
*/
|
|
117
191
|
get skippedTests() {
|
|
118
192
|
return this._tests.filter(test => test.state === 'skipped' || test.state === 'pending')
|
|
119
193
|
}
|
|
120
194
|
|
|
195
|
+
/**
|
|
196
|
+
* @returns {object} The JSON representation of this result.
|
|
197
|
+
*/
|
|
121
198
|
simplify() {
|
|
122
199
|
return {
|
|
123
200
|
hasFailed: this.hasFailed,
|
|
@@ -129,9 +206,9 @@ class Result {
|
|
|
129
206
|
}
|
|
130
207
|
|
|
131
208
|
/**
|
|
132
|
-
*
|
|
209
|
+
* Saves this result to a JSON file.
|
|
133
210
|
*
|
|
134
|
-
* @param {string} fileName
|
|
211
|
+
* @param {string} [fileName] Path to the JSON file, relative to `output_dir`. Defaults to "result.json".
|
|
135
212
|
*/
|
|
136
213
|
save(fileName) {
|
|
137
214
|
if (!fileName) fileName = 'result.json'
|
|
@@ -139,9 +216,9 @@ class Result {
|
|
|
139
216
|
}
|
|
140
217
|
|
|
141
218
|
/**
|
|
142
|
-
*
|
|
219
|
+
* Adds stats to this result.
|
|
143
220
|
*
|
|
144
|
-
* @param {
|
|
221
|
+
* @param {Partial<Stats>} [newStats]
|
|
145
222
|
*/
|
|
146
223
|
addStats(newStats = {}) {
|
|
147
224
|
this._stats.passes += newStats.passes || 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.7.6-beta.
|
|
3
|
+
"version": "3.7.6-beta.3",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"@pollyjs/core": "6.0.6",
|
|
139
139
|
"@types/chai": "5.2.2",
|
|
140
140
|
"@types/inquirer": "9.0.9",
|
|
141
|
-
"@types/node": "24.6.0",
|
|
141
|
+
"@types/node": "^24.6.0",
|
|
142
142
|
"@wdio/sauce-service": "9.12.5",
|
|
143
143
|
"@wdio/selenium-standalone-service": "8.15.0",
|
|
144
144
|
"@wdio/utils": "9.19.2",
|
|
@@ -2733,12 +2733,14 @@ declare namespace CodeceptJS {
|
|
|
2733
2733
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
2734
2734
|
* @property [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
|
|
2735
2735
|
* @property [testIdAttribute = data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
|
|
2736
|
-
* @property [customLocatorStrategies] - custom locator strategies. An object with keys as strategy names and values as JavaScript functions. Example: `{ byRole: (selector, root) => { return root.querySelector(
|
|
2736
|
+
* @property [customLocatorStrategies] - custom locator strategies. An object with keys as strategy names and values as JavaScript functions. Example: `{ byRole: (selector, root) => { return root.querySelector(`[role="${selector}"]`) } }`
|
|
2737
|
+
* @property [storageState] - Playwright storage state (path to JSON file or object)
|
|
2738
|
+
* passed directly to `browser.newContext`.
|
|
2739
|
+
* If a Scenario is declared with a `cookies` option (e.g. `Scenario('name', { cookies: [...] }, fn)`),
|
|
2740
|
+
* those cookies are used instead and the configured `storageState` is ignored (no merge).
|
|
2741
|
+
* May include session cookies, auth tokens, localStorage and (if captured with
|
|
2742
|
+
* `grabStorageState({ indexedDB: true })`) IndexedDB data; treat as sensitive and do not commit.
|
|
2737
2743
|
*/
|
|
2738
|
-
// @ts-ignore
|
|
2739
|
-
// @ts-ignore
|
|
2740
|
-
// @ts-ignore
|
|
2741
|
-
// @ts-ignore
|
|
2742
2744
|
type PlaywrightConfig = {
|
|
2743
2745
|
url?: string;
|
|
2744
2746
|
browser?: 'chromium' | 'firefox' | 'webkit' | 'electron';
|
|
@@ -2777,6 +2779,7 @@ declare namespace CodeceptJS {
|
|
|
2777
2779
|
recordHar?: any;
|
|
2778
2780
|
testIdAttribute?: string;
|
|
2779
2781
|
customLocatorStrategies?: any;
|
|
2782
|
+
storageState?: string | any;
|
|
2780
2783
|
};
|
|
2781
2784
|
/**
|
|
2782
2785
|
* Uses [Playwright](https://github.com/microsoft/playwright) library to run tests inside:
|
|
@@ -3688,7 +3691,7 @@ declare namespace CodeceptJS {
|
|
|
3688
3691
|
*/
|
|
3689
3692
|
pressKeyUp(key: string): Promise<any>;
|
|
3690
3693
|
/**
|
|
3691
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
3694
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
3692
3695
|
*
|
|
3693
3696
|
* Presses a key in the browser (on a focused element).
|
|
3694
3697
|
*
|
|
@@ -4087,6 +4090,27 @@ declare namespace CodeceptJS {
|
|
|
4087
4090
|
* @param [name = null] - cookie name.
|
|
4088
4091
|
*/
|
|
4089
4092
|
grabCookie(name?: string): Promise<any>;
|
|
4093
|
+
/**
|
|
4094
|
+
* Grab the current storage state (cookies, localStorage, etc.) via Playwright's `browserContext.storageState()`.
|
|
4095
|
+
* Returns the raw object that Playwright provides.
|
|
4096
|
+
*
|
|
4097
|
+
* Security: The returned object can contain authentication tokens, session cookies
|
|
4098
|
+
* and (when `indexedDB: true` is used) data that may include user PII. Treat it as a secret.
|
|
4099
|
+
* Avoid committing it to source control and prefer storing it in a protected secrets store / CI artifact vault.
|
|
4100
|
+
* @param [options.indexedDB] - set to true to include IndexedDB in snapshot (Playwright >=1.51)
|
|
4101
|
+
*
|
|
4102
|
+
* ```js
|
|
4103
|
+
* // basic usage
|
|
4104
|
+
* const state = await I.grabStorageState();
|
|
4105
|
+
* require('fs').writeFileSync('authState.json', JSON.stringify(state));
|
|
4106
|
+
*
|
|
4107
|
+
* // include IndexedDB when using Firebase Auth, etc.
|
|
4108
|
+
* const stateWithIDB = await I.grabStorageState({ indexedDB: true });
|
|
4109
|
+
* ```
|
|
4110
|
+
*/
|
|
4111
|
+
grabStorageState(options?: {
|
|
4112
|
+
indexedDB?: boolean;
|
|
4113
|
+
}): Promise<any>;
|
|
4090
4114
|
/**
|
|
4091
4115
|
* Clears a cookie by name,
|
|
4092
4116
|
* if none provided clears all cookies.
|
|
@@ -4517,7 +4541,7 @@ declare namespace CodeceptJS {
|
|
|
4517
4541
|
/**
|
|
4518
4542
|
* Waits for navigation to finish. By default, it takes configured `waitForNavigation` option.
|
|
4519
4543
|
*
|
|
4520
|
-
* See [Playwright's reference](https://playwright.dev/docs/api/class-page
|
|
4544
|
+
* See [Playwright's reference](https://playwright.dev/docs/api/class-page#page-wait-for-navigation)
|
|
4521
4545
|
*/
|
|
4522
4546
|
waitForNavigation(options: any): Promise<any>;
|
|
4523
4547
|
/**
|
|
@@ -6105,7 +6129,7 @@ declare namespace CodeceptJS {
|
|
|
6105
6129
|
* @property [keepBrowserState = false] - keep browser state between tests when `restart` is set to false.
|
|
6106
6130
|
* @property [keepCookies = false] - keep cookies between tests when `restart` is set to false.
|
|
6107
6131
|
* @property [waitForAction = 100] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
6108
|
-
* @property [waitForNavigation = load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/
|
|
6132
|
+
* @property [waitForNavigation = load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.waitforoptions.md). Array values are accepted as well.
|
|
6109
6133
|
* @property [pressKeyDelay = 10] - delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
|
|
6110
6134
|
* @property [getPageTimeout = 30000] - config option to set maximum navigation time in milliseconds. If the timeout is set to 0, then timeout will be disabled.
|
|
6111
6135
|
* @property [waitForTimeout = 1000] - default wait* timeout in ms.
|
|
@@ -6113,13 +6137,9 @@ declare namespace CodeceptJS {
|
|
|
6113
6137
|
* @property [userAgent] - user-agent string.
|
|
6114
6138
|
* @property [manualStart = false] - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
|
|
6115
6139
|
* @property [browser = chrome] - can be changed to `firefox` when using [puppeteer-firefox](https://codecept.io/helpers/Puppeteer-firefox).
|
|
6116
|
-
* @property [chrome] - pass additional [Puppeteer run options](https://github.com/
|
|
6140
|
+
* @property [chrome] - pass additional [Puppeteer run options](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.launchoptions.md).
|
|
6117
6141
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
6118
6142
|
*/
|
|
6119
|
-
// @ts-ignore
|
|
6120
|
-
// @ts-ignore
|
|
6121
|
-
// @ts-ignore
|
|
6122
|
-
// @ts-ignore
|
|
6123
6143
|
type PuppeteerConfig = {
|
|
6124
6144
|
url: string;
|
|
6125
6145
|
basicAuth?: any;
|
|
@@ -6133,7 +6153,7 @@ declare namespace CodeceptJS {
|
|
|
6133
6153
|
keepBrowserState?: boolean;
|
|
6134
6154
|
keepCookies?: boolean;
|
|
6135
6155
|
waitForAction?: number;
|
|
6136
|
-
waitForNavigation?: string;
|
|
6156
|
+
waitForNavigation?: string | string[];
|
|
6137
6157
|
pressKeyDelay?: number;
|
|
6138
6158
|
getPageTimeout?: number;
|
|
6139
6159
|
waitForTimeout?: number;
|
|
@@ -6145,7 +6165,7 @@ declare namespace CodeceptJS {
|
|
|
6145
6165
|
highlightElement?: boolean;
|
|
6146
6166
|
};
|
|
6147
6167
|
/**
|
|
6148
|
-
* Uses [Google Chrome's Puppeteer](https://github.com/
|
|
6168
|
+
* Uses [Google Chrome's Puppeteer](https://github.com/puppeteer/puppeteer) library to run tests inside headless Chrome.
|
|
6149
6169
|
* Browser control is executed via DevTools Protocol (instead of Selenium).
|
|
6150
6170
|
* This helper works with a browser out of the box with no additional tools required to install.
|
|
6151
6171
|
*
|
|
@@ -6887,7 +6907,7 @@ declare namespace CodeceptJS {
|
|
|
6887
6907
|
*/
|
|
6888
6908
|
pressKeyUp(key: string): Promise<any>;
|
|
6889
6909
|
/**
|
|
6890
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
6910
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
6891
6911
|
*
|
|
6892
6912
|
* Presses a key in the browser (on a focused element).
|
|
6893
6913
|
*
|
|
@@ -7735,7 +7755,7 @@ declare namespace CodeceptJS {
|
|
|
7735
7755
|
/**
|
|
7736
7756
|
* Waits for navigation to finish. By default, takes configured `waitForNavigation` option.
|
|
7737
7757
|
*
|
|
7738
|
-
* See [Puppeteer's reference](https://github.com/
|
|
7758
|
+
* See [Puppeteer's reference](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.page.waitfornavigation.md)
|
|
7739
7759
|
*/
|
|
7740
7760
|
waitForNavigation(opts: any): Promise<any>;
|
|
7741
7761
|
/**
|
|
@@ -7964,10 +7984,6 @@ declare namespace CodeceptJS {
|
|
|
7964
7984
|
* @property [onResponse] - an async function which can update response object.
|
|
7965
7985
|
* @property [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
7966
7986
|
*/
|
|
7967
|
-
// @ts-ignore
|
|
7968
|
-
// @ts-ignore
|
|
7969
|
-
// @ts-ignore
|
|
7970
|
-
// @ts-ignore
|
|
7971
7987
|
type RESTConfig = {
|
|
7972
7988
|
endpoint?: string;
|
|
7973
7989
|
prettyPrintJson?: boolean;
|
|
@@ -9123,10 +9139,6 @@ declare namespace CodeceptJS {
|
|
|
9123
9139
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
9124
9140
|
* @property [logLevel = silent] - level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: https://webdriver.io/docs/configuration/#loglevel
|
|
9125
9141
|
*/
|
|
9126
|
-
// @ts-ignore
|
|
9127
|
-
// @ts-ignore
|
|
9128
|
-
// @ts-ignore
|
|
9129
|
-
// @ts-ignore
|
|
9130
9142
|
type WebDriverConfig = {
|
|
9131
9143
|
url: string;
|
|
9132
9144
|
browser: string;
|
package/typings/types.d.ts
CHANGED
|
@@ -2823,12 +2823,14 @@ declare namespace CodeceptJS {
|
|
|
2823
2823
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
2824
2824
|
* @property [recordHar] - record HAR and will be saved to `output/har`. See more of [HAR options](https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har).
|
|
2825
2825
|
* @property [testIdAttribute = data-testid] - locate elements based on the testIdAttribute. See more of [locate by test id](https://playwright.dev/docs/locators#locate-by-test-id).
|
|
2826
|
-
* @property [customLocatorStrategies] - custom locator strategies. An object with keys as strategy names and values as JavaScript functions. Example: `{ byRole: (selector, root) => { return root.querySelector(
|
|
2826
|
+
* @property [customLocatorStrategies] - custom locator strategies. An object with keys as strategy names and values as JavaScript functions. Example: `{ byRole: (selector, root) => { return root.querySelector(`[role="${selector}"]`) } }`
|
|
2827
|
+
* @property [storageState] - Playwright storage state (path to JSON file or object)
|
|
2828
|
+
* passed directly to `browser.newContext`.
|
|
2829
|
+
* If a Scenario is declared with a `cookies` option (e.g. `Scenario('name', { cookies: [...] }, fn)`),
|
|
2830
|
+
* those cookies are used instead and the configured `storageState` is ignored (no merge).
|
|
2831
|
+
* May include session cookies, auth tokens, localStorage and (if captured with
|
|
2832
|
+
* `grabStorageState({ indexedDB: true })`) IndexedDB data; treat as sensitive and do not commit.
|
|
2827
2833
|
*/
|
|
2828
|
-
// @ts-ignore
|
|
2829
|
-
// @ts-ignore
|
|
2830
|
-
// @ts-ignore
|
|
2831
|
-
// @ts-ignore
|
|
2832
2834
|
type PlaywrightConfig = {
|
|
2833
2835
|
url?: string;
|
|
2834
2836
|
browser?: 'chromium' | 'firefox' | 'webkit' | 'electron';
|
|
@@ -2867,6 +2869,7 @@ declare namespace CodeceptJS {
|
|
|
2867
2869
|
recordHar?: any;
|
|
2868
2870
|
testIdAttribute?: string;
|
|
2869
2871
|
customLocatorStrategies?: any;
|
|
2872
|
+
storageState?: string | any;
|
|
2870
2873
|
};
|
|
2871
2874
|
/**
|
|
2872
2875
|
* Uses [Playwright](https://github.com/microsoft/playwright) library to run tests inside:
|
|
@@ -3807,7 +3810,7 @@ declare namespace CodeceptJS {
|
|
|
3807
3810
|
*/
|
|
3808
3811
|
pressKeyUp(key: string): void;
|
|
3809
3812
|
/**
|
|
3810
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
3813
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
3811
3814
|
*
|
|
3812
3815
|
* Presses a key in the browser (on a focused element).
|
|
3813
3816
|
*
|
|
@@ -4229,6 +4232,27 @@ declare namespace CodeceptJS {
|
|
|
4229
4232
|
* @returns attribute value
|
|
4230
4233
|
*/
|
|
4231
4234
|
grabCookie(name?: string): any;
|
|
4235
|
+
/**
|
|
4236
|
+
* Grab the current storage state (cookies, localStorage, etc.) via Playwright's `browserContext.storageState()`.
|
|
4237
|
+
* Returns the raw object that Playwright provides.
|
|
4238
|
+
*
|
|
4239
|
+
* Security: The returned object can contain authentication tokens, session cookies
|
|
4240
|
+
* and (when `indexedDB: true` is used) data that may include user PII. Treat it as a secret.
|
|
4241
|
+
* Avoid committing it to source control and prefer storing it in a protected secrets store / CI artifact vault.
|
|
4242
|
+
* @param [options.indexedDB] - set to true to include IndexedDB in snapshot (Playwright >=1.51)
|
|
4243
|
+
*
|
|
4244
|
+
* ```js
|
|
4245
|
+
* // basic usage
|
|
4246
|
+
* const state = await I.grabStorageState();
|
|
4247
|
+
* require('fs').writeFileSync('authState.json', JSON.stringify(state));
|
|
4248
|
+
*
|
|
4249
|
+
* // include IndexedDB when using Firebase Auth, etc.
|
|
4250
|
+
* const stateWithIDB = await I.grabStorageState({ indexedDB: true });
|
|
4251
|
+
* ```
|
|
4252
|
+
*/
|
|
4253
|
+
grabStorageState(options?: {
|
|
4254
|
+
indexedDB?: boolean;
|
|
4255
|
+
}): void;
|
|
4232
4256
|
/**
|
|
4233
4257
|
* Clears a cookie by name,
|
|
4234
4258
|
* if none provided clears all cookies.
|
|
@@ -4680,7 +4704,7 @@ declare namespace CodeceptJS {
|
|
|
4680
4704
|
/**
|
|
4681
4705
|
* Waits for navigation to finish. By default, it takes configured `waitForNavigation` option.
|
|
4682
4706
|
*
|
|
4683
|
-
* See [Playwright's reference](https://playwright.dev/docs/api/class-page
|
|
4707
|
+
* See [Playwright's reference](https://playwright.dev/docs/api/class-page#page-wait-for-navigation)
|
|
4684
4708
|
*/
|
|
4685
4709
|
waitForNavigation(options: any): void;
|
|
4686
4710
|
/**
|
|
@@ -6346,7 +6370,7 @@ declare namespace CodeceptJS {
|
|
|
6346
6370
|
* @property [keepBrowserState = false] - keep browser state between tests when `restart` is set to false.
|
|
6347
6371
|
* @property [keepCookies = false] - keep cookies between tests when `restart` is set to false.
|
|
6348
6372
|
* @property [waitForAction = 100] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
6349
|
-
* @property [waitForNavigation = load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/
|
|
6373
|
+
* @property [waitForNavigation = load] - when to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.waitforoptions.md). Array values are accepted as well.
|
|
6350
6374
|
* @property [pressKeyDelay = 10] - delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
|
|
6351
6375
|
* @property [getPageTimeout = 30000] - config option to set maximum navigation time in milliseconds. If the timeout is set to 0, then timeout will be disabled.
|
|
6352
6376
|
* @property [waitForTimeout = 1000] - default wait* timeout in ms.
|
|
@@ -6354,13 +6378,9 @@ declare namespace CodeceptJS {
|
|
|
6354
6378
|
* @property [userAgent] - user-agent string.
|
|
6355
6379
|
* @property [manualStart = false] - do not start browser before a test, start it manually inside a helper with `this.helpers["Puppeteer"]._startBrowser()`.
|
|
6356
6380
|
* @property [browser = chrome] - can be changed to `firefox` when using [puppeteer-firefox](https://codecept.io/helpers/Puppeteer-firefox).
|
|
6357
|
-
* @property [chrome] - pass additional [Puppeteer run options](https://github.com/
|
|
6381
|
+
* @property [chrome] - pass additional [Puppeteer run options](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.launchoptions.md).
|
|
6358
6382
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
6359
6383
|
*/
|
|
6360
|
-
// @ts-ignore
|
|
6361
|
-
// @ts-ignore
|
|
6362
|
-
// @ts-ignore
|
|
6363
|
-
// @ts-ignore
|
|
6364
6384
|
type PuppeteerConfig = {
|
|
6365
6385
|
url: string;
|
|
6366
6386
|
basicAuth?: any;
|
|
@@ -6374,7 +6394,7 @@ declare namespace CodeceptJS {
|
|
|
6374
6394
|
keepBrowserState?: boolean;
|
|
6375
6395
|
keepCookies?: boolean;
|
|
6376
6396
|
waitForAction?: number;
|
|
6377
|
-
waitForNavigation?: string;
|
|
6397
|
+
waitForNavigation?: string | string[];
|
|
6378
6398
|
pressKeyDelay?: number;
|
|
6379
6399
|
getPageTimeout?: number;
|
|
6380
6400
|
waitForTimeout?: number;
|
|
@@ -6386,7 +6406,7 @@ declare namespace CodeceptJS {
|
|
|
6386
6406
|
highlightElement?: boolean;
|
|
6387
6407
|
};
|
|
6388
6408
|
/**
|
|
6389
|
-
* Uses [Google Chrome's Puppeteer](https://github.com/
|
|
6409
|
+
* Uses [Google Chrome's Puppeteer](https://github.com/puppeteer/puppeteer) library to run tests inside headless Chrome.
|
|
6390
6410
|
* Browser control is executed via DevTools Protocol (instead of Selenium).
|
|
6391
6411
|
* This helper works with a browser out of the box with no additional tools required to install.
|
|
6392
6412
|
*
|
|
@@ -7178,7 +7198,7 @@ declare namespace CodeceptJS {
|
|
|
7178
7198
|
*/
|
|
7179
7199
|
pressKeyUp(key: string): void;
|
|
7180
7200
|
/**
|
|
7181
|
-
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([
|
|
7201
|
+
* _Note:_ Shortcuts like `'Meta'` + `'A'` do not work on macOS ([puppeteer/puppeteer#1313](https://github.com/puppeteer/puppeteer/issues/1313)).
|
|
7182
7202
|
*
|
|
7183
7203
|
* Presses a key in the browser (on a focused element).
|
|
7184
7204
|
*
|
|
@@ -8104,7 +8124,7 @@ declare namespace CodeceptJS {
|
|
|
8104
8124
|
/**
|
|
8105
8125
|
* Waits for navigation to finish. By default, takes configured `waitForNavigation` option.
|
|
8106
8126
|
*
|
|
8107
|
-
* See [Puppeteer's reference](https://github.com/
|
|
8127
|
+
* See [Puppeteer's reference](https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.page.waitfornavigation.md)
|
|
8108
8128
|
*/
|
|
8109
8129
|
waitForNavigation(opts: any): void;
|
|
8110
8130
|
/**
|
|
@@ -8341,10 +8361,6 @@ declare namespace CodeceptJS {
|
|
|
8341
8361
|
* @property [onResponse] - an async function which can update response object.
|
|
8342
8362
|
* @property [maxUploadFileSize] - set the max content file size in MB when performing api calls.
|
|
8343
8363
|
*/
|
|
8344
|
-
// @ts-ignore
|
|
8345
|
-
// @ts-ignore
|
|
8346
|
-
// @ts-ignore
|
|
8347
|
-
// @ts-ignore
|
|
8348
8364
|
type RESTConfig = {
|
|
8349
8365
|
endpoint?: string;
|
|
8350
8366
|
prettyPrintJson?: boolean;
|
|
@@ -9560,10 +9576,6 @@ declare namespace CodeceptJS {
|
|
|
9560
9576
|
* @property [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
9561
9577
|
* @property [logLevel = silent] - level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: https://webdriver.io/docs/configuration/#loglevel
|
|
9562
9578
|
*/
|
|
9563
|
-
// @ts-ignore
|
|
9564
|
-
// @ts-ignore
|
|
9565
|
-
// @ts-ignore
|
|
9566
|
-
// @ts-ignore
|
|
9567
9579
|
type WebDriverConfig = {
|
|
9568
9580
|
url: string;
|
|
9569
9581
|
browser: string;
|
|
@@ -11580,11 +11592,11 @@ declare namespace CodeceptJS {
|
|
|
11580
11592
|
/**
|
|
11581
11593
|
* Executes bootstrap.
|
|
11582
11594
|
*/
|
|
11583
|
-
bootstrap(): void
|
|
11595
|
+
bootstrap(): Promise<void>;
|
|
11584
11596
|
/**
|
|
11585
11597
|
* Executes teardown.
|
|
11586
11598
|
*/
|
|
11587
|
-
teardown(): void
|
|
11599
|
+
teardown(): Promise<void>;
|
|
11588
11600
|
/**
|
|
11589
11601
|
* Loads tests by pattern or by config.tests
|
|
11590
11602
|
*/
|
|
@@ -11600,6 +11612,11 @@ declare namespace CodeceptJS {
|
|
|
11600
11612
|
* Run a specific test or all loaded tests.
|
|
11601
11613
|
*/
|
|
11602
11614
|
run(test?: string): Promise<void>;
|
|
11615
|
+
/**
|
|
11616
|
+
* Returns the version string of CodeceptJS.
|
|
11617
|
+
* @returns The version string.
|
|
11618
|
+
*/
|
|
11619
|
+
static version(): string;
|
|
11603
11620
|
}
|
|
11604
11621
|
/**
|
|
11605
11622
|
* Current configuration
|
|
@@ -11642,7 +11659,15 @@ declare namespace CodeceptJS {
|
|
|
11642
11659
|
};
|
|
11643
11660
|
}
|
|
11644
11661
|
/**
|
|
11645
|
-
*
|
|
11662
|
+
* Statistics for a test result.
|
|
11663
|
+
* @property passes - Number of passed tests.
|
|
11664
|
+
* @property failures - Number of failed tests.
|
|
11665
|
+
* @property tests - Total number of tests.
|
|
11666
|
+
* @property pending - Number of pending tests.
|
|
11667
|
+
* @property failedHooks - Number of failed hooks.
|
|
11668
|
+
* @property start - Start time of the test run.
|
|
11669
|
+
* @property end - End time of the test run.
|
|
11670
|
+
* @property duration - Duration of the test run, in milliseconds.
|
|
11646
11671
|
*/
|
|
11647
11672
|
type Stats = {
|
|
11648
11673
|
passes: number;
|
|
@@ -11655,10 +11680,82 @@ declare namespace CodeceptJS {
|
|
|
11655
11680
|
duration: number;
|
|
11656
11681
|
};
|
|
11657
11682
|
/**
|
|
11658
|
-
*
|
|
11683
|
+
* Result of a test run. Will be emitted for example in "event.all.result" events.
|
|
11659
11684
|
*/
|
|
11660
11685
|
class Result {
|
|
11661
|
-
|
|
11686
|
+
/**
|
|
11687
|
+
* Resets all collected stats, tests, and failure reports.
|
|
11688
|
+
*/
|
|
11689
|
+
reset(): void;
|
|
11690
|
+
/**
|
|
11691
|
+
* Sets the start time to the current time.
|
|
11692
|
+
*/
|
|
11693
|
+
start(): void;
|
|
11694
|
+
/**
|
|
11695
|
+
* Sets the end time to the current time.
|
|
11696
|
+
*/
|
|
11697
|
+
finish(): void;
|
|
11698
|
+
/**
|
|
11699
|
+
* Whether this result contains any failed tests.
|
|
11700
|
+
*/
|
|
11701
|
+
readonly hasFailed: boolean;
|
|
11702
|
+
/**
|
|
11703
|
+
* All collected tests.
|
|
11704
|
+
*/
|
|
11705
|
+
readonly tests: CodeceptJS.Test[];
|
|
11706
|
+
/**
|
|
11707
|
+
* The failure reports (array of strings per failed test).
|
|
11708
|
+
*/
|
|
11709
|
+
readonly failures: string[][];
|
|
11710
|
+
/**
|
|
11711
|
+
* The test statistics.
|
|
11712
|
+
*/
|
|
11713
|
+
readonly stats: Stats;
|
|
11714
|
+
/**
|
|
11715
|
+
* The start time of the test run.
|
|
11716
|
+
*/
|
|
11717
|
+
readonly startTime: Date;
|
|
11718
|
+
/**
|
|
11719
|
+
* Adds a test to this result.
|
|
11720
|
+
*/
|
|
11721
|
+
addTest(test: CodeceptJS.Test): void;
|
|
11722
|
+
/**
|
|
11723
|
+
* Adds failure reports to this result.
|
|
11724
|
+
*/
|
|
11725
|
+
addFailures(newFailures: string[][]): void;
|
|
11726
|
+
/**
|
|
11727
|
+
* Whether this result contains any failed tests.
|
|
11728
|
+
*/
|
|
11729
|
+
readonly hasFailures: boolean;
|
|
11730
|
+
/**
|
|
11731
|
+
* The duration of the test run, in milliseconds.
|
|
11732
|
+
*/
|
|
11733
|
+
readonly duration: number;
|
|
11734
|
+
/**
|
|
11735
|
+
* All failed tests.
|
|
11736
|
+
*/
|
|
11737
|
+
failedTests: CodeceptJS.Test[];
|
|
11738
|
+
/**
|
|
11739
|
+
* All passed tests.
|
|
11740
|
+
*/
|
|
11741
|
+
readonly passedTests: CodeceptJS.Test[];
|
|
11742
|
+
/**
|
|
11743
|
+
* All skipped tests.
|
|
11744
|
+
*/
|
|
11745
|
+
readonly skippedTests: CodeceptJS.Test[];
|
|
11746
|
+
/**
|
|
11747
|
+
* @returns The JSON representation of this result.
|
|
11748
|
+
*/
|
|
11749
|
+
simplify(): any;
|
|
11750
|
+
/**
|
|
11751
|
+
* Saves this result to a JSON file.
|
|
11752
|
+
* @param [fileName] - Path to the JSON file, relative to `output_dir`. Defaults to "result.json".
|
|
11753
|
+
*/
|
|
11754
|
+
save(fileName?: string): void;
|
|
11755
|
+
/**
|
|
11756
|
+
* Adds stats to this result.
|
|
11757
|
+
*/
|
|
11758
|
+
addStats(newStats?: Partial<Stats>): void;
|
|
11662
11759
|
}
|
|
11663
11760
|
/**
|
|
11664
11761
|
* Dependency Injection Container
|