codeceptjs 4.0.0-rc.8 → 4.0.0
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/README.md +9 -10
- package/bin/codecept.js +15 -2
- package/bin/codeceptq.js +49 -0
- package/bin/mcp-server.js +751 -172
- package/docs/advanced.md +201 -0
- package/docs/agents.md +181 -0
- package/docs/ai.md +489 -0
- package/docs/aitrace.md +266 -0
- package/docs/api.md +332 -0
- package/docs/architecture.md +235 -0
- package/docs/assertions.md +415 -0
- package/docs/auth.md +318 -0
- package/docs/basics.md +424 -0
- package/docs/bdd.md +539 -0
- package/docs/best.md +240 -0
- package/docs/bootstrap.md +132 -0
- package/docs/commands.md +352 -0
- package/docs/community-helpers.md +63 -0
- package/docs/configuration.md +185 -0
- package/docs/continuous-integration.md +431 -0
- package/docs/custom-helpers.md +297 -0
- package/docs/data.md +448 -0
- package/docs/debugging.md +332 -0
- package/docs/detox.md +235 -0
- package/docs/docker.md +107 -0
- package/docs/effects.md +179 -0
- package/docs/element-based-testing.md +295 -0
- package/docs/element-selection.md +125 -0
- package/docs/els.md +328 -0
- package/docs/environment-variables.md +131 -0
- package/docs/examples.md +160 -0
- package/docs/heal.md +213 -0
- package/docs/helpers/ApiDataFactory.md +267 -0
- package/docs/helpers/Appium.md +1419 -0
- package/docs/helpers/Detox.md +665 -0
- package/docs/helpers/ExpectHelper.md +275 -0
- package/docs/helpers/FileSystem.md +152 -0
- package/docs/helpers/GraphQL.md +152 -0
- package/docs/helpers/GraphQLDataFactory.md +226 -0
- package/docs/helpers/JSONResponse.md +255 -0
- package/docs/helpers/MockRequest.md +377 -0
- package/docs/helpers/Playwright.md +2970 -0
- package/docs/helpers/Puppeteer-firefox.md +86 -0
- package/docs/helpers/Puppeteer.md +2583 -0
- package/docs/helpers/REST.md +289 -0
- package/docs/helpers/WebDriver.md +2639 -0
- package/docs/hooks.md +148 -0
- package/docs/index.md +111 -0
- package/docs/installation.md +121 -0
- package/docs/internal-test-server.md +89 -0
- package/docs/locators.md +355 -0
- package/docs/mcp.md +485 -0
- package/docs/migrate-from-cypress.md +98 -0
- package/docs/migrate-from-java.md +108 -0
- package/docs/migrate-from-protractor.md +101 -0
- package/docs/migrate-from-testcafe.md +99 -0
- package/docs/migration-4.md +743 -0
- package/docs/mobile.md +338 -0
- package/docs/pageobjects.md +399 -0
- package/docs/parallel.md +187 -0
- package/docs/playwright.md +714 -0
- package/docs/plugins/aiTrace.md +49 -0
- package/docs/plugins/analyze.md +66 -0
- package/docs/plugins/auth.md +241 -0
- package/docs/plugins/autoDelay.md +48 -0
- package/docs/plugins/browser.md +41 -0
- package/docs/plugins/coverage.md +39 -0
- package/docs/plugins/customLocator.md +119 -0
- package/docs/plugins/customReporter.md +16 -0
- package/docs/plugins/expose.md +75 -0
- package/docs/plugins/heal.md +44 -0
- package/docs/plugins/junitReporter.md +51 -0
- package/docs/plugins/pageInfo.md +34 -0
- package/docs/plugins/pause.md +43 -0
- package/docs/plugins/pauseOnFail.md +18 -0
- package/docs/plugins/retryFailedStep.md +75 -0
- package/docs/plugins/screencast.md +55 -0
- package/docs/plugins/screenshot.md +58 -0
- package/docs/plugins/screenshotOnFail.md +18 -0
- package/docs/plugins/stepTimeout.md +65 -0
- package/docs/plugins.md +87 -0
- package/docs/puppeteer.md +314 -0
- package/docs/quickstart.md +120 -0
- package/docs/reports.md +198 -0
- package/docs/retry.md +311 -0
- package/docs/secrets.md +150 -0
- package/docs/sessions.md +80 -0
- package/docs/shadow.md +68 -0
- package/docs/store.md +94 -0
- package/docs/test-structure.md +275 -0
- package/docs/timeouts.md +183 -0
- package/docs/translation.md +247 -0
- package/docs/tutorial.md +323 -0
- package/docs/typescript.md +159 -0
- package/docs/web-element.md +251 -0
- package/docs/webdriver.md +641 -0
- package/docs/within.md +55 -0
- package/lib/actor.js +1 -36
- package/lib/ai.js +3 -2
- package/lib/aria.js +260 -0
- package/lib/assertions.js +18 -0
- package/lib/codecept.js +7 -7
- package/lib/command/check.js +2 -1
- package/lib/command/dryRun.js +24 -5
- package/lib/command/generate.js +2 -0
- package/lib/command/gherkin/snippets.js +5 -4
- package/lib/command/init.js +248 -266
- package/lib/command/list.js +150 -10
- package/lib/command/query.js +218 -0
- package/lib/command/run-multiple.js +3 -2
- package/lib/command/run-workers.js +1 -14
- package/lib/command/run.js +3 -17
- package/lib/command/utils.js +14 -0
- package/lib/command/workers/runTests.js +11 -15
- package/lib/config.js +77 -4
- package/lib/container.js +97 -15
- package/lib/effects.js +17 -0
- package/lib/element/WebElement.js +195 -3
- package/lib/els.js +12 -6
- package/lib/globals.js +32 -19
- package/lib/heal.js +7 -4
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/FileSystem.js +3 -2
- package/lib/helper/GraphQLDataFactory.js +2 -1
- package/lib/helper/Playwright.js +96 -115
- package/lib/helper/Puppeteer.js +43 -131
- package/lib/helper/WebDriver.js +42 -52
- package/lib/helper/errors/NonFocusedType.js +8 -0
- package/lib/helper/extras/Download.js +45 -0
- package/lib/helper/extras/PlaywrightLocator.js +10 -0
- package/lib/helper/extras/elementSelection.js +58 -0
- package/lib/helper/extras/focusCheck.js +43 -0
- package/lib/helper/extras/richTextEditor.js +178 -0
- package/lib/history.js +3 -2
- package/lib/html.js +90 -16
- package/lib/index.js +9 -1
- package/lib/listener/config.js +6 -4
- package/lib/listener/emptyRun.js +2 -1
- package/lib/listener/helpers.js +4 -1
- package/lib/listener/mocha.js +2 -1
- package/lib/listener/pageobjects.js +43 -0
- package/lib/listener/result.js +3 -2
- package/lib/locator.js +126 -16
- package/lib/mocha/cli.js +4 -2
- package/lib/mocha/factory.js +7 -2
- package/lib/mocha/inject.js +1 -1
- package/lib/mocha/scenarioConfig.js +2 -1
- package/lib/mocha/ui.js +5 -6
- package/lib/parser.js +2 -2
- package/lib/pause.js +38 -4
- package/lib/plugin/aiTrace.js +96 -103
- package/lib/plugin/analyze.js +9 -9
- package/lib/plugin/auth.js +3 -3
- package/lib/plugin/browser.js +77 -0
- package/lib/plugin/expose.js +159 -0
- package/lib/plugin/heal.js +47 -3
- package/lib/plugin/junitReporter.js +303 -0
- package/lib/plugin/pageInfo.js +54 -52
- package/lib/plugin/pause.js +131 -0
- package/lib/plugin/pauseOnFail.js +11 -33
- package/lib/plugin/retryFailedStep.js +15 -13
- package/lib/plugin/screencast.js +289 -0
- package/lib/plugin/screenshot.js +558 -0
- package/lib/plugin/screenshotOnFail.js +9 -170
- package/lib/plugin/stepTimeout.js +3 -2
- package/lib/recorder.js +1 -1
- package/lib/rerun.js +2 -1
- package/lib/result.js +2 -1
- package/lib/step/base.js +10 -9
- package/lib/step/comment.js +2 -2
- package/lib/step/config.js +15 -2
- package/lib/step/helper.js +4 -4
- package/lib/step/meta.js +3 -3
- package/lib/step/record.js +5 -5
- package/lib/store.js +72 -3
- package/lib/translation.js +2 -1
- package/lib/utils/mask_data.js +2 -1
- package/lib/utils/pluginParser.js +151 -0
- package/lib/utils/trace.js +297 -0
- package/lib/utils.js +29 -3
- package/lib/workers.js +14 -22
- package/package.json +17 -14
- package/typings/index.d.ts +19 -5
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -16
- package/docs/webapi/attachFile.mustache +0 -24
- package/docs/webapi/blur.mustache +0 -18
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -9
- package/docs/webapi/clearField.mustache +0 -14
- package/docs/webapi/click.mustache +0 -29
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -12
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -16
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/dontSeeTraffic.mustache +0 -13
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -21
- package/docs/webapi/flushNetworkTraffics.mustache +0 -5
- package/docs/webapi/focus.mustache +0 -13
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/grabWebElement.mustache +0 -9
- package/docs/webapi/grabWebElements.mustache +0 -9
- package/docs/webapi/moveCursorTo.mustache +0 -16
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentPathEquals.mustache +0 -10
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -12
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -17
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/seeTraffic.mustache +0 -36
- package/docs/webapi/selectOption.mustache +0 -26
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/startRecordingTraffic.mustache +0 -8
- package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
- package/docs/webapi/stopRecordingTraffic.mustache +0 -5
- package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -21
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForCookie.mustache +0 -9
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForDisabled.mustache +0 -6
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
- package/lib/helper/AI.js +0 -214
- package/lib/helper/Mochawesome.js +0 -96
- package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -52
- package/lib/helper/extras/React.js +0 -65
- package/lib/plugin/stepByStepReport.js +0 -431
- package/lib/plugin/subtitles.js +0 -89
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -8,6 +8,7 @@ import promiseRetry from 'promise-retry'
|
|
|
8
8
|
import Locator from '../locator.js'
|
|
9
9
|
import recorder from '../recorder.js'
|
|
10
10
|
import store from '../store.js'
|
|
11
|
+
import { checkFocusBeforeType, checkFocusBeforePressKey } from './extras/focusCheck.js'
|
|
11
12
|
import { includes as stringIncludes } from '../assert/include.js'
|
|
12
13
|
import { urlEquals, equals } from '../assert/equal.js'
|
|
13
14
|
import { empty } from '../assert/empty.js'
|
|
@@ -43,6 +44,8 @@ import { dropFile } from './scripts/dropFile.js'
|
|
|
43
44
|
import { dontSeeElementError, seeElementError, dontSeeElementInDOMError, seeElementInDOMError } from './errors/ElementAssertion.js'
|
|
44
45
|
import { dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics } from './network/actions.js'
|
|
45
46
|
import WebElement from '../element/WebElement.js'
|
|
47
|
+
import { selectElement } from './extras/elementSelection.js'
|
|
48
|
+
import { fillRichEditor } from './extras/richTextEditor.js'
|
|
46
49
|
|
|
47
50
|
let puppeteer
|
|
48
51
|
|
|
@@ -750,7 +753,7 @@ class Puppeteer extends Helper {
|
|
|
750
753
|
}
|
|
751
754
|
|
|
752
755
|
if (this.options.trace) {
|
|
753
|
-
const fileName = `${`${
|
|
756
|
+
const fileName = `${`${store.outputDir}${path.sep}trace${path.sep}${uuidv4()}_${clearString(this.currentRunningTest.title)}`.slice(0, 245)}.json`
|
|
754
757
|
const dir = path.dirname(fileName)
|
|
755
758
|
if (!fileExists(dir)) fs.mkdirSync(dir)
|
|
756
759
|
await this.page.tracing.start({ screenshots: true, path: fileName })
|
|
@@ -818,7 +821,6 @@ class Puppeteer extends Helper {
|
|
|
818
821
|
|
|
819
822
|
/**
|
|
820
823
|
* {{> moveCursorTo }}
|
|
821
|
-
* {{ react }}
|
|
822
824
|
*/
|
|
823
825
|
async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
|
|
824
826
|
let context = null
|
|
@@ -989,7 +991,6 @@ class Puppeteer extends Helper {
|
|
|
989
991
|
* const elements = await this.helpers['Puppeteer']._locate({name: 'password'});
|
|
990
992
|
* ```
|
|
991
993
|
*
|
|
992
|
-
* {{ react }}
|
|
993
994
|
*/
|
|
994
995
|
async _locate(locator) {
|
|
995
996
|
const context = await this.context
|
|
@@ -1004,17 +1005,16 @@ class Puppeteer extends Helper {
|
|
|
1004
1005
|
* const element = await this.helpers['Puppeteer']._locateElement({name: 'password'});
|
|
1005
1006
|
* ```
|
|
1006
1007
|
*
|
|
1007
|
-
* {{ react }}
|
|
1008
1008
|
*/
|
|
1009
1009
|
async _locateElement(locator) {
|
|
1010
1010
|
const context = await this.context
|
|
1011
|
-
|
|
1011
|
+
const elementIndex = store.currentStep?.opts?.elementIndex
|
|
1012
|
+
if (this.options.strict || elementIndex) {
|
|
1012
1013
|
const elements = await findElements.call(this, context, locator)
|
|
1013
1014
|
if (elements.length === 0) {
|
|
1014
1015
|
throw new ElementNotFound(locator, 'Element', 'was not found')
|
|
1015
1016
|
}
|
|
1016
|
-
|
|
1017
|
-
return elements[0]
|
|
1017
|
+
return selectElement(elements, locator, this)
|
|
1018
1018
|
}
|
|
1019
1019
|
return findElement.call(this, context, locator)
|
|
1020
1020
|
}
|
|
@@ -1033,8 +1033,7 @@ class Puppeteer extends Helper {
|
|
|
1033
1033
|
if (!els || els.length === 0) {
|
|
1034
1034
|
throw new ElementNotFound(locator, 'Checkbox or radio')
|
|
1035
1035
|
}
|
|
1036
|
-
|
|
1037
|
-
return els[0]
|
|
1036
|
+
return selectElement(els, locator, this)
|
|
1038
1037
|
}
|
|
1039
1038
|
|
|
1040
1039
|
/**
|
|
@@ -1189,7 +1188,6 @@ class Puppeteer extends Helper {
|
|
|
1189
1188
|
|
|
1190
1189
|
/**
|
|
1191
1190
|
* {{> seeElement }}
|
|
1192
|
-
* {{ react }}
|
|
1193
1191
|
*/
|
|
1194
1192
|
async seeElement(locator, context = null) {
|
|
1195
1193
|
let els
|
|
@@ -1213,7 +1211,6 @@ class Puppeteer extends Helper {
|
|
|
1213
1211
|
|
|
1214
1212
|
/**
|
|
1215
1213
|
* {{> dontSeeElement }}
|
|
1216
|
-
* {{ react }}
|
|
1217
1214
|
*/
|
|
1218
1215
|
async dontSeeElement(locator, context = null) {
|
|
1219
1216
|
let els
|
|
@@ -1262,7 +1259,6 @@ class Puppeteer extends Helper {
|
|
|
1262
1259
|
/**
|
|
1263
1260
|
* {{> click }}
|
|
1264
1261
|
*
|
|
1265
|
-
* {{ react }}
|
|
1266
1262
|
*/
|
|
1267
1263
|
async click(locator = '//body', context = null) {
|
|
1268
1264
|
return proceedClick.call(this, locator, context)
|
|
@@ -1271,7 +1267,6 @@ class Puppeteer extends Helper {
|
|
|
1271
1267
|
/**
|
|
1272
1268
|
* {{> forceClick }}
|
|
1273
1269
|
*
|
|
1274
|
-
* {{ react }}
|
|
1275
1270
|
*/
|
|
1276
1271
|
async forceClick(locator, context = null) {
|
|
1277
1272
|
let matcher = await this.context
|
|
@@ -1301,7 +1296,6 @@ class Puppeteer extends Helper {
|
|
|
1301
1296
|
/**
|
|
1302
1297
|
* {{> clickLink }}
|
|
1303
1298
|
*
|
|
1304
|
-
* {{ react }}
|
|
1305
1299
|
*/
|
|
1306
1300
|
async clickLink(locator, context = null) {
|
|
1307
1301
|
return proceedClick.call(this, locator, context, { waitForNavigation: true })
|
|
@@ -1325,7 +1319,7 @@ class Puppeteer extends Helper {
|
|
|
1325
1319
|
* @param {string} [downloadPath='downloads'] change this parameter to set another directory for saving
|
|
1326
1320
|
*/
|
|
1327
1321
|
async handleDownloads(downloadPath = 'downloads') {
|
|
1328
|
-
downloadPath = path.join(
|
|
1322
|
+
downloadPath = path.join(store.outputDir, downloadPath)
|
|
1329
1323
|
if (!fs.existsSync(downloadPath)) {
|
|
1330
1324
|
fs.mkdirSync(downloadPath, '0777')
|
|
1331
1325
|
}
|
|
@@ -1387,7 +1381,7 @@ class Puppeteer extends Helper {
|
|
|
1387
1381
|
},
|
|
1388
1382
|
})
|
|
1389
1383
|
|
|
1390
|
-
const outputFile = path.join(`${
|
|
1384
|
+
const outputFile = path.join(`${store.outputDir}/${fileName}`)
|
|
1391
1385
|
|
|
1392
1386
|
try {
|
|
1393
1387
|
await new Promise((resolve, reject) => {
|
|
@@ -1409,7 +1403,6 @@ class Puppeteer extends Helper {
|
|
|
1409
1403
|
/**
|
|
1410
1404
|
* {{> doubleClick }}
|
|
1411
1405
|
*
|
|
1412
|
-
* {{ react }}
|
|
1413
1406
|
*/
|
|
1414
1407
|
async doubleClick(locator, context = null) {
|
|
1415
1408
|
return proceedClick.call(this, locator, context, { clickCount: 2 })
|
|
@@ -1418,7 +1411,6 @@ class Puppeteer extends Helper {
|
|
|
1418
1411
|
/**
|
|
1419
1412
|
* {{> rightClick }}
|
|
1420
1413
|
*
|
|
1421
|
-
* {{ react }}
|
|
1422
1414
|
*/
|
|
1423
1415
|
async rightClick(locator, context = null) {
|
|
1424
1416
|
return proceedClick.call(this, locator, context, { button: 'right' })
|
|
@@ -1547,6 +1539,7 @@ class Puppeteer extends Helper {
|
|
|
1547
1539
|
* {{> pressKeyWithKeyNormalization }}
|
|
1548
1540
|
*/
|
|
1549
1541
|
async pressKey(key) {
|
|
1542
|
+
await checkFocusBeforePressKey(this, key)
|
|
1550
1543
|
const modifiers = []
|
|
1551
1544
|
if (Array.isArray(key)) {
|
|
1552
1545
|
for (let k of key) {
|
|
@@ -1575,6 +1568,8 @@ class Puppeteer extends Helper {
|
|
|
1575
1568
|
* {{> type }}
|
|
1576
1569
|
*/
|
|
1577
1570
|
async type(keys, delay = null) {
|
|
1571
|
+
await checkFocusBeforeType(this)
|
|
1572
|
+
|
|
1578
1573
|
if (!Array.isArray(keys)) {
|
|
1579
1574
|
keys = keys.toString()
|
|
1580
1575
|
keys = keys.split('')
|
|
@@ -1588,13 +1583,20 @@ class Puppeteer extends Helper {
|
|
|
1588
1583
|
|
|
1589
1584
|
/**
|
|
1590
1585
|
* {{> fillField }}
|
|
1591
|
-
* {{ react }}
|
|
1592
1586
|
*/
|
|
1593
1587
|
async fillField(field, value, context = null) {
|
|
1594
|
-
|
|
1588
|
+
let els = await findVisibleFields.call(this, field, context)
|
|
1589
|
+
if (!els.length) {
|
|
1590
|
+
els = await findFields.call(this, field, context)
|
|
1591
|
+
}
|
|
1595
1592
|
assertElementExists(els, field, 'Field')
|
|
1596
|
-
|
|
1597
|
-
|
|
1593
|
+
const el = selectElement(els, field, this)
|
|
1594
|
+
|
|
1595
|
+
if (await fillRichEditor(this, el, value)) {
|
|
1596
|
+
highlightActiveElement.call(this, el, await this._getContext())
|
|
1597
|
+
return this._waitForAction()
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1598
1600
|
const tag = await el.getProperty('tagName').then(el => el.jsonValue())
|
|
1599
1601
|
const editable = await el.getProperty('contenteditable').then(el => el.jsonValue())
|
|
1600
1602
|
if (tag === 'INPUT' || tag === 'TEXTAREA') {
|
|
@@ -1619,15 +1621,14 @@ class Puppeteer extends Helper {
|
|
|
1619
1621
|
/**
|
|
1620
1622
|
* {{> appendField }}
|
|
1621
1623
|
*
|
|
1622
|
-
* {{ react }}
|
|
1623
1624
|
*/
|
|
1624
1625
|
async appendField(field, value, context = null) {
|
|
1625
1626
|
const els = await findVisibleFields.call(this, field, context)
|
|
1626
1627
|
assertElementExists(els, field, 'Field')
|
|
1627
|
-
|
|
1628
|
-
highlightActiveElement.call(this,
|
|
1629
|
-
await
|
|
1630
|
-
await
|
|
1628
|
+
const el = selectElement(els, field, this)
|
|
1629
|
+
highlightActiveElement.call(this, el, await this._getContext())
|
|
1630
|
+
await el.press('End')
|
|
1631
|
+
await el.type(value.toString(), { delay: this.options.pressKeyDelay })
|
|
1631
1632
|
return this._waitForAction()
|
|
1632
1633
|
}
|
|
1633
1634
|
|
|
@@ -1653,29 +1654,31 @@ class Puppeteer extends Helper {
|
|
|
1653
1654
|
* {{> attachFile }}
|
|
1654
1655
|
*/
|
|
1655
1656
|
async attachFile(locator, pathToFile, context = null) {
|
|
1656
|
-
const file = path.join(
|
|
1657
|
+
const file = path.join(store.codeceptDir, pathToFile)
|
|
1657
1658
|
|
|
1658
1659
|
if (!fileExists(file)) {
|
|
1659
1660
|
throw new Error(`File at ${file} can not be found on local system`)
|
|
1660
1661
|
}
|
|
1661
1662
|
const els = await findFields.call(this, locator, context)
|
|
1662
1663
|
if (els.length) {
|
|
1663
|
-
const
|
|
1664
|
-
const
|
|
1664
|
+
const el = selectElement(els, locator, this)
|
|
1665
|
+
const tag = await el.evaluate(el => el.tagName)
|
|
1666
|
+
const type = await el.evaluate(el => el.type)
|
|
1665
1667
|
if (tag === 'INPUT' && type === 'file') {
|
|
1666
|
-
await
|
|
1668
|
+
await el.uploadFile(file)
|
|
1667
1669
|
return this._waitForAction()
|
|
1668
1670
|
}
|
|
1669
1671
|
}
|
|
1670
1672
|
|
|
1671
1673
|
const targetEls = els.length ? els : await this._locate(locator)
|
|
1672
1674
|
assertElementExists(targetEls, locator, 'Element')
|
|
1675
|
+
const el = selectElement(targetEls, locator, this)
|
|
1673
1676
|
const fileData = {
|
|
1674
1677
|
base64Content: base64EncodeFile(file),
|
|
1675
1678
|
fileName: path.basename(file),
|
|
1676
1679
|
mimeType: getMimeType(path.basename(file)),
|
|
1677
1680
|
}
|
|
1678
|
-
await
|
|
1681
|
+
await el.evaluate(dropFile, fileData)
|
|
1679
1682
|
return this._waitForAction()
|
|
1680
1683
|
}
|
|
1681
1684
|
|
|
@@ -1698,28 +1701,27 @@ class Puppeteer extends Helper {
|
|
|
1698
1701
|
this.debugSection('SelectOption', `Strict: ${JSON.stringify(select)}`)
|
|
1699
1702
|
const els = contextEl ? await findElements.call(this, contextEl, select) : await this._locate(select)
|
|
1700
1703
|
assertElementExists(els, select, 'Selectable element')
|
|
1701
|
-
return proceedSelect.call(this, pageContext, els
|
|
1704
|
+
return proceedSelect.call(this, pageContext, selectElement(els, select, this), option)
|
|
1702
1705
|
}
|
|
1703
1706
|
|
|
1704
1707
|
// Fuzzy: try combobox
|
|
1705
1708
|
this.debugSection('SelectOption', `Fuzzy: "${matchedLocator.value}"`)
|
|
1706
1709
|
const comboboxSearchCtx = contextEl || pageContext
|
|
1707
1710
|
let els = await findByRole(comboboxSearchCtx, { role: 'combobox', name: matchedLocator.value })
|
|
1708
|
-
if (els?.length) return proceedSelect.call(this, pageContext, els
|
|
1711
|
+
if (els?.length) return proceedSelect.call(this, pageContext, selectElement(els, select, this), option)
|
|
1709
1712
|
|
|
1710
1713
|
// Fuzzy: try listbox
|
|
1711
1714
|
els = await findByRole(comboboxSearchCtx, { role: 'listbox', name: matchedLocator.value })
|
|
1712
|
-
if (els?.length) return proceedSelect.call(this, pageContext, els
|
|
1715
|
+
if (els?.length) return proceedSelect.call(this, pageContext, selectElement(els, select, this), option)
|
|
1713
1716
|
|
|
1714
1717
|
// Fuzzy: try native select
|
|
1715
1718
|
const visibleEls = await findVisibleFields.call(this, select, context)
|
|
1716
1719
|
assertElementExists(visibleEls, select, 'Selectable field')
|
|
1717
|
-
return proceedSelect.call(this, pageContext, visibleEls
|
|
1720
|
+
return proceedSelect.call(this, pageContext, selectElement(visibleEls, select, this), option)
|
|
1718
1721
|
}
|
|
1719
1722
|
|
|
1720
1723
|
/**
|
|
1721
1724
|
* {{> grabNumberOfVisibleElements }}
|
|
1722
|
-
* {{ react }}
|
|
1723
1725
|
*/
|
|
1724
1726
|
async grabNumberOfVisibleElements(locator) {
|
|
1725
1727
|
let els = await this._locate(locator)
|
|
@@ -1781,7 +1783,6 @@ class Puppeteer extends Helper {
|
|
|
1781
1783
|
/**
|
|
1782
1784
|
* {{> see }}
|
|
1783
1785
|
*
|
|
1784
|
-
* {{ react }}
|
|
1785
1786
|
*/
|
|
1786
1787
|
async see(text, context = null) {
|
|
1787
1788
|
return proceedSee.call(this, 'assert', text, context)
|
|
@@ -1797,7 +1798,6 @@ class Puppeteer extends Helper {
|
|
|
1797
1798
|
/**
|
|
1798
1799
|
* {{> dontSee }}
|
|
1799
1800
|
*
|
|
1800
|
-
* {{ react }}
|
|
1801
1801
|
*/
|
|
1802
1802
|
async dontSee(text, context = null) {
|
|
1803
1803
|
return proceedSee.call(this, 'negate', text, context)
|
|
@@ -1851,7 +1851,6 @@ class Puppeteer extends Helper {
|
|
|
1851
1851
|
/**
|
|
1852
1852
|
* {{> seeNumberOfElements }}
|
|
1853
1853
|
*
|
|
1854
|
-
* {{ react }}
|
|
1855
1854
|
*/
|
|
1856
1855
|
async seeNumberOfElements(locator, num) {
|
|
1857
1856
|
const elements = await this._locate(locator)
|
|
@@ -1861,7 +1860,6 @@ class Puppeteer extends Helper {
|
|
|
1861
1860
|
/**
|
|
1862
1861
|
* {{> seeNumberOfVisibleElements }}
|
|
1863
1862
|
*
|
|
1864
|
-
* {{ react }}
|
|
1865
1863
|
*/
|
|
1866
1864
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1867
1865
|
const res = await this.grabNumberOfVisibleElements(locator)
|
|
@@ -1988,7 +1986,6 @@ class Puppeteer extends Helper {
|
|
|
1988
1986
|
|
|
1989
1987
|
/**
|
|
1990
1988
|
* {{> grabTextFromAll }}
|
|
1991
|
-
* {{ react }}
|
|
1992
1989
|
*/
|
|
1993
1990
|
async grabTextFromAll(locator) {
|
|
1994
1991
|
const els = await this._locate(locator)
|
|
@@ -2001,7 +1998,6 @@ class Puppeteer extends Helper {
|
|
|
2001
1998
|
|
|
2002
1999
|
/**
|
|
2003
2000
|
* {{> grabTextFrom }}
|
|
2004
|
-
* {{ react }}
|
|
2005
2001
|
*/
|
|
2006
2002
|
async grabTextFrom(locator) {
|
|
2007
2003
|
const texts = await this.grabTextFromAll(locator)
|
|
@@ -2062,7 +2058,6 @@ class Puppeteer extends Helper {
|
|
|
2062
2058
|
|
|
2063
2059
|
/**
|
|
2064
2060
|
* {{> grabCssPropertyFromAll }}
|
|
2065
|
-
* {{ react }}
|
|
2066
2061
|
*/
|
|
2067
2062
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
2068
2063
|
const els = await this._locate(locator)
|
|
@@ -2074,7 +2069,6 @@ class Puppeteer extends Helper {
|
|
|
2074
2069
|
|
|
2075
2070
|
/**
|
|
2076
2071
|
* {{> grabCssPropertyFrom }}
|
|
2077
|
-
* {{ react }}
|
|
2078
2072
|
*/
|
|
2079
2073
|
async grabCssPropertyFrom(locator, cssProperty) {
|
|
2080
2074
|
const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
|
|
@@ -2089,7 +2083,6 @@ class Puppeteer extends Helper {
|
|
|
2089
2083
|
|
|
2090
2084
|
/**
|
|
2091
2085
|
* {{> seeCssPropertiesOnElements }}
|
|
2092
|
-
* {{ react }}
|
|
2093
2086
|
*/
|
|
2094
2087
|
async seeCssPropertiesOnElements(locator, cssProperties) {
|
|
2095
2088
|
const res = await this._locate(locator)
|
|
@@ -2124,7 +2117,6 @@ class Puppeteer extends Helper {
|
|
|
2124
2117
|
|
|
2125
2118
|
/**
|
|
2126
2119
|
* {{> seeAttributesOnElements }}
|
|
2127
|
-
* {{ react }}
|
|
2128
2120
|
*/
|
|
2129
2121
|
async seeAttributesOnElements(locator, attributes) {
|
|
2130
2122
|
const elements = await this._locate(locator)
|
|
@@ -2162,7 +2154,6 @@ class Puppeteer extends Helper {
|
|
|
2162
2154
|
|
|
2163
2155
|
/**
|
|
2164
2156
|
* {{> dragSlider }}
|
|
2165
|
-
* {{ react }}
|
|
2166
2157
|
*/
|
|
2167
2158
|
async dragSlider(locator, offsetX = 0) {
|
|
2168
2159
|
const src = await this._locate(locator)
|
|
@@ -2184,7 +2175,6 @@ class Puppeteer extends Helper {
|
|
|
2184
2175
|
|
|
2185
2176
|
/**
|
|
2186
2177
|
* {{> grabAttributeFromAll }}
|
|
2187
|
-
* {{ react }}
|
|
2188
2178
|
*/
|
|
2189
2179
|
async grabAttributeFromAll(locator, attr) {
|
|
2190
2180
|
const els = await this._locate(locator)
|
|
@@ -2198,7 +2188,6 @@ class Puppeteer extends Helper {
|
|
|
2198
2188
|
|
|
2199
2189
|
/**
|
|
2200
2190
|
* {{> grabAttributeFrom }}
|
|
2201
|
-
* {{ react }}
|
|
2202
2191
|
*/
|
|
2203
2192
|
async grabAttributeFrom(locator, attr) {
|
|
2204
2193
|
const attrs = await this.grabAttributeFromAll(locator, attr)
|
|
@@ -2361,7 +2350,6 @@ class Puppeteer extends Helper {
|
|
|
2361
2350
|
|
|
2362
2351
|
/**
|
|
2363
2352
|
* {{> waitNumberOfVisibleElements }}
|
|
2364
|
-
* {{ react }}
|
|
2365
2353
|
*/
|
|
2366
2354
|
async waitNumberOfVisibleElements(locator, num, sec) {
|
|
2367
2355
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
@@ -2409,7 +2397,6 @@ class Puppeteer extends Helper {
|
|
|
2409
2397
|
|
|
2410
2398
|
/**
|
|
2411
2399
|
* {{> waitForElement }}
|
|
2412
|
-
* {{ react }}
|
|
2413
2400
|
*/
|
|
2414
2401
|
async waitForElement(locator, sec) {
|
|
2415
2402
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
@@ -2430,7 +2417,6 @@ class Puppeteer extends Helper {
|
|
|
2430
2417
|
/**
|
|
2431
2418
|
* {{> waitForVisible }}
|
|
2432
2419
|
*
|
|
2433
|
-
* {{ react }}
|
|
2434
2420
|
*/
|
|
2435
2421
|
async waitForVisible(locator, sec) {
|
|
2436
2422
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
@@ -3007,10 +2993,6 @@ export default Puppeteer
|
|
|
3007
2993
|
* @returns {Promise<Array>} Array of ElementHandle objects
|
|
3008
2994
|
*/
|
|
3009
2995
|
async function findElements(matcher, locator) {
|
|
3010
|
-
// Check if locator is a Locator object with react type, or a raw object with react property
|
|
3011
|
-
const isReactLocator = locator.type === 'react' || (locator.locator && locator.locator.react) || locator.react
|
|
3012
|
-
if (isReactLocator) return findReactElements.call(this, locator)
|
|
3013
|
-
|
|
3014
2996
|
locator = new Locator(locator, 'css')
|
|
3015
2997
|
|
|
3016
2998
|
// Check if locator is a role locator and call findByRole
|
|
@@ -3077,7 +3059,6 @@ async function findElements(matcher, locator) {
|
|
|
3077
3059
|
* @returns {Promise<Object>} Single ElementHandle object
|
|
3078
3060
|
*/
|
|
3079
3061
|
async function findElement(matcher, locator) {
|
|
3080
|
-
if (locator.react) return findReactElements.call(this, locator)
|
|
3081
3062
|
locator = new Locator(locator, 'css')
|
|
3082
3063
|
|
|
3083
3064
|
// Check if locator is a role locator and call findByRole
|
|
@@ -3121,11 +3102,11 @@ async function proceedClick(locator, context = null, options = {}) {
|
|
|
3121
3102
|
} else {
|
|
3122
3103
|
assertElementExists(els, locator, 'Clickable element')
|
|
3123
3104
|
}
|
|
3124
|
-
|
|
3105
|
+
const el = selectElement(els, locator, this)
|
|
3125
3106
|
|
|
3126
|
-
highlightActiveElement.call(this,
|
|
3107
|
+
highlightActiveElement.call(this, el, await this._getContext())
|
|
3127
3108
|
|
|
3128
|
-
await
|
|
3109
|
+
await el.click(options)
|
|
3129
3110
|
const promises = []
|
|
3130
3111
|
if (options.waitForNavigation) {
|
|
3131
3112
|
promises.push(this.waitForNavigation())
|
|
@@ -3563,7 +3544,7 @@ function getNormalizedKey(key) {
|
|
|
3563
3544
|
}
|
|
3564
3545
|
|
|
3565
3546
|
function highlightActiveElement(element, context) {
|
|
3566
|
-
if (this.options.highlightElement &&
|
|
3547
|
+
if (this.options.highlightElement && store.debugMode) {
|
|
3567
3548
|
highlightElement(element, context)
|
|
3568
3549
|
}
|
|
3569
3550
|
}
|
|
@@ -3576,75 +3557,6 @@ function _waitForElement(locator, options) {
|
|
|
3576
3557
|
}
|
|
3577
3558
|
}
|
|
3578
3559
|
|
|
3579
|
-
async function findReactElements(locator) {
|
|
3580
|
-
// Handle both Locator objects and raw locator objects
|
|
3581
|
-
const resolved = locator.locator ? locator.locator : toLocatorConfig(locator, 'react')
|
|
3582
|
-
this.debug(`Finding React elements: ${JSON.stringify(resolved)}`)
|
|
3583
|
-
|
|
3584
|
-
// Use createRequire to access require.resolve in ESM
|
|
3585
|
-
const { createRequire } = await import('module')
|
|
3586
|
-
const require = createRequire(import.meta.url)
|
|
3587
|
-
const resqScript = await fs.promises.readFile(require.resolve('resq'), 'utf-8')
|
|
3588
|
-
await this.page.evaluate(resqScript.toString())
|
|
3589
|
-
|
|
3590
|
-
await this.page.evaluate(() => window.resq.waitToLoadReact())
|
|
3591
|
-
const arrayHandle = await this.page.evaluateHandle(
|
|
3592
|
-
obj => {
|
|
3593
|
-
const { selector, props, state } = obj
|
|
3594
|
-
let elements = window.resq.resq$$(selector)
|
|
3595
|
-
if (Object.keys(props).length) {
|
|
3596
|
-
elements = elements.byProps(props)
|
|
3597
|
-
}
|
|
3598
|
-
if (Object.keys(state).length) {
|
|
3599
|
-
elements = elements.byState(state)
|
|
3600
|
-
}
|
|
3601
|
-
|
|
3602
|
-
if (!elements.length) {
|
|
3603
|
-
return []
|
|
3604
|
-
}
|
|
3605
|
-
|
|
3606
|
-
// resq returns an array of HTMLElements if the React component is a fragment
|
|
3607
|
-
// this avoids having nested arrays of nodes which the driver does not understand
|
|
3608
|
-
// [[div, div], [div, div]] => [div, div, div, div]
|
|
3609
|
-
let nodes = []
|
|
3610
|
-
|
|
3611
|
-
elements.forEach(element => {
|
|
3612
|
-
let { node, isFragment } = element
|
|
3613
|
-
|
|
3614
|
-
if (!node) {
|
|
3615
|
-
isFragment = true
|
|
3616
|
-
node = element.children
|
|
3617
|
-
}
|
|
3618
|
-
|
|
3619
|
-
if (isFragment) {
|
|
3620
|
-
nodes = nodes.concat(node)
|
|
3621
|
-
} else {
|
|
3622
|
-
nodes.push(node)
|
|
3623
|
-
}
|
|
3624
|
-
})
|
|
3625
|
-
|
|
3626
|
-
return [...nodes]
|
|
3627
|
-
},
|
|
3628
|
-
{
|
|
3629
|
-
selector: resolved.react,
|
|
3630
|
-
props: resolved.props || {},
|
|
3631
|
-
state: resolved.state || {},
|
|
3632
|
-
},
|
|
3633
|
-
)
|
|
3634
|
-
|
|
3635
|
-
const properties = await arrayHandle.getProperties()
|
|
3636
|
-
const result = []
|
|
3637
|
-
for (const property of properties.values()) {
|
|
3638
|
-
const elementHandle = property.asElement()
|
|
3639
|
-
if (elementHandle) {
|
|
3640
|
-
result.push(elementHandle)
|
|
3641
|
-
}
|
|
3642
|
-
}
|
|
3643
|
-
|
|
3644
|
-
await arrayHandle.dispose()
|
|
3645
|
-
return result
|
|
3646
|
-
}
|
|
3647
|
-
|
|
3648
3560
|
async function findByRole(matcher, locator) {
|
|
3649
3561
|
const resolved = toLocatorConfig(locator, 'role')
|
|
3650
3562
|
const roleSelector = buildRoleSelector(resolved)
|