codeceptjs 4.0.0-rc.23 → 4.0.0-rc.24

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.
Files changed (73) hide show
  1. package/README.md +9 -10
  2. package/docs/ai.md +3 -51
  3. package/docs/architecture.md +16 -0
  4. package/docs/bootstrap.md +1 -1
  5. package/docs/continuous-integration.md +16 -44
  6. package/docs/custom-helpers.md +1 -1
  7. package/docs/detox.md +1 -1
  8. package/docs/docker.md +1 -30
  9. package/docs/examples.md +0 -1
  10. package/docs/helpers/Appium.md +16 -2
  11. package/docs/helpers/Playwright.md +161 -160
  12. package/docs/helpers/Puppeteer.md +143 -250
  13. package/docs/helpers/WebDriver.md +134 -177
  14. package/docs/hooks.md +11 -1
  15. package/docs/index.md +1 -1
  16. package/docs/installation.md +2 -19
  17. package/docs/locators.md +1 -1
  18. package/docs/migrate-from-cypress.md +98 -0
  19. package/docs/migrate-from-java.md +108 -0
  20. package/docs/migrate-from-protractor.md +101 -0
  21. package/docs/migrate-from-testcafe.md +99 -0
  22. package/docs/migration-4.md +195 -8
  23. package/docs/plugins/aiTrace.md +49 -0
  24. package/docs/plugins/analyze.md +66 -0
  25. package/docs/plugins/auth.md +241 -0
  26. package/docs/plugins/autoDelay.md +48 -0
  27. package/docs/plugins/browser.md +41 -0
  28. package/docs/plugins/coverage.md +39 -0
  29. package/docs/plugins/customLocator.md +119 -0
  30. package/docs/plugins/customReporter.md +16 -0
  31. package/docs/plugins/expose.md +75 -0
  32. package/docs/plugins/heal.md +44 -0
  33. package/docs/plugins/junitReporter.md +51 -0
  34. package/docs/plugins/pageInfo.md +34 -0
  35. package/docs/plugins/pause.md +43 -0
  36. package/docs/plugins/pauseOnFail.md +18 -0
  37. package/docs/plugins/retryFailedStep.md +75 -0
  38. package/docs/plugins/screencast.md +55 -0
  39. package/docs/plugins/screenshot.md +58 -0
  40. package/docs/plugins/screenshotOnFail.md +18 -0
  41. package/docs/plugins/stepTimeout.md +65 -0
  42. package/docs/plugins.md +40 -862
  43. package/docs/reports.md +18 -4
  44. package/docs/retry.md +48 -18
  45. package/docs/store.md +94 -0
  46. package/docs/timeouts.md +1 -1
  47. package/docs/tutorial.md +207 -155
  48. package/docs/webdriver.md +6 -73
  49. package/lib/actor.js +0 -35
  50. package/lib/command/run-multiple.js +1 -2
  51. package/lib/helper/Playwright.js +1 -15
  52. package/lib/helper/Puppeteer.js +0 -103
  53. package/lib/helper/WebDriver.js +1 -28
  54. package/lib/helper/extras/PlaywrightLocator.js +10 -0
  55. package/lib/locator.js +0 -13
  56. package/lib/plugin/analyze.js +3 -4
  57. package/lib/plugin/pauseOnFail.js +3 -1
  58. package/lib/plugin/retryFailedStep.js +7 -7
  59. package/lib/plugin/screenshot.js +0 -5
  60. package/lib/plugin/screenshotOnFail.js +3 -1
  61. package/lib/plugin/stepTimeout.js +1 -1
  62. package/lib/recorder.js +1 -1
  63. package/lib/workers.js +0 -4
  64. package/package.json +3 -4
  65. package/docs/helpers/Mochawesome.md +0 -8
  66. package/docs/helpers/MockServer.md +0 -212
  67. package/docs/helpers/Polly.md +0 -44
  68. package/docs/helpers/Protractor.md +0 -1769
  69. package/docs/helpers/SoftExpectHelper.md +0 -352
  70. package/docs/react.md +0 -70
  71. package/lib/helper/Mochawesome.js +0 -96
  72. package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -61
  73. package/lib/helper/extras/React.js +0 -65
@@ -138,9 +138,8 @@ function executeRun(runName, runConfig) {
138
138
 
139
139
  outputDir = clearString(outputDir)
140
140
 
141
- // tweaking default output directories and for mochawesome
141
+ // tweaking default output directories
142
142
  overriddenConfig = replaceValueDeep(overriddenConfig, 'output', path.join(config.output, outputDir))
143
- overriddenConfig = replaceValueDeep(overriddenConfig, 'reportDir', path.join(config.output, outputDir))
144
143
  overriddenConfig = replaceValueDeep(overriddenConfig, 'mochaFile', path.join(config.output, outputDir, `${browserName}_report.xml`))
145
144
 
146
145
  // override tests configuration
@@ -36,7 +36,7 @@ import MultipleElementsFound from './errors/MultipleElementsFound.js'
36
36
  import RemoteBrowserConnectionRefused from './errors/RemoteBrowserConnectionRefused.js'
37
37
  import Popup from './extras/Popup.js'
38
38
  import Console from './extras/Console.js'
39
- import { findReact, findByPlaywrightLocator } from './extras/PlaywrightReactVueLocator.js'
39
+ import { findByPlaywrightLocator } from './extras/PlaywrightLocator.js'
40
40
  import { dropFile } from './scripts/dropFile.js'
41
41
  import WebElement from '../element/WebElement.js'
42
42
  import { selectElement } from './extras/elementSelection.js'
@@ -2081,15 +2081,6 @@ class Playwright extends Helper {
2081
2081
  return proceedClick.call(this, locator, context, options)
2082
2082
  }
2083
2083
 
2084
- /**
2085
- * Clicks link and waits for navigation (deprecated)
2086
- */
2087
- async clickLink(locator, context = null) {
2088
- console.log('clickLink deprecated: Playwright automatically waits for navigation to happen.')
2089
- console.log('Replace I.clickLink with I.click')
2090
- return this.click(locator, context)
2091
- }
2092
-
2093
2084
  /**
2094
2085
  * {{> forceClick }}
2095
2086
  */
@@ -3306,8 +3297,6 @@ class Playwright extends Helper {
3306
3297
  }
3307
3298
 
3308
3299
  /**
3309
- * This method accepts [React selectors](https://codecept.io/react).
3310
- *
3311
3300
  * {{> waitForVisible }}
3312
3301
  */
3313
3302
  async waitForVisible(locator, sec) {
@@ -4231,10 +4220,8 @@ async function findByRole(context, locator) {
4231
4220
  }
4232
4221
 
4233
4222
  async function findElements(matcher, locator) {
4234
- const isReactLocator = locator.type === 'react' || (locator.locator && locator.locator.react) || locator.react
4235
4223
  const isPwLocator = locator.type === 'pw' || (locator.locator && locator.locator.pw) || locator.pw
4236
4224
 
4237
- if (isReactLocator) return findReact(matcher, locator)
4238
4225
  if (isPwLocator) return findByPlaywrightLocator.call(this, matcher, locator)
4239
4226
 
4240
4227
  // Handle role locators with text/exact options (e.g., {role: 'button', text: 'Submit', exact: true})
@@ -4249,7 +4236,6 @@ async function findElements(matcher, locator) {
4249
4236
  }
4250
4237
 
4251
4238
  async function findElement(matcher, locator) {
4252
- if (locator.react) return findReact(matcher, locator)
4253
4239
  if (locator.pw) return findByPlaywrightLocator.call(this, matcher, locator)
4254
4240
 
4255
4241
  locator = new Locator(locator, 'css')
@@ -821,7 +821,6 @@ class Puppeteer extends Helper {
821
821
 
822
822
  /**
823
823
  * {{> moveCursorTo }}
824
- * {{ react }}
825
824
  */
826
825
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
827
826
  let context = null
@@ -992,7 +991,6 @@ class Puppeteer extends Helper {
992
991
  * const elements = await this.helpers['Puppeteer']._locate({name: 'password'});
993
992
  * ```
994
993
  *
995
- * {{ react }}
996
994
  */
997
995
  async _locate(locator) {
998
996
  const context = await this.context
@@ -1007,7 +1005,6 @@ class Puppeteer extends Helper {
1007
1005
  * const element = await this.helpers['Puppeteer']._locateElement({name: 'password'});
1008
1006
  * ```
1009
1007
  *
1010
- * {{ react }}
1011
1008
  */
1012
1009
  async _locateElement(locator) {
1013
1010
  const context = await this.context
@@ -1191,7 +1188,6 @@ class Puppeteer extends Helper {
1191
1188
 
1192
1189
  /**
1193
1190
  * {{> seeElement }}
1194
- * {{ react }}
1195
1191
  */
1196
1192
  async seeElement(locator, context = null) {
1197
1193
  let els
@@ -1215,7 +1211,6 @@ class Puppeteer extends Helper {
1215
1211
 
1216
1212
  /**
1217
1213
  * {{> dontSeeElement }}
1218
- * {{ react }}
1219
1214
  */
1220
1215
  async dontSeeElement(locator, context = null) {
1221
1216
  let els
@@ -1264,7 +1259,6 @@ class Puppeteer extends Helper {
1264
1259
  /**
1265
1260
  * {{> click }}
1266
1261
  *
1267
- * {{ react }}
1268
1262
  */
1269
1263
  async click(locator = '//body', context = null) {
1270
1264
  return proceedClick.call(this, locator, context)
@@ -1273,7 +1267,6 @@ class Puppeteer extends Helper {
1273
1267
  /**
1274
1268
  * {{> forceClick }}
1275
1269
  *
1276
- * {{ react }}
1277
1270
  */
1278
1271
  async forceClick(locator, context = null) {
1279
1272
  let matcher = await this.context
@@ -1303,7 +1296,6 @@ class Puppeteer extends Helper {
1303
1296
  /**
1304
1297
  * {{> clickLink }}
1305
1298
  *
1306
- * {{ react }}
1307
1299
  */
1308
1300
  async clickLink(locator, context = null) {
1309
1301
  return proceedClick.call(this, locator, context, { waitForNavigation: true })
@@ -1411,7 +1403,6 @@ class Puppeteer extends Helper {
1411
1403
  /**
1412
1404
  * {{> doubleClick }}
1413
1405
  *
1414
- * {{ react }}
1415
1406
  */
1416
1407
  async doubleClick(locator, context = null) {
1417
1408
  return proceedClick.call(this, locator, context, { clickCount: 2 })
@@ -1420,7 +1411,6 @@ class Puppeteer extends Helper {
1420
1411
  /**
1421
1412
  * {{> rightClick }}
1422
1413
  *
1423
- * {{ react }}
1424
1414
  */
1425
1415
  async rightClick(locator, context = null) {
1426
1416
  return proceedClick.call(this, locator, context, { button: 'right' })
@@ -1593,7 +1583,6 @@ class Puppeteer extends Helper {
1593
1583
 
1594
1584
  /**
1595
1585
  * {{> fillField }}
1596
- * {{ react }}
1597
1586
  */
1598
1587
  async fillField(field, value, context = null) {
1599
1588
  let els = await findVisibleFields.call(this, field, context)
@@ -1632,7 +1621,6 @@ class Puppeteer extends Helper {
1632
1621
  /**
1633
1622
  * {{> appendField }}
1634
1623
  *
1635
- * {{ react }}
1636
1624
  */
1637
1625
  async appendField(field, value, context = null) {
1638
1626
  const els = await findVisibleFields.call(this, field, context)
@@ -1734,7 +1722,6 @@ class Puppeteer extends Helper {
1734
1722
 
1735
1723
  /**
1736
1724
  * {{> grabNumberOfVisibleElements }}
1737
- * {{ react }}
1738
1725
  */
1739
1726
  async grabNumberOfVisibleElements(locator) {
1740
1727
  let els = await this._locate(locator)
@@ -1796,7 +1783,6 @@ class Puppeteer extends Helper {
1796
1783
  /**
1797
1784
  * {{> see }}
1798
1785
  *
1799
- * {{ react }}
1800
1786
  */
1801
1787
  async see(text, context = null) {
1802
1788
  return proceedSee.call(this, 'assert', text, context)
@@ -1812,7 +1798,6 @@ class Puppeteer extends Helper {
1812
1798
  /**
1813
1799
  * {{> dontSee }}
1814
1800
  *
1815
- * {{ react }}
1816
1801
  */
1817
1802
  async dontSee(text, context = null) {
1818
1803
  return proceedSee.call(this, 'negate', text, context)
@@ -1866,7 +1851,6 @@ class Puppeteer extends Helper {
1866
1851
  /**
1867
1852
  * {{> seeNumberOfElements }}
1868
1853
  *
1869
- * {{ react }}
1870
1854
  */
1871
1855
  async seeNumberOfElements(locator, num) {
1872
1856
  const elements = await this._locate(locator)
@@ -1876,7 +1860,6 @@ class Puppeteer extends Helper {
1876
1860
  /**
1877
1861
  * {{> seeNumberOfVisibleElements }}
1878
1862
  *
1879
- * {{ react }}
1880
1863
  */
1881
1864
  async seeNumberOfVisibleElements(locator, num) {
1882
1865
  const res = await this.grabNumberOfVisibleElements(locator)
@@ -2003,7 +1986,6 @@ class Puppeteer extends Helper {
2003
1986
 
2004
1987
  /**
2005
1988
  * {{> grabTextFromAll }}
2006
- * {{ react }}
2007
1989
  */
2008
1990
  async grabTextFromAll(locator) {
2009
1991
  const els = await this._locate(locator)
@@ -2016,7 +1998,6 @@ class Puppeteer extends Helper {
2016
1998
 
2017
1999
  /**
2018
2000
  * {{> grabTextFrom }}
2019
- * {{ react }}
2020
2001
  */
2021
2002
  async grabTextFrom(locator) {
2022
2003
  const texts = await this.grabTextFromAll(locator)
@@ -2077,7 +2058,6 @@ class Puppeteer extends Helper {
2077
2058
 
2078
2059
  /**
2079
2060
  * {{> grabCssPropertyFromAll }}
2080
- * {{ react }}
2081
2061
  */
2082
2062
  async grabCssPropertyFromAll(locator, cssProperty) {
2083
2063
  const els = await this._locate(locator)
@@ -2089,7 +2069,6 @@ class Puppeteer extends Helper {
2089
2069
 
2090
2070
  /**
2091
2071
  * {{> grabCssPropertyFrom }}
2092
- * {{ react }}
2093
2072
  */
2094
2073
  async grabCssPropertyFrom(locator, cssProperty) {
2095
2074
  const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
@@ -2104,7 +2083,6 @@ class Puppeteer extends Helper {
2104
2083
 
2105
2084
  /**
2106
2085
  * {{> seeCssPropertiesOnElements }}
2107
- * {{ react }}
2108
2086
  */
2109
2087
  async seeCssPropertiesOnElements(locator, cssProperties) {
2110
2088
  const res = await this._locate(locator)
@@ -2139,7 +2117,6 @@ class Puppeteer extends Helper {
2139
2117
 
2140
2118
  /**
2141
2119
  * {{> seeAttributesOnElements }}
2142
- * {{ react }}
2143
2120
  */
2144
2121
  async seeAttributesOnElements(locator, attributes) {
2145
2122
  const elements = await this._locate(locator)
@@ -2177,7 +2154,6 @@ class Puppeteer extends Helper {
2177
2154
 
2178
2155
  /**
2179
2156
  * {{> dragSlider }}
2180
- * {{ react }}
2181
2157
  */
2182
2158
  async dragSlider(locator, offsetX = 0) {
2183
2159
  const src = await this._locate(locator)
@@ -2199,7 +2175,6 @@ class Puppeteer extends Helper {
2199
2175
 
2200
2176
  /**
2201
2177
  * {{> grabAttributeFromAll }}
2202
- * {{ react }}
2203
2178
  */
2204
2179
  async grabAttributeFromAll(locator, attr) {
2205
2180
  const els = await this._locate(locator)
@@ -2213,7 +2188,6 @@ class Puppeteer extends Helper {
2213
2188
 
2214
2189
  /**
2215
2190
  * {{> grabAttributeFrom }}
2216
- * {{ react }}
2217
2191
  */
2218
2192
  async grabAttributeFrom(locator, attr) {
2219
2193
  const attrs = await this.grabAttributeFromAll(locator, attr)
@@ -2376,7 +2350,6 @@ class Puppeteer extends Helper {
2376
2350
 
2377
2351
  /**
2378
2352
  * {{> waitNumberOfVisibleElements }}
2379
- * {{ react }}
2380
2353
  */
2381
2354
  async waitNumberOfVisibleElements(locator, num, sec) {
2382
2355
  const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
@@ -2424,7 +2397,6 @@ class Puppeteer extends Helper {
2424
2397
 
2425
2398
  /**
2426
2399
  * {{> waitForElement }}
2427
- * {{ react }}
2428
2400
  */
2429
2401
  async waitForElement(locator, sec) {
2430
2402
  const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
@@ -2445,7 +2417,6 @@ class Puppeteer extends Helper {
2445
2417
  /**
2446
2418
  * {{> waitForVisible }}
2447
2419
  *
2448
- * {{ react }}
2449
2420
  */
2450
2421
  async waitForVisible(locator, sec) {
2451
2422
  const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
@@ -3022,10 +2993,6 @@ export default Puppeteer
3022
2993
  * @returns {Promise<Array>} Array of ElementHandle objects
3023
2994
  */
3024
2995
  async function findElements(matcher, locator) {
3025
- // Check if locator is a Locator object with react type, or a raw object with react property
3026
- const isReactLocator = locator.type === 'react' || (locator.locator && locator.locator.react) || locator.react
3027
- if (isReactLocator) return findReactElements.call(this, locator)
3028
-
3029
2996
  locator = new Locator(locator, 'css')
3030
2997
 
3031
2998
  // Check if locator is a role locator and call findByRole
@@ -3092,7 +3059,6 @@ async function findElements(matcher, locator) {
3092
3059
  * @returns {Promise<Object>} Single ElementHandle object
3093
3060
  */
3094
3061
  async function findElement(matcher, locator) {
3095
- if (locator.react) return findReactElements.call(this, locator)
3096
3062
  locator = new Locator(locator, 'css')
3097
3063
 
3098
3064
  // Check if locator is a role locator and call findByRole
@@ -3591,75 +3557,6 @@ function _waitForElement(locator, options) {
3591
3557
  }
3592
3558
  }
3593
3559
 
3594
- async function findReactElements(locator) {
3595
- // Handle both Locator objects and raw locator objects
3596
- const resolved = locator.locator ? locator.locator : toLocatorConfig(locator, 'react')
3597
- this.debug(`Finding React elements: ${JSON.stringify(resolved)}`)
3598
-
3599
- // Use createRequire to access require.resolve in ESM
3600
- const { createRequire } = await import('module')
3601
- const require = createRequire(import.meta.url)
3602
- const resqScript = await fs.promises.readFile(require.resolve('resq'), 'utf-8')
3603
- await this.page.evaluate(resqScript.toString())
3604
-
3605
- await this.page.evaluate(() => window.resq.waitToLoadReact())
3606
- const arrayHandle = await this.page.evaluateHandle(
3607
- obj => {
3608
- const { selector, props, state } = obj
3609
- let elements = window.resq.resq$$(selector)
3610
- if (Object.keys(props).length) {
3611
- elements = elements.byProps(props)
3612
- }
3613
- if (Object.keys(state).length) {
3614
- elements = elements.byState(state)
3615
- }
3616
-
3617
- if (!elements.length) {
3618
- return []
3619
- }
3620
-
3621
- // resq returns an array of HTMLElements if the React component is a fragment
3622
- // this avoids having nested arrays of nodes which the driver does not understand
3623
- // [[div, div], [div, div]] => [div, div, div, div]
3624
- let nodes = []
3625
-
3626
- elements.forEach(element => {
3627
- let { node, isFragment } = element
3628
-
3629
- if (!node) {
3630
- isFragment = true
3631
- node = element.children
3632
- }
3633
-
3634
- if (isFragment) {
3635
- nodes = nodes.concat(node)
3636
- } else {
3637
- nodes.push(node)
3638
- }
3639
- })
3640
-
3641
- return [...nodes]
3642
- },
3643
- {
3644
- selector: resolved.react,
3645
- props: resolved.props || {},
3646
- state: resolved.state || {},
3647
- },
3648
- )
3649
-
3650
- const properties = await arrayHandle.getProperties()
3651
- const result = []
3652
- for (const property of properties.values()) {
3653
- const elementHandle = property.asElement()
3654
- if (elementHandle) {
3655
- result.push(elementHandle)
3656
- }
3657
- }
3658
-
3659
- await arrayHandle.dispose()
3660
- return result
3661
- }
3662
-
3663
3560
  async function findByRole(matcher, locator) {
3664
3561
  const resolved = toLocatorConfig(locator, 'role')
3665
3562
  const roleSelector = buildRoleSelector(resolved)
@@ -97,11 +97,7 @@ const config = {}
97
97
  * WebDriver helper which wraps [webdriverio](http://webdriver.io/) library to
98
98
  * manipulate browser using Selenium WebDriver or PhantomJS.
99
99
  *
100
- * WebDriver requires Selenium Server and ChromeDriver/GeckoDriver to be installed. Those tools can be easily installed via NPM. Please check [Testing with WebDriver](https://codecept.io/webdriver/#testing-with-webdriver) for more details.
101
- *
102
- * With the release of WebdriverIO version v8.14.0, and onwards, all driver management hassles are now a thing of the past 🙌. Read more [here](https://webdriver.io/blog/2023/07/31/driver-management/).
103
- * One of the significant advantages of this update is that you can now get rid of any driver services you previously had to manage, such as
104
- * `wdio-chromedriver-service`, `wdio-geckodriver-service`, `wdio-edgedriver-service`, `wdio-safaridriver-service`, and even `@wdio/selenium-standalone-service`.
100
+ * No Selenium Server, ChromeDriver, or GeckoDriver to install or start. Since WebdriverIO 9, driver management is fully automatic — WebdriverIO downloads and starts the matching driver for you. Read more [here](https://webdriver.io/blog/2023/07/31/driver-management/). Please check [Testing with WebDriver](https://codecept.io/webdriver/#testing-with-webdriver) for more details.
105
101
  *
106
102
  * For those who require custom driver options, fear not; WebDriver Helper allows you to pass in driver options through custom WebDriver configuration.
107
103
  * If you have a custom grid, use a cloud service, or prefer to run your own driver, there's no need to worry since WebDriver Helper will only start a driver when there are no other connection information settings like hostname or port specified.
@@ -908,13 +904,6 @@ class WebDriver extends Helper {
908
904
  return els
909
905
  }
910
906
 
911
- // special locator type for React
912
- if (locator.react) {
913
- const els = await this.browser.react$$(locator.react, locator.props || undefined, locator.state || undefined)
914
- this.debugSection('Elements', `Found ${els.length} react components`)
915
- return els
916
- }
917
-
918
907
  // special locator type for ARIA roles
919
908
  if (locator.role) {
920
909
  return this._locateByRole(locator)
@@ -1084,7 +1073,6 @@ class WebDriver extends Helper {
1084
1073
  /**
1085
1074
  * {{> click }}
1086
1075
  *
1087
- * {{ react }}
1088
1076
  */
1089
1077
  async click(locator, context = null) {
1090
1078
  const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
@@ -1104,7 +1092,6 @@ class WebDriver extends Helper {
1104
1092
  /**
1105
1093
  * {{> forceClick }}
1106
1094
  *
1107
- * {{ react }}
1108
1095
  */
1109
1096
  async forceClick(locator, context = null) {
1110
1097
  const locateFn = prepareLocateFn.call(this, context)
@@ -1131,7 +1118,6 @@ class WebDriver extends Helper {
1131
1118
  /**
1132
1119
  * {{> doubleClick }}
1133
1120
  *
1134
- * {{ react }}
1135
1121
  */
1136
1122
  async doubleClick(locator, context = null) {
1137
1123
  const locateFn = prepareLocateFn.call(this, context)
@@ -1151,7 +1137,6 @@ class WebDriver extends Helper {
1151
1137
  /**
1152
1138
  * {{> rightClick }}
1153
1139
  *
1154
- * {{ react }}
1155
1140
  */
1156
1141
  async rightClick(locator, context) {
1157
1142
  const locateFn = prepareLocateFn.call(this, context)
@@ -1246,7 +1231,6 @@ class WebDriver extends Helper {
1246
1231
  /**
1247
1232
  * {{> forceRightClick }}
1248
1233
  *
1249
- * {{ react }}
1250
1234
  */
1251
1235
  async forceRightClick(locator, context = null) {
1252
1236
  const locateFn = prepareLocateFn.call(this, context)
@@ -1271,7 +1255,6 @@ class WebDriver extends Helper {
1271
1255
 
1272
1256
  /**
1273
1257
  * {{> fillField }}
1274
- * {{ react }}
1275
1258
  * {{ custom }}
1276
1259
  *
1277
1260
  */
@@ -1301,7 +1284,6 @@ class WebDriver extends Helper {
1301
1284
 
1302
1285
  /**
1303
1286
  * {{> appendField }}
1304
- * {{ react }}
1305
1287
  */
1306
1288
  async appendField(field, value, context = null) {
1307
1289
  const res = await findFields.call(this, field, context)
@@ -1599,7 +1581,6 @@ class WebDriver extends Helper {
1599
1581
  /**
1600
1582
  * {{> see }}
1601
1583
  *
1602
- * {{ react }}
1603
1584
  */
1604
1585
  async see(text, context = null) {
1605
1586
  return proceedSee.call(this, 'assert', text, context)
@@ -1615,7 +1596,6 @@ class WebDriver extends Helper {
1615
1596
  /**
1616
1597
  * {{> dontSee }}
1617
1598
  *
1618
- * {{ react }}
1619
1599
  */
1620
1600
  async dontSee(text, context = null) {
1621
1601
  return proceedSee.call(this, 'negate', text, context)
@@ -1657,7 +1637,6 @@ class WebDriver extends Helper {
1657
1637
 
1658
1638
  /**
1659
1639
  * {{> seeElement }}
1660
- * {{ react }}
1661
1640
  *
1662
1641
  */
1663
1642
  async seeElement(locator, context = null) {
@@ -1674,7 +1653,6 @@ class WebDriver extends Helper {
1674
1653
 
1675
1654
  /**
1676
1655
  * {{> dontSeeElement }}
1677
- * {{ react }}
1678
1656
  */
1679
1657
  async dontSeeElement(locator, context = null) {
1680
1658
  const locateFn = prepareLocateFn.call(this, context)
@@ -1759,7 +1737,6 @@ class WebDriver extends Helper {
1759
1737
 
1760
1738
  /**
1761
1739
  * {{> seeNumberOfElements }}
1762
- * {{ react }}
1763
1740
  */
1764
1741
  async seeNumberOfElements(locator, num) {
1765
1742
  const res = await this._locate(locator)
@@ -1768,7 +1745,6 @@ class WebDriver extends Helper {
1768
1745
 
1769
1746
  /**
1770
1747
  * {{> seeNumberOfVisibleElements }}
1771
- * {{ react }}
1772
1748
  */
1773
1749
  async seeNumberOfVisibleElements(locator, num) {
1774
1750
  const res = await this.grabNumberOfVisibleElements(locator)
@@ -3501,9 +3477,6 @@ function prepareLocateFn(context) {
3501
3477
  l = new Locator(l, 'css')
3502
3478
  return this._locate(context, true).then(async res => {
3503
3479
  assertElementExists(res, context, 'Context element')
3504
- if (l.react) {
3505
- return res[0].react$$(l.react, l.props || undefined)
3506
- }
3507
3480
  return res[0].$$(l.simplify())
3508
3481
  })
3509
3482
  }
@@ -0,0 +1,10 @@
1
+ async function findByPlaywrightLocator(matcher, locator) {
2
+ const pwLocator = locator.locator || locator
3
+ if (pwLocator && pwLocator.toString && pwLocator.toString().includes(process.env.testIdAttribute)) {
4
+ return matcher.getByTestId(pwLocator.pw.value.split('=')[1])
5
+ }
6
+ const pwValue = typeof pwLocator.pw === 'string' ? pwLocator.pw : pwLocator.pw
7
+ return matcher.locator(pwValue).all()
8
+ }
9
+
10
+ export { findByPlaywrightLocator }
package/lib/locator.js CHANGED
@@ -58,9 +58,6 @@ class Locator {
58
58
  if (isShadow(locator)) {
59
59
  this.type = 'shadow'
60
60
  }
61
- if (isPlaywrightLocator(locator)) {
62
- this.type = 'pw'
63
- }
64
61
 
65
62
  Locator.filters.forEach(f => f(locator, this))
66
63
  }
@@ -753,16 +750,6 @@ function removePrefix(xpath) {
753
750
  return xpath.replace(/^(\.|\/)+/, '')
754
751
  }
755
752
 
756
- /**
757
- * @private
758
- * check if the locator is a Playwright locator
759
- * @param {string} locator
760
- * @returns {boolean}
761
- */
762
- function isPlaywrightLocator(locator) {
763
- return locator.includes('_react') || locator.includes('_vue')
764
- }
765
-
766
753
  /**
767
754
  * @private
768
755
  * check if the locator is a role locator
@@ -155,10 +155,9 @@ const defaultConfig = {
155
155
  if (config.vision && test.artifacts.screenshot) {
156
156
  debug('Adding screenshot to prompt')
157
157
  messages[0].content.push({
158
- type: 'image_url',
159
- image_url: {
160
- url: 'data:image/png;base64,' + base64EncodeFile(test.artifacts.screenshot),
161
- },
158
+ type: 'image',
159
+ image: base64EncodeFile(test.artifacts.screenshot),
160
+ mediaType: 'image/png',
162
161
  })
163
162
  }
164
163
 
@@ -4,7 +4,9 @@ import pause from './pause.js'
4
4
  let warned = false
5
5
 
6
6
  /**
7
- * @deprecated Use the `pause` plugin with `on: 'fail'` (the default).
7
+ * Starts an interactive pause when a test fails.
8
+ *
9
+ * **Deprecated:** use the `pause` plugin with `on: 'fail'`, which is the default behavior.
8
10
  */
9
11
  export default function (config = {}) {
10
12
  if (!warned) {
@@ -8,7 +8,10 @@ const debug = debugModule('codeceptjs:retryFailedStep')
8
8
  const defaultConfig = {
9
9
  retries: 3,
10
10
  defaultIgnoredSteps: ['amOnPage', 'wait*', 'send*', 'execute*', 'run*', 'have*'],
11
+ minTimeout: 150,
12
+ maxTimeout: 10000,
11
13
  factor: 1.5,
14
+ randomize: false,
12
15
  ignoredSteps: [],
13
16
  deferToScenarioRetries: true,
14
17
  }
@@ -44,10 +47,9 @@ const RETRY_PRIORITIES = {
44
47
  * #### Configuration:
45
48
  *
46
49
  * * `retries` - number of retries (by default 3),
47
- * * `when` - function, when to perform a retry (accepts error as parameter)
48
50
  * * `factor` - The exponential factor to use. Default is 1.5.
49
- * * `minTimeout` - The number of milliseconds before starting the first retry. Default is 1000.
50
- * * `maxTimeout` - The maximum number of milliseconds between two retries. Default is Infinity.
51
+ * * `minTimeout` - The number of milliseconds before starting the first retry. Default is 150.
52
+ * * `maxTimeout` - The maximum number of milliseconds between two retries. Default is 10000.
51
53
  * * `randomize` - Randomizes the timeouts by multiplying with a factor from 1 to 2. Default is false.
52
54
  * * `defaultIgnoredSteps` - an array of steps to be ignored for retry. Includes:
53
55
  * * `amOnPage`
@@ -77,7 +79,7 @@ const RETRY_PRIORITIES = {
77
79
  *
78
80
  * #### Disable Per Test
79
81
  *
80
- * This plugin can be disabled per test. In this case you will need to stet `I.retry()` to all flaky steps:
82
+ * This plugin can be disabled per test. In this case you will need to add `step.retry()` to all flaky steps:
81
83
  *
82
84
  * Use scenario configuration to disable plugin for a test
83
85
  *
@@ -89,9 +91,8 @@ const RETRY_PRIORITIES = {
89
91
  *
90
92
  */
91
93
  export default function (config) {
92
- config = Object.assign(defaultConfig, config)
94
+ config = Object.assign({}, defaultConfig, config)
93
95
  config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
94
- const customWhen = config.when
95
96
 
96
97
  let enableRetry = false
97
98
 
@@ -101,7 +102,6 @@ export default function (config) {
101
102
  if (!store.autoRetries) return false
102
103
  if (err && err.isTerminal) return false
103
104
  if (err && err.message && (err.message.includes('ERR_ABORTED') || err.message.includes('frame was detached') || err.message.includes('Target page, context or browser has been closed'))) return false
104
- if (customWhen) return customWhen(err)
105
105
  return true
106
106
  }
107
107
  config.when = when
@@ -86,14 +86,9 @@ export default function (config = {}) {
86
86
  const trigger = resolveTrigger(cliArgs, config, { on: defaultConfig.on }, { name: 'screenshot' })
87
87
  if (!trigger) return
88
88
 
89
- const helpers = Container.helpers()
90
89
  const options = Object.assign({}, defaultConfig, helper.options, config)
91
90
  options.slides = cliArgs.slides ?? config.slides ?? defaultConfig.slides
92
91
 
93
- if (helpers.Mochawesome?.config) {
94
- options.uniqueScreenshotNames = helpers.Mochawesome.config.uniqueScreenshotNames
95
- }
96
-
97
92
  if (Codeceptjs.container.mocha()) {
98
93
  options.reportDir = Codeceptjs.container.mocha()?.options?.reporterOptions
99
94
  && Codeceptjs.container.mocha()?.options?.reporterOptions?.reportDir
@@ -4,7 +4,9 @@ import screenshot from './screenshot.js'
4
4
  let warned = false
5
5
 
6
6
  /**
7
- * @deprecated Use the `screenshot` plugin with `on: 'fail'` (the default).
7
+ * Saves a screenshot when a test fails.
8
+ *
9
+ * **Deprecated:** use the `screenshot` plugin with `on: 'fail'`, which is the default behavior.
8
10
  */
9
11
  export default function (config = {}) {
10
12
  if (!warned) {
@@ -32,7 +32,7 @@ const defaultConfig = {
32
32
  * #### Configuration:
33
33
  *
34
34
  * * `timeout` - global step timeout, default 150 seconds
35
- * * `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with I.limitTime(x).action(...), default false
35
+ * * `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with `I.action(..., step.timeout(x))`, default false
36
36
  * * `noTimeoutSteps` - an array of steps with no timeout. Default:
37
37
  * * `amOnPage`
38
38
  * * `wait*`
package/lib/recorder.js CHANGED
@@ -217,7 +217,7 @@ export default {
217
217
  }
218
218
 
219
219
  const retryRules = this.retries.slice().reverse()
220
- return promiseRetry(Object.assign(defaultRetryOptions, retryOpts), (retry, number) => {
220
+ return promiseRetry(Object.assign({}, defaultRetryOptions, retryOpts), (retry, number) => {
221
221
  if (number > 1) output.log(`${currentQueue()}Retrying... Attempt #${number}`)
222
222
  const [promise, timer] = getTimeoutPromise(timeout, taskName)
223
223
  return Promise.race([promise, Promise.resolve(res).then(fn)])