codeceptjs 4.0.0-beta.3 → 4.0.0-beta.5
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 +134 -119
- package/bin/codecept.js +12 -2
- package/bin/test-server.js +53 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/lib/actor.js +66 -102
- package/lib/ai.js +130 -121
- package/lib/assert/empty.js +3 -5
- package/lib/assert/equal.js +4 -7
- package/lib/assert/include.js +4 -6
- package/lib/assert/throws.js +2 -4
- package/lib/assert/truth.js +2 -2
- package/lib/codecept.js +141 -86
- package/lib/command/check.js +201 -0
- package/lib/command/configMigrate.js +2 -4
- package/lib/command/definitions.js +8 -26
- package/lib/command/dryRun.js +30 -35
- package/lib/command/generate.js +10 -14
- package/lib/command/gherkin/snippets.js +75 -73
- package/lib/command/gherkin/steps.js +1 -1
- package/lib/command/info.js +42 -8
- package/lib/command/init.js +13 -12
- package/lib/command/interactive.js +10 -2
- package/lib/command/list.js +1 -1
- package/lib/command/run-multiple/chunk.js +48 -45
- package/lib/command/run-multiple.js +12 -35
- package/lib/command/run-workers.js +21 -58
- package/lib/command/utils.js +5 -6
- package/lib/command/workers/runTests.js +263 -222
- package/lib/container.js +386 -238
- package/lib/data/context.js +10 -13
- package/lib/data/dataScenarioConfig.js +8 -8
- package/lib/data/dataTableArgument.js +6 -6
- package/lib/data/table.js +5 -11
- package/lib/effects.js +223 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +158 -0
- package/lib/event.js +21 -17
- package/lib/heal.js +88 -80
- package/lib/helper/AI.js +2 -1
- package/lib/helper/ApiDataFactory.js +4 -7
- package/lib/helper/Appium.js +50 -57
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +4 -4
- package/lib/helper/JSONResponse.js +75 -37
- package/lib/helper/Mochawesome.js +31 -9
- package/lib/helper/Nightmare.js +37 -58
- package/lib/helper/Playwright.js +267 -272
- package/lib/helper/Protractor.js +56 -87
- package/lib/helper/Puppeteer.js +247 -264
- package/lib/helper/REST.js +29 -17
- package/lib/helper/TestCafe.js +22 -47
- package/lib/helper/WebDriver.js +157 -368
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/network/utils.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +27 -28
- package/lib/listener/emptyRun.js +55 -0
- package/lib/listener/exit.js +7 -10
- package/lib/listener/{retry.js → globalRetry.js} +5 -5
- package/lib/listener/globalTimeout.js +165 -0
- package/lib/listener/helpers.js +15 -15
- package/lib/listener/mocha.js +1 -1
- package/lib/listener/result.js +12 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +32 -18
- package/lib/listener/store.js +20 -0
- package/lib/locator.js +1 -1
- package/lib/mocha/asyncWrapper.js +231 -0
- package/lib/{interfaces → mocha}/bdd.js +3 -3
- package/lib/mocha/cli.js +308 -0
- package/lib/mocha/factory.js +104 -0
- package/lib/{interfaces → mocha}/featureConfig.js +32 -12
- package/lib/{interfaces → mocha}/gherkin.js +26 -28
- package/lib/mocha/hooks.js +112 -0
- package/lib/mocha/index.js +12 -0
- package/lib/mocha/inject.js +29 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
- package/lib/mocha/suite.js +82 -0
- package/lib/mocha/test.js +181 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +232 -0
- package/lib/output.js +93 -65
- package/lib/pause.js +160 -138
- package/lib/plugin/analyze.js +396 -0
- package/lib/plugin/auth.js +435 -0
- package/lib/plugin/autoDelay.js +8 -8
- package/lib/plugin/autoLogin.js +3 -338
- package/lib/plugin/commentStep.js +6 -1
- package/lib/plugin/coverage.js +10 -22
- package/lib/plugin/customLocator.js +3 -3
- package/lib/plugin/customReporter.js +52 -0
- package/lib/plugin/eachElement.js +1 -1
- package/lib/plugin/fakerTransform.js +1 -1
- package/lib/plugin/heal.js +36 -9
- package/lib/plugin/htmlReporter.js +1947 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/retryFailedStep.js +17 -18
- package/lib/plugin/retryTo.js +2 -113
- package/lib/plugin/screenshotOnFail.js +17 -58
- package/lib/plugin/selenoid.js +15 -35
- package/lib/plugin/standardActingHelpers.js +4 -1
- package/lib/plugin/stepByStepReport.js +56 -17
- package/lib/plugin/stepTimeout.js +5 -12
- package/lib/plugin/subtitles.js +4 -4
- package/lib/plugin/tryTo.js +3 -102
- package/lib/plugin/wdio.js +8 -10
- package/lib/recorder.js +155 -124
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/secret.js +1 -2
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +21 -332
- package/lib/steps.js +50 -0
- package/lib/store.js +37 -5
- package/lib/template/heal.js +2 -11
- package/lib/test-server.js +323 -0
- package/lib/timeout.js +66 -0
- package/lib/utils.js +351 -218
- package/lib/within.js +75 -55
- package/lib/workerStorage.js +2 -1
- package/lib/workers.js +386 -277
- package/package.json +81 -75
- package/translations/de-DE.js +5 -3
- package/translations/fr-FR.js +5 -4
- package/translations/index.js +1 -0
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +9 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +197 -187
- package/typings/promiseBasedTypes.d.ts +53 -903
- package/typings/types.d.ts +372 -1042
- package/lib/cli.js +0 -257
- package/lib/helper/ExpectHelper.js +0 -391
- package/lib/helper/MockServer.js +0 -221
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -113
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/scenario.js +0 -224
- package/lib/ui.js +0 -236
package/lib/helper/WebDriver.js
CHANGED
|
@@ -7,19 +7,11 @@ const Helper = require('@codeceptjs/helper')
|
|
|
7
7
|
const promiseRetry = require('promise-retry')
|
|
8
8
|
const stringIncludes = require('../assert/include').includes
|
|
9
9
|
const { urlEquals, equals } = require('../assert/equal')
|
|
10
|
+
const store = require('../store')
|
|
10
11
|
const { debug } = require('../output')
|
|
11
12
|
const { empty } = require('../assert/empty')
|
|
12
13
|
const { truth } = require('../assert/truth')
|
|
13
|
-
const {
|
|
14
|
-
xpathLocator,
|
|
15
|
-
fileExists,
|
|
16
|
-
decodeUrl,
|
|
17
|
-
chunkArray,
|
|
18
|
-
convertCssPropertiesToCamelCase,
|
|
19
|
-
screenshotOutputFolder,
|
|
20
|
-
getNormalizedKeyAttributeValue,
|
|
21
|
-
modifierKeys,
|
|
22
|
-
} = require('../utils')
|
|
14
|
+
const { xpathLocator, fileExists, decodeUrl, chunkArray, convertCssPropertiesToCamelCase, screenshotOutputFolder, getNormalizedKeyAttributeValue, modifierKeys } = require('../utils')
|
|
23
15
|
const { isColorProperty, convertColorToRGBA } = require('../colorUtils')
|
|
24
16
|
const ElementNotFound = require('./errors/ElementNotFound')
|
|
25
17
|
const ConnectionRefused = require('./errors/ConnectionRefused')
|
|
@@ -27,22 +19,13 @@ const Locator = require('../locator')
|
|
|
27
19
|
const { highlightElement } = require('./scripts/highlightElement')
|
|
28
20
|
const { focusElement } = require('./scripts/focusElement')
|
|
29
21
|
const { blurElement } = require('./scripts/blurElement')
|
|
30
|
-
const {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
seeElementInDOMError,
|
|
34
|
-
dontSeeElementInDOMError,
|
|
35
|
-
} = require('./errors/ElementAssertion')
|
|
36
|
-
const {
|
|
37
|
-
dontSeeTraffic,
|
|
38
|
-
seeTraffic,
|
|
39
|
-
grabRecordedNetworkTraffics,
|
|
40
|
-
stopRecordingTraffic,
|
|
41
|
-
flushNetworkTraffics,
|
|
42
|
-
} = require('./network/actions')
|
|
22
|
+
const { dontSeeElementError, seeElementError, seeElementInDOMError, dontSeeElementInDOMError } = require('./errors/ElementAssertion')
|
|
23
|
+
const { dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics } = require('./network/actions')
|
|
24
|
+
const WebElement = require('../element/WebElement')
|
|
43
25
|
|
|
44
26
|
const SHADOW = 'shadow'
|
|
45
27
|
const webRoot = 'body'
|
|
28
|
+
let browserLogs = []
|
|
46
29
|
|
|
47
30
|
/**
|
|
48
31
|
* ## Configuration
|
|
@@ -53,6 +36,7 @@ const webRoot = 'body'
|
|
|
53
36
|
* @type {object}
|
|
54
37
|
* @prop {string} url - base url of website to be tested.
|
|
55
38
|
* @prop {string} browser - Browser in which to perform testing.
|
|
39
|
+
* @prop {boolean} [bidiProtocol=false] - WebDriver Bidi Protocol. Default: false. More info: https://webdriver.io/docs/api/webdriverBidi/
|
|
56
40
|
* @prop {string} [basicAuth] - (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'}
|
|
57
41
|
* @prop {string} [host=localhost] - WebDriver host to connect.
|
|
58
42
|
* @prop {number} [port=4444] - WebDriver port to connect.
|
|
@@ -72,7 +56,6 @@ const webRoot = 'body'
|
|
|
72
56
|
* @prop {object} [timeouts] [WebDriver timeouts](http://webdriver.io/docs/timeouts.html) defined as hash.
|
|
73
57
|
* @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose).
|
|
74
58
|
* @prop {string} [logLevel=silent] - level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: https://webdriver.io/docs/configuration/#loglevel
|
|
75
|
-
* @prop {boolean} [devtoolsProtocol=false] - enable devtools protocol. Default: false. More info: https://webdriver.io/docs/automationProtocols/#devtools-protocol.
|
|
76
59
|
*/
|
|
77
60
|
const config = {}
|
|
78
61
|
|
|
@@ -180,7 +163,6 @@ const config = {}
|
|
|
180
163
|
* WebDriver : {
|
|
181
164
|
* url: "http://localhost",
|
|
182
165
|
* browser: "chrome",
|
|
183
|
-
* devtoolsProtocol: true,
|
|
184
166
|
* desiredCapabilities: {
|
|
185
167
|
* chromeOptions: {
|
|
186
168
|
* args: [ "--headless", "--disable-gpu", "--no-sandbox" ]
|
|
@@ -508,6 +490,10 @@ class WebDriver extends Helper {
|
|
|
508
490
|
config.capabilities = config.desiredCapabilities
|
|
509
491
|
}
|
|
510
492
|
config.capabilities.browserName = config.browser || config.capabilities.browserName
|
|
493
|
+
|
|
494
|
+
// WebDriver Bidi Protocol. Default: false
|
|
495
|
+
config.capabilities.webSocketUrl = config.bidiProtocol ?? config.capabilities.webSocketUrl ?? true
|
|
496
|
+
|
|
511
497
|
config.capabilities.browserVersion = config.browserVersion || config.capabilities.browserVersion
|
|
512
498
|
if (config.capabilities.chromeOptions) {
|
|
513
499
|
config.capabilities['goog:chromeOptions'] = config.capabilities.chromeOptions
|
|
@@ -597,10 +583,7 @@ class WebDriver extends Helper {
|
|
|
597
583
|
}
|
|
598
584
|
|
|
599
585
|
async _res(locator) {
|
|
600
|
-
const res =
|
|
601
|
-
this._isShadowLocator(locator) || this._isCustomLocator(locator)
|
|
602
|
-
? await this._locate(locator)
|
|
603
|
-
: await this.$$(withStrictLocator(locator))
|
|
586
|
+
const res = this._isShadowLocator(locator) || this._isCustomLocator(locator) ? await this._locate(locator) : await this.$$(withStrictLocator(locator))
|
|
604
587
|
return res
|
|
605
588
|
}
|
|
606
589
|
|
|
@@ -614,11 +597,6 @@ class WebDriver extends Helper {
|
|
|
614
597
|
delete this.options.capabilities.hostname
|
|
615
598
|
delete this.options.capabilities.port
|
|
616
599
|
delete this.options.capabilities.path
|
|
617
|
-
if (this.options.devtoolsProtocol) {
|
|
618
|
-
if (!['chrome', 'chromium'].includes(this.options.browser.toLowerCase()))
|
|
619
|
-
throw Error('The devtools protocol is only working with Chrome or Chromium')
|
|
620
|
-
this.options.automationProtocol = 'devtools'
|
|
621
|
-
}
|
|
622
600
|
this.browser = await webdriverio.remote(this.options)
|
|
623
601
|
}
|
|
624
602
|
} catch (err) {
|
|
@@ -638,7 +616,7 @@ class WebDriver extends Helper {
|
|
|
638
616
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
639
617
|
|
|
640
618
|
if (this._isCustomLocatorStrategyDefined()) {
|
|
641
|
-
Object.keys(this.customLocatorStrategies).forEach(async
|
|
619
|
+
Object.keys(this.customLocatorStrategies).forEach(async customLocator => {
|
|
642
620
|
this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`)
|
|
643
621
|
const locatorFunction = this._lookupCustomLocator(customLocator)
|
|
644
622
|
this.browser.addLocatorStrategy(customLocator, locatorFunction)
|
|
@@ -649,10 +627,10 @@ class WebDriver extends Helper {
|
|
|
649
627
|
this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase()
|
|
650
628
|
}
|
|
651
629
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
630
|
+
this.browser.on('dialog', () => {})
|
|
631
|
+
|
|
632
|
+
await this.browser.sessionSubscribe({ events: ['log.entryAdded'] })
|
|
633
|
+
this.browser.on('log.entryAdded', logEvents)
|
|
656
634
|
|
|
657
635
|
return this.browser
|
|
658
636
|
}
|
|
@@ -679,7 +657,7 @@ class WebDriver extends Helper {
|
|
|
679
657
|
this.isRunning = false
|
|
680
658
|
return this.browser.deleteSession()
|
|
681
659
|
}
|
|
682
|
-
if (this.browser.isInsideFrame) await this.browser.
|
|
660
|
+
if (this.browser.isInsideFrame) await this.browser.switchFrame(null)
|
|
683
661
|
|
|
684
662
|
if (this.options.keepBrowserState) return
|
|
685
663
|
|
|
@@ -687,10 +665,11 @@ class WebDriver extends Helper {
|
|
|
687
665
|
this.debugSection('Session', 'cleaning cookies and localStorage')
|
|
688
666
|
await this.browser.deleteCookies()
|
|
689
667
|
}
|
|
690
|
-
await this.browser.execute('localStorage.clear();').catch(
|
|
668
|
+
await this.browser.execute('localStorage.clear();').catch(err => {
|
|
691
669
|
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
|
|
692
670
|
})
|
|
693
671
|
await this.closeOtherTabs()
|
|
672
|
+
browserLogs = []
|
|
694
673
|
return this.browser
|
|
695
674
|
}
|
|
696
675
|
|
|
@@ -717,17 +696,17 @@ class WebDriver extends Helper {
|
|
|
717
696
|
|
|
718
697
|
return browser
|
|
719
698
|
},
|
|
720
|
-
stop: async
|
|
699
|
+
stop: async browser => {
|
|
721
700
|
if (!browser) return
|
|
722
701
|
return browser.deleteSession()
|
|
723
702
|
},
|
|
724
|
-
loadVars: async
|
|
703
|
+
loadVars: async browser => {
|
|
725
704
|
if (this.context !== this.root) throw new Error("Can't start session inside within block")
|
|
726
705
|
this.browser = browser
|
|
727
706
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
728
707
|
this.sessionWindows[this.activeSessionName] = browser
|
|
729
708
|
},
|
|
730
|
-
restoreVars: async
|
|
709
|
+
restoreVars: async session => {
|
|
731
710
|
if (!session) {
|
|
732
711
|
this.activeSessionName = ''
|
|
733
712
|
}
|
|
@@ -769,7 +748,7 @@ class WebDriver extends Helper {
|
|
|
769
748
|
this.browser.isInsideFrame = true
|
|
770
749
|
if (Array.isArray(frame)) {
|
|
771
750
|
// this.switchTo(null);
|
|
772
|
-
await forEachAsync(frame, async
|
|
751
|
+
await forEachAsync(frame, async f => this.switchTo(f))
|
|
773
752
|
return
|
|
774
753
|
}
|
|
775
754
|
await this.switchTo(frame)
|
|
@@ -847,10 +826,7 @@ class WebDriver extends Helper {
|
|
|
847
826
|
* @param {object} locator
|
|
848
827
|
*/
|
|
849
828
|
async _smartWait(locator) {
|
|
850
|
-
this.debugSection(
|
|
851
|
-
`SmartWait (${this.options.smartWait}ms)`,
|
|
852
|
-
`Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`,
|
|
853
|
-
)
|
|
829
|
+
this.debugSection(`SmartWait (${this.options.smartWait}ms)`, `Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`)
|
|
854
830
|
await this.defineTimeout({ implicit: this.options.smartWait })
|
|
855
831
|
}
|
|
856
832
|
|
|
@@ -925,7 +901,7 @@ class WebDriver extends Helper {
|
|
|
925
901
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
926
902
|
*/
|
|
927
903
|
async _locateCheckable(locator) {
|
|
928
|
-
return findCheckable.call(this, locator, this.$$.bind(this)).then(
|
|
904
|
+
return findCheckable.call(this, locator, this.$$.bind(this)).then(res => res)
|
|
929
905
|
}
|
|
930
906
|
|
|
931
907
|
/**
|
|
@@ -953,7 +929,7 @@ class WebDriver extends Helper {
|
|
|
953
929
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
954
930
|
*/
|
|
955
931
|
async _locateFields(locator) {
|
|
956
|
-
return findFields.call(this, locator).then(
|
|
932
|
+
return findFields.call(this, locator).then(res => res)
|
|
957
933
|
}
|
|
958
934
|
|
|
959
935
|
/**
|
|
@@ -961,7 +937,20 @@ class WebDriver extends Helper {
|
|
|
961
937
|
*
|
|
962
938
|
*/
|
|
963
939
|
async grabWebElements(locator) {
|
|
964
|
-
|
|
940
|
+
const elements = await this._locate(locator)
|
|
941
|
+
return elements.map(element => new WebElement(element, this))
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* {{> grabWebElement }}
|
|
946
|
+
*
|
|
947
|
+
*/
|
|
948
|
+
async grabWebElement(locator) {
|
|
949
|
+
const elements = await this._locate(locator)
|
|
950
|
+
if (elements.length === 0) {
|
|
951
|
+
throw new ElementNotFound(locator, 'Element')
|
|
952
|
+
}
|
|
953
|
+
return new WebElement(elements[0], this)
|
|
965
954
|
}
|
|
966
955
|
|
|
967
956
|
/**
|
|
@@ -1037,7 +1026,7 @@ class WebDriver extends Helper {
|
|
|
1037
1026
|
const elem = usingFirstElement(res)
|
|
1038
1027
|
highlightActiveElement.call(this, elem)
|
|
1039
1028
|
|
|
1040
|
-
return this.executeScript(
|
|
1029
|
+
return this.executeScript(el => {
|
|
1041
1030
|
if (document.activeElement instanceof HTMLElement) {
|
|
1042
1031
|
document.activeElement.blur()
|
|
1043
1032
|
}
|
|
@@ -1109,7 +1098,7 @@ class WebDriver extends Helper {
|
|
|
1109
1098
|
}
|
|
1110
1099
|
const elem = usingFirstElement(res)
|
|
1111
1100
|
|
|
1112
|
-
return this.executeScript(
|
|
1101
|
+
return this.executeScript(el => {
|
|
1113
1102
|
if (document.activeElement instanceof HTMLElement) {
|
|
1114
1103
|
document.activeElement.blur()
|
|
1115
1104
|
}
|
|
@@ -1143,10 +1132,6 @@ class WebDriver extends Helper {
|
|
|
1143
1132
|
assertElementExists(res, field, 'Field')
|
|
1144
1133
|
const elem = usingFirstElement(res)
|
|
1145
1134
|
highlightActiveElement.call(this, elem)
|
|
1146
|
-
if (this.options.automationProtocol) {
|
|
1147
|
-
const curentValue = await elem.getValue()
|
|
1148
|
-
return elem.setValue(curentValue + value.toString())
|
|
1149
|
-
}
|
|
1150
1135
|
return elem.addValue(value.toString())
|
|
1151
1136
|
}
|
|
1152
1137
|
|
|
@@ -1159,9 +1144,6 @@ class WebDriver extends Helper {
|
|
|
1159
1144
|
assertElementExists(res, field, 'Field')
|
|
1160
1145
|
const elem = usingFirstElement(res)
|
|
1161
1146
|
highlightActiveElement.call(this, elem)
|
|
1162
|
-
if (this.options.automationProtocol) {
|
|
1163
|
-
return elem.setValue('')
|
|
1164
|
-
}
|
|
1165
1147
|
return elem.clearValue(getElementId(elem))
|
|
1166
1148
|
}
|
|
1167
1149
|
|
|
@@ -1179,15 +1161,9 @@ class WebDriver extends Helper {
|
|
|
1179
1161
|
}
|
|
1180
1162
|
|
|
1181
1163
|
// select options by visible text
|
|
1182
|
-
let els = await forEachAsync(option, async (opt)
|
|
1183
|
-
this.browser.findElementsFromElement(
|
|
1184
|
-
getElementId(elem),
|
|
1185
|
-
'xpath',
|
|
1186
|
-
Locator.select.byVisibleText(xpathLocator.literal(opt)),
|
|
1187
|
-
),
|
|
1188
|
-
)
|
|
1164
|
+
let els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byVisibleText(xpathLocator.literal(opt))))
|
|
1189
1165
|
|
|
1190
|
-
const clickOptionFn = async
|
|
1166
|
+
const clickOptionFn = async el => {
|
|
1191
1167
|
if (el[0]) el = el[0]
|
|
1192
1168
|
const elementId = getElementId(el)
|
|
1193
1169
|
if (elementId) return this.browser.elementClick(elementId)
|
|
@@ -1197,19 +1173,9 @@ class WebDriver extends Helper {
|
|
|
1197
1173
|
return forEachAsync(els, clickOptionFn)
|
|
1198
1174
|
}
|
|
1199
1175
|
// select options by value
|
|
1200
|
-
els = await forEachAsync(option, async (opt)
|
|
1201
|
-
this.browser.findElementsFromElement(
|
|
1202
|
-
getElementId(elem),
|
|
1203
|
-
'xpath',
|
|
1204
|
-
Locator.select.byValue(xpathLocator.literal(opt)),
|
|
1205
|
-
),
|
|
1206
|
-
)
|
|
1176
|
+
els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byValue(xpathLocator.literal(opt))))
|
|
1207
1177
|
if (els.length === 0) {
|
|
1208
|
-
throw new ElementNotFound(
|
|
1209
|
-
select,
|
|
1210
|
-
`Option "${option}" in`,
|
|
1211
|
-
'was not found neither by a visible text nor by a value',
|
|
1212
|
-
)
|
|
1178
|
+
throw new ElementNotFound(select, `Option "${option}" in`, 'was not found neither by a visible text nor by a value')
|
|
1213
1179
|
}
|
|
1214
1180
|
return forEachAsync(els, clickOptionFn)
|
|
1215
1181
|
}
|
|
@@ -1231,14 +1197,12 @@ class WebDriver extends Helper {
|
|
|
1231
1197
|
const el = usingFirstElement(res)
|
|
1232
1198
|
|
|
1233
1199
|
// Remote Upload (when running Selenium Server)
|
|
1234
|
-
if (this.options.remoteFileUpload
|
|
1200
|
+
if (this.options.remoteFileUpload) {
|
|
1235
1201
|
try {
|
|
1236
1202
|
this.debugSection('File', 'Uploading file to remote server')
|
|
1237
1203
|
file = await this.browser.uploadFile(file)
|
|
1238
1204
|
} catch (err) {
|
|
1239
|
-
throw new Error(
|
|
1240
|
-
`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`,
|
|
1241
|
-
)
|
|
1205
|
+
throw new Error(`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`)
|
|
1242
1206
|
}
|
|
1243
1207
|
}
|
|
1244
1208
|
|
|
@@ -1291,7 +1255,11 @@ class WebDriver extends Helper {
|
|
|
1291
1255
|
*/
|
|
1292
1256
|
async grabTextFromAll(locator) {
|
|
1293
1257
|
const res = await this._locate(locator, true)
|
|
1294
|
-
|
|
1258
|
+
let val = []
|
|
1259
|
+
await forEachAsync(res, async el => {
|
|
1260
|
+
const text = await this.browser.getElementText(getElementId(el))
|
|
1261
|
+
val.push(text)
|
|
1262
|
+
})
|
|
1295
1263
|
this.debugSection('GrabText', String(val))
|
|
1296
1264
|
return val
|
|
1297
1265
|
}
|
|
@@ -1316,7 +1284,7 @@ class WebDriver extends Helper {
|
|
|
1316
1284
|
*/
|
|
1317
1285
|
async grabHTMLFromAll(locator) {
|
|
1318
1286
|
const elems = await this._locate(locator, true)
|
|
1319
|
-
const html = await forEachAsync(elems,
|
|
1287
|
+
const html = await forEachAsync(elems, elem => elem.getHTML(false))
|
|
1320
1288
|
this.debugSection('GrabHTML', String(html))
|
|
1321
1289
|
return html
|
|
1322
1290
|
}
|
|
@@ -1341,7 +1309,7 @@ class WebDriver extends Helper {
|
|
|
1341
1309
|
*/
|
|
1342
1310
|
async grabValueFromAll(locator) {
|
|
1343
1311
|
const res = await this._locate(locator, true)
|
|
1344
|
-
const val = await forEachAsync(res,
|
|
1312
|
+
const val = await forEachAsync(res, el => el.getValue())
|
|
1345
1313
|
this.debugSection('GrabValue', String(val))
|
|
1346
1314
|
|
|
1347
1315
|
return val
|
|
@@ -1366,7 +1334,7 @@ class WebDriver extends Helper {
|
|
|
1366
1334
|
*/
|
|
1367
1335
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
1368
1336
|
const res = await this._locate(locator, true)
|
|
1369
|
-
const val = await forEachAsync(res, async
|
|
1337
|
+
const val = await forEachAsync(res, async el => this.browser.getElementCSSValue(getElementId(el), cssProperty))
|
|
1370
1338
|
this.debugSection('Grab', String(val))
|
|
1371
1339
|
return val
|
|
1372
1340
|
}
|
|
@@ -1390,7 +1358,7 @@ class WebDriver extends Helper {
|
|
|
1390
1358
|
*/
|
|
1391
1359
|
async grabAttributeFromAll(locator, attr) {
|
|
1392
1360
|
const res = await this._locate(locator, true)
|
|
1393
|
-
const val = await forEachAsync(res, async
|
|
1361
|
+
const val = await forEachAsync(res, async el => el.getAttribute(attr))
|
|
1394
1362
|
this.debugSection('GrabAttribute', String(val))
|
|
1395
1363
|
return val
|
|
1396
1364
|
}
|
|
@@ -1507,7 +1475,7 @@ class WebDriver extends Helper {
|
|
|
1507
1475
|
async seeElement(locator) {
|
|
1508
1476
|
const res = await this._locate(locator, true)
|
|
1509
1477
|
assertElementExists(res, locator)
|
|
1510
|
-
const selected = await forEachAsync(res, async
|
|
1478
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1511
1479
|
try {
|
|
1512
1480
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').assert(selected)
|
|
1513
1481
|
} catch (e) {
|
|
@@ -1524,7 +1492,7 @@ class WebDriver extends Helper {
|
|
|
1524
1492
|
if (!res || res.length === 0) {
|
|
1525
1493
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(false)
|
|
1526
1494
|
}
|
|
1527
|
-
const selected = await forEachAsync(res, async
|
|
1495
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1528
1496
|
try {
|
|
1529
1497
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(selected)
|
|
1530
1498
|
} catch (e) {
|
|
@@ -1579,11 +1547,7 @@ class WebDriver extends Helper {
|
|
|
1579
1547
|
* {{> grabBrowserLogs }}
|
|
1580
1548
|
*/
|
|
1581
1549
|
async grabBrowserLogs() {
|
|
1582
|
-
|
|
1583
|
-
this.debug('Logs not available in W3C specification')
|
|
1584
|
-
return
|
|
1585
|
-
}
|
|
1586
|
-
return this.browser.getLogs('browser')
|
|
1550
|
+
return browserLogs
|
|
1587
1551
|
}
|
|
1588
1552
|
|
|
1589
1553
|
/**
|
|
@@ -1609,11 +1573,7 @@ class WebDriver extends Helper {
|
|
|
1609
1573
|
*/
|
|
1610
1574
|
async seeNumberOfElements(locator, num) {
|
|
1611
1575
|
const res = await this._locate(locator)
|
|
1612
|
-
return assert.equal(
|
|
1613
|
-
res.length,
|
|
1614
|
-
num,
|
|
1615
|
-
`expected number of elements (${new Locator(locator)}) is ${num}, but found ${res.length}`,
|
|
1616
|
-
)
|
|
1576
|
+
return assert.equal(res.length, num, `expected number of elements (${new Locator(locator)}) is ${num}, but found ${res.length}`)
|
|
1617
1577
|
}
|
|
1618
1578
|
|
|
1619
1579
|
/**
|
|
@@ -1622,11 +1582,7 @@ class WebDriver extends Helper {
|
|
|
1622
1582
|
*/
|
|
1623
1583
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1624
1584
|
const res = await this.grabNumberOfVisibleElements(locator)
|
|
1625
|
-
return assert.equal(
|
|
1626
|
-
res,
|
|
1627
|
-
num,
|
|
1628
|
-
`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`,
|
|
1629
|
-
)
|
|
1585
|
+
return assert.equal(res, num, `expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`)
|
|
1630
1586
|
}
|
|
1631
1587
|
|
|
1632
1588
|
/**
|
|
@@ -1651,19 +1607,16 @@ class WebDriver extends Helper {
|
|
|
1651
1607
|
}
|
|
1652
1608
|
}
|
|
1653
1609
|
|
|
1654
|
-
const values = Object.keys(cssPropertiesCamelCase).map(
|
|
1610
|
+
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key])
|
|
1655
1611
|
if (!Array.isArray(props)) props = [props]
|
|
1656
1612
|
let chunked = chunkArray(props, values.length)
|
|
1657
|
-
chunked = chunked.filter(
|
|
1613
|
+
chunked = chunked.filter(val => {
|
|
1658
1614
|
for (let i = 0; i < val.length; ++i) {
|
|
1659
|
-
// eslint-disable-next-line eqeqeq
|
|
1660
1615
|
if (val[i] != values[i]) return false
|
|
1661
1616
|
}
|
|
1662
1617
|
return true
|
|
1663
1618
|
})
|
|
1664
|
-
return equals(
|
|
1665
|
-
`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
|
|
1666
|
-
).assert(chunked.length, elemAmount)
|
|
1619
|
+
return equals(`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount)
|
|
1667
1620
|
}
|
|
1668
1621
|
|
|
1669
1622
|
/**
|
|
@@ -1674,28 +1627,24 @@ class WebDriver extends Helper {
|
|
|
1674
1627
|
assertElementExists(res, locator)
|
|
1675
1628
|
const elemAmount = res.length
|
|
1676
1629
|
|
|
1677
|
-
let attrs = await forEachAsync(res, async
|
|
1678
|
-
return forEachAsync(Object.keys(attributes), async
|
|
1630
|
+
let attrs = await forEachAsync(res, async el => {
|
|
1631
|
+
return forEachAsync(Object.keys(attributes), async attr => el.getAttribute(attr))
|
|
1679
1632
|
})
|
|
1680
1633
|
|
|
1681
|
-
const values = Object.keys(attributes).map(
|
|
1634
|
+
const values = Object.keys(attributes).map(key => attributes[key])
|
|
1682
1635
|
if (!Array.isArray(attrs)) attrs = [attrs]
|
|
1683
1636
|
let chunked = chunkArray(attrs, values.length)
|
|
1684
|
-
chunked = chunked.filter(
|
|
1637
|
+
chunked = chunked.filter(val => {
|
|
1685
1638
|
for (let i = 0; i < val.length; ++i) {
|
|
1686
1639
|
const _actual = Number.isNaN(val[i]) || typeof values[i] === 'string' ? val[i] : Number.parseInt(val[i], 10)
|
|
1687
|
-
const _expected =
|
|
1688
|
-
Number.isNaN(values[i]) || typeof values[i] === 'string' ? values[i] : Number.parseInt(values[i], 10)
|
|
1640
|
+
const _expected = Number.isNaN(values[i]) || typeof values[i] === 'string' ? values[i] : Number.parseInt(values[i], 10)
|
|
1689
1641
|
// the attribute could be a boolean
|
|
1690
1642
|
if (typeof _actual === 'boolean') return _actual === _expected
|
|
1691
1643
|
if (_actual !== _expected) return false
|
|
1692
1644
|
}
|
|
1693
1645
|
return true
|
|
1694
1646
|
})
|
|
1695
|
-
return assert.ok(
|
|
1696
|
-
chunked.length === elemAmount,
|
|
1697
|
-
`expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`,
|
|
1698
|
-
)
|
|
1647
|
+
return assert.ok(chunked.length === elemAmount, `expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`)
|
|
1699
1648
|
}
|
|
1700
1649
|
|
|
1701
1650
|
/**
|
|
@@ -1704,9 +1653,9 @@ class WebDriver extends Helper {
|
|
|
1704
1653
|
async grabNumberOfVisibleElements(locator) {
|
|
1705
1654
|
const res = await this._locate(locator)
|
|
1706
1655
|
|
|
1707
|
-
let selected = await forEachAsync(res, async
|
|
1656
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1708
1657
|
if (!Array.isArray(selected)) selected = [selected]
|
|
1709
|
-
selected = selected.filter(
|
|
1658
|
+
selected = selected.filter(val => val === true)
|
|
1710
1659
|
return selected.length
|
|
1711
1660
|
}
|
|
1712
1661
|
|
|
@@ -1793,7 +1742,7 @@ class WebDriver extends Helper {
|
|
|
1793
1742
|
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(offsetX, offsetY, elementId)
|
|
1794
1743
|
const location = await elem.getLocation()
|
|
1795
1744
|
assertElementExists(location, locator, 'Failed to receive', 'location')
|
|
1796
|
-
|
|
1745
|
+
|
|
1797
1746
|
return this.browser.execute(
|
|
1798
1747
|
function (x, y) {
|
|
1799
1748
|
return window.scrollTo(x, y)
|
|
@@ -1801,12 +1750,10 @@ class WebDriver extends Helper {
|
|
|
1801
1750
|
location.x + offsetX,
|
|
1802
1751
|
location.y + offsetY,
|
|
1803
1752
|
)
|
|
1804
|
-
/* eslint-enable */
|
|
1805
1753
|
}
|
|
1806
1754
|
|
|
1807
1755
|
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(locator, offsetX, offsetY)
|
|
1808
1756
|
|
|
1809
|
-
/* eslint-disable prefer-arrow-callback, comma-dangle */
|
|
1810
1757
|
return this.browser.execute(
|
|
1811
1758
|
function (x, y) {
|
|
1812
1759
|
return window.scrollTo(x, y)
|
|
@@ -1814,7 +1761,6 @@ class WebDriver extends Helper {
|
|
|
1814
1761
|
offsetX,
|
|
1815
1762
|
offsetY,
|
|
1816
1763
|
)
|
|
1817
|
-
/* eslint-enable */
|
|
1818
1764
|
}
|
|
1819
1765
|
|
|
1820
1766
|
/**
|
|
@@ -1863,19 +1809,25 @@ class WebDriver extends Helper {
|
|
|
1863
1809
|
|
|
1864
1810
|
if (browser) {
|
|
1865
1811
|
this.debug(`Screenshot of ${sessionName} session has been saved to ${outputFile}`)
|
|
1866
|
-
|
|
1812
|
+
await browser.saveScreenshot(outputFile)
|
|
1867
1813
|
}
|
|
1868
1814
|
}
|
|
1869
1815
|
}
|
|
1870
1816
|
|
|
1871
1817
|
if (!fullPage) {
|
|
1872
1818
|
this.debug(`Screenshot has been saved to ${outputFile}`)
|
|
1873
|
-
|
|
1819
|
+
await this.browser.saveScreenshot(outputFile)
|
|
1874
1820
|
}
|
|
1875
1821
|
|
|
1876
|
-
/* eslint-disable prefer-arrow-callback, comma-dangle, prefer-const */
|
|
1877
1822
|
const originalWindowSize = await this.browser.getWindowSize()
|
|
1878
1823
|
|
|
1824
|
+
// this case running on device, so we could not set the windowSize
|
|
1825
|
+
if (this.browser.isMobile) {
|
|
1826
|
+
this.debug(`Screenshot has been saved to ${outputFile}, size: ${originalWindowSize.width}x${originalWindowSize.height}`)
|
|
1827
|
+
const buffer = await this.browser.saveScreenshot(outputFile)
|
|
1828
|
+
return buffer
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1879
1831
|
let { width, height } = await this.browser
|
|
1880
1832
|
.execute(function () {
|
|
1881
1833
|
return {
|
|
@@ -1883,10 +1835,9 @@ class WebDriver extends Helper {
|
|
|
1883
1835
|
width: document.body.scrollWidth,
|
|
1884
1836
|
}
|
|
1885
1837
|
})
|
|
1886
|
-
.then(
|
|
1838
|
+
.then(res => res)
|
|
1887
1839
|
|
|
1888
1840
|
if (height < 100) height = 500 // errors for very small height
|
|
1889
|
-
/* eslint-enable */
|
|
1890
1841
|
|
|
1891
1842
|
await this.browser.setWindowSize(width, height)
|
|
1892
1843
|
this.debug(`Screenshot has been saved to ${outputFile}, size: ${width}x${height}`)
|
|
@@ -1952,7 +1903,7 @@ class WebDriver extends Helper {
|
|
|
1952
1903
|
|
|
1953
1904
|
return promiseRetry(
|
|
1954
1905
|
async (retry, number) => {
|
|
1955
|
-
const _grabCookie = async
|
|
1906
|
+
const _grabCookie = async name => {
|
|
1956
1907
|
const cookie = await this.browser.getCookies([name])
|
|
1957
1908
|
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
|
|
1958
1909
|
}
|
|
@@ -1976,11 +1927,10 @@ class WebDriver extends Helper {
|
|
|
1976
1927
|
* libraries](http://jster.net/category/windows-modals-popups).
|
|
1977
1928
|
*/
|
|
1978
1929
|
async acceptPopup() {
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
})
|
|
1930
|
+
const text = await this.browser.getAlertText()
|
|
1931
|
+
if (text) {
|
|
1932
|
+
return await this.browser.acceptAlert()
|
|
1933
|
+
}
|
|
1984
1934
|
}
|
|
1985
1935
|
|
|
1986
1936
|
/**
|
|
@@ -1988,11 +1938,10 @@ class WebDriver extends Helper {
|
|
|
1988
1938
|
*
|
|
1989
1939
|
*/
|
|
1990
1940
|
async cancelPopup() {
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
})
|
|
1941
|
+
const text = await this.browser.getAlertText()
|
|
1942
|
+
if (text) {
|
|
1943
|
+
return await this.browser.dismissAlert()
|
|
1944
|
+
}
|
|
1996
1945
|
}
|
|
1997
1946
|
|
|
1998
1947
|
/**
|
|
@@ -2002,7 +1951,7 @@ class WebDriver extends Helper {
|
|
|
2002
1951
|
* @param {string} text value to check.
|
|
2003
1952
|
*/
|
|
2004
1953
|
async seeInPopup(text) {
|
|
2005
|
-
return this.browser.getAlertText().then(
|
|
1954
|
+
return await this.browser.getAlertText().then(res => {
|
|
2006
1955
|
if (res === null) {
|
|
2007
1956
|
throw new Error('Popup is not opened')
|
|
2008
1957
|
}
|
|
@@ -2283,9 +2232,9 @@ class WebDriver extends Helper {
|
|
|
2283
2232
|
async closeOtherTabs() {
|
|
2284
2233
|
const handles = await this.browser.getWindowHandles()
|
|
2285
2234
|
const currentHandle = await this.browser.getWindowHandle()
|
|
2286
|
-
const otherHandles = handles.filter(
|
|
2235
|
+
const otherHandles = handles.filter(handle => handle !== currentHandle)
|
|
2287
2236
|
|
|
2288
|
-
await forEachAsync(otherHandles, async
|
|
2237
|
+
await forEachAsync(otherHandles, async handle => {
|
|
2289
2238
|
await this.browser.switchToWindow(handle)
|
|
2290
2239
|
await this.browser.closeWindow()
|
|
2291
2240
|
})
|
|
@@ -2296,7 +2245,7 @@ class WebDriver extends Helper {
|
|
|
2296
2245
|
* {{> wait }}
|
|
2297
2246
|
*/
|
|
2298
2247
|
async wait(sec) {
|
|
2299
|
-
return new Promise(
|
|
2248
|
+
return new Promise(resolve => {
|
|
2300
2249
|
setTimeout(resolve, sec * 1000)
|
|
2301
2250
|
})
|
|
2302
2251
|
}
|
|
@@ -2313,9 +2262,9 @@ class WebDriver extends Helper {
|
|
|
2313
2262
|
if (!res || res.length === 0) {
|
|
2314
2263
|
return false
|
|
2315
2264
|
}
|
|
2316
|
-
const selected = await forEachAsync(res, async
|
|
2265
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementEnabled(getElementId(el)))
|
|
2317
2266
|
if (Array.isArray(selected)) {
|
|
2318
|
-
return selected.filter(
|
|
2267
|
+
return selected.filter(val => val === true).length > 0
|
|
2319
2268
|
}
|
|
2320
2269
|
return selected
|
|
2321
2270
|
},
|
|
@@ -2370,14 +2319,14 @@ class WebDriver extends Helper {
|
|
|
2370
2319
|
return client
|
|
2371
2320
|
.waitUntil(
|
|
2372
2321
|
function () {
|
|
2373
|
-
return this.getUrl().then(
|
|
2322
|
+
return this.getUrl().then(res => {
|
|
2374
2323
|
currUrl = decodeUrl(res)
|
|
2375
2324
|
return currUrl.indexOf(urlPart) > -1
|
|
2376
2325
|
})
|
|
2377
2326
|
},
|
|
2378
2327
|
{ timeout: aSec * 1000 },
|
|
2379
2328
|
)
|
|
2380
|
-
.catch(
|
|
2329
|
+
.catch(e => {
|
|
2381
2330
|
if (e.message.indexOf('timeout')) {
|
|
2382
2331
|
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
|
|
2383
2332
|
}
|
|
@@ -2397,12 +2346,12 @@ class WebDriver extends Helper {
|
|
|
2397
2346
|
let currUrl = ''
|
|
2398
2347
|
return this.browser
|
|
2399
2348
|
.waitUntil(function () {
|
|
2400
|
-
return this.getUrl().then(
|
|
2349
|
+
return this.getUrl().then(res => {
|
|
2401
2350
|
currUrl = decodeUrl(res)
|
|
2402
2351
|
return currUrl === urlPart
|
|
2403
2352
|
})
|
|
2404
2353
|
}, aSec * 1000)
|
|
2405
|
-
.catch(
|
|
2354
|
+
.catch(e => {
|
|
2406
2355
|
if (e.message.indexOf('timeout')) {
|
|
2407
2356
|
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
|
|
2408
2357
|
}
|
|
@@ -2422,9 +2371,9 @@ class WebDriver extends Helper {
|
|
|
2422
2371
|
async () => {
|
|
2423
2372
|
const res = await this.$$(withStrictLocator.call(this, _context))
|
|
2424
2373
|
if (!res || res.length === 0) return false
|
|
2425
|
-
const selected = await forEachAsync(res, async
|
|
2374
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)))
|
|
2426
2375
|
if (Array.isArray(selected)) {
|
|
2427
|
-
return selected.filter(
|
|
2376
|
+
return selected.filter(part => part.indexOf(text) >= 0).length > 0
|
|
2428
2377
|
}
|
|
2429
2378
|
return selected.indexOf(text) >= 0
|
|
2430
2379
|
},
|
|
@@ -2446,9 +2395,9 @@ class WebDriver extends Helper {
|
|
|
2446
2395
|
async () => {
|
|
2447
2396
|
const res = await findFields.call(this, field)
|
|
2448
2397
|
if (!res || res.length === 0) return false
|
|
2449
|
-
const selected = await forEachAsync(res, async
|
|
2398
|
+
const selected = await forEachAsync(res, async el => el.getValue())
|
|
2450
2399
|
if (Array.isArray(selected)) {
|
|
2451
|
-
return selected.filter(
|
|
2400
|
+
return selected.filter(part => part.indexOf(value) >= 0).length > 0
|
|
2452
2401
|
}
|
|
2453
2402
|
return selected.indexOf(value) >= 0
|
|
2454
2403
|
},
|
|
@@ -2470,9 +2419,9 @@ class WebDriver extends Helper {
|
|
|
2470
2419
|
async () => {
|
|
2471
2420
|
const res = await this._res(locator)
|
|
2472
2421
|
if (!res || res.length === 0) return false
|
|
2473
|
-
const selected = await forEachAsync(res, async
|
|
2422
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2474
2423
|
if (Array.isArray(selected)) {
|
|
2475
|
-
return selected.filter(
|
|
2424
|
+
return selected.filter(val => val === true).length > 0
|
|
2476
2425
|
}
|
|
2477
2426
|
return selected
|
|
2478
2427
|
},
|
|
@@ -2493,10 +2442,10 @@ class WebDriver extends Helper {
|
|
|
2493
2442
|
async () => {
|
|
2494
2443
|
const res = await this._res(locator)
|
|
2495
2444
|
if (!res || res.length === 0) return false
|
|
2496
|
-
let selected = await forEachAsync(res, async
|
|
2445
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2497
2446
|
|
|
2498
2447
|
if (!Array.isArray(selected)) selected = [selected]
|
|
2499
|
-
selected = selected.filter(
|
|
2448
|
+
selected = selected.filter(val => val === true)
|
|
2500
2449
|
return selected.length === num
|
|
2501
2450
|
},
|
|
2502
2451
|
{
|
|
@@ -2516,7 +2465,7 @@ class WebDriver extends Helper {
|
|
|
2516
2465
|
async () => {
|
|
2517
2466
|
const res = await this._res(locator)
|
|
2518
2467
|
if (!res || res.length === 0) return true
|
|
2519
|
-
const selected = await forEachAsync(res, async
|
|
2468
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2520
2469
|
return !selected.length
|
|
2521
2470
|
},
|
|
2522
2471
|
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still visible after ${aSec} sec` },
|
|
@@ -2592,20 +2541,14 @@ class WebDriver extends Helper {
|
|
|
2592
2541
|
*/
|
|
2593
2542
|
async switchTo(locator) {
|
|
2594
2543
|
this.browser.isInsideFrame = true
|
|
2595
|
-
if (Number.isInteger(locator)) {
|
|
2596
|
-
if (this.options.automationProtocol) {
|
|
2597
|
-
return this.browser.switchToFrame(locator + 1)
|
|
2598
|
-
}
|
|
2599
|
-
return this.browser.switchToFrame(locator)
|
|
2600
|
-
}
|
|
2601
2544
|
if (!locator) {
|
|
2602
|
-
return this.browser.
|
|
2545
|
+
return this.browser.switchFrame(null)
|
|
2603
2546
|
}
|
|
2604
2547
|
|
|
2605
2548
|
let res = await this._locate(locator, true)
|
|
2606
2549
|
assertElementExists(res, locator)
|
|
2607
2550
|
res = usingFirstElement(res)
|
|
2608
|
-
return this.browser.
|
|
2551
|
+
return this.browser.switchFrame(res)
|
|
2609
2552
|
}
|
|
2610
2553
|
|
|
2611
2554
|
/**
|
|
@@ -2618,7 +2561,7 @@ class WebDriver extends Helper {
|
|
|
2618
2561
|
|
|
2619
2562
|
await this.browser.waitUntil(
|
|
2620
2563
|
async () => {
|
|
2621
|
-
await this.browser.getWindowHandles().then(
|
|
2564
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2622
2565
|
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
2623
2566
|
target = handles[handles.indexOf(current) + num]
|
|
2624
2567
|
}
|
|
@@ -2640,7 +2583,7 @@ class WebDriver extends Helper {
|
|
|
2640
2583
|
|
|
2641
2584
|
await this.browser.waitUntil(
|
|
2642
2585
|
async () => {
|
|
2643
|
-
await this.browser.getWindowHandles().then(
|
|
2586
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2644
2587
|
if (handles.indexOf(current) - num > -1) {
|
|
2645
2588
|
target = handles[handles.indexOf(current) - num]
|
|
2646
2589
|
}
|
|
@@ -2695,11 +2638,10 @@ class WebDriver extends Helper {
|
|
|
2695
2638
|
*/
|
|
2696
2639
|
scrollPageToTop() {
|
|
2697
2640
|
const client = this.browser
|
|
2698
|
-
|
|
2641
|
+
|
|
2699
2642
|
return client.execute(function () {
|
|
2700
2643
|
window.scrollTo(0, 0)
|
|
2701
2644
|
})
|
|
2702
|
-
/* eslint-enable */
|
|
2703
2645
|
}
|
|
2704
2646
|
|
|
2705
2647
|
/**
|
|
@@ -2707,69 +2649,26 @@ class WebDriver extends Helper {
|
|
|
2707
2649
|
*/
|
|
2708
2650
|
scrollPageToBottom() {
|
|
2709
2651
|
const client = this.browser
|
|
2710
|
-
|
|
2652
|
+
|
|
2711
2653
|
return client.execute(function () {
|
|
2712
2654
|
const body = document.body
|
|
2713
2655
|
const html = document.documentElement
|
|
2714
|
-
window.scrollTo(
|
|
2715
|
-
0,
|
|
2716
|
-
Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
|
|
2717
|
-
)
|
|
2656
|
+
window.scrollTo(0, Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight))
|
|
2718
2657
|
})
|
|
2719
|
-
/* eslint-enable */
|
|
2720
2658
|
}
|
|
2721
2659
|
|
|
2722
2660
|
/**
|
|
2723
2661
|
* {{> grabPageScrollPosition }}
|
|
2724
2662
|
*/
|
|
2725
2663
|
async grabPageScrollPosition() {
|
|
2726
|
-
/* eslint-disable comma-dangle */
|
|
2727
2664
|
function getScrollPosition() {
|
|
2728
2665
|
return {
|
|
2729
2666
|
x: window.pageXOffset,
|
|
2730
2667
|
y: window.pageYOffset,
|
|
2731
2668
|
}
|
|
2732
2669
|
}
|
|
2733
|
-
/* eslint-enable comma-dangle */
|
|
2734
|
-
return this.executeScript(getScrollPosition)
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
/**
|
|
2738
|
-
* This method is **deprecated**.
|
|
2739
|
-
*
|
|
2740
|
-
*
|
|
2741
|
-
* {{> setGeoLocation }}
|
|
2742
|
-
*/
|
|
2743
|
-
async setGeoLocation(latitude, longitude) {
|
|
2744
|
-
if (!this.options.automationProtocol) {
|
|
2745
|
-
console.log(`setGeoLocation deprecated:
|
|
2746
|
-
* This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#setgeolocation
|
|
2747
|
-
* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`)
|
|
2748
|
-
return
|
|
2749
|
-
}
|
|
2750
|
-
this.geoLocation = { latitude, longitude }
|
|
2751
|
-
|
|
2752
|
-
await this.browser.call(async () => {
|
|
2753
|
-
const pages = await this.puppeteerBrowser.pages()
|
|
2754
|
-
await pages[0].setGeolocation({ latitude, longitude })
|
|
2755
|
-
})
|
|
2756
|
-
}
|
|
2757
2670
|
|
|
2758
|
-
|
|
2759
|
-
* This method is **deprecated**.
|
|
2760
|
-
*
|
|
2761
|
-
* {{> grabGeoLocation }}
|
|
2762
|
-
*
|
|
2763
|
-
*/
|
|
2764
|
-
async grabGeoLocation() {
|
|
2765
|
-
if (!this.options.automationProtocol) {
|
|
2766
|
-
console.log(`grabGeoLocation deprecated:
|
|
2767
|
-
* This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#getgeolocation
|
|
2768
|
-
* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`)
|
|
2769
|
-
return
|
|
2770
|
-
}
|
|
2771
|
-
if (!this.geoLocation) return 'No GeoLocation is set!'
|
|
2772
|
-
return this.geoLocation
|
|
2671
|
+
return this.executeScript(getScrollPosition)
|
|
2773
2672
|
}
|
|
2774
2673
|
|
|
2775
2674
|
/**
|
|
@@ -2793,7 +2692,7 @@ class WebDriver extends Helper {
|
|
|
2793
2692
|
* @param {*} caps
|
|
2794
2693
|
* @param {*} fn
|
|
2795
2694
|
*/
|
|
2796
|
-
|
|
2695
|
+
|
|
2797
2696
|
runOnIOS(caps, fn) {}
|
|
2798
2697
|
|
|
2799
2698
|
/**
|
|
@@ -2802,135 +2701,13 @@ class WebDriver extends Helper {
|
|
|
2802
2701
|
* @param {*} fn
|
|
2803
2702
|
*/
|
|
2804
2703
|
runOnAndroid(caps, fn) {}
|
|
2805
|
-
/* eslint-enable */
|
|
2806
2704
|
|
|
2807
2705
|
/**
|
|
2808
2706
|
* Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
|
|
2809
2707
|
*/
|
|
2810
|
-
runInWeb(fn) {
|
|
2708
|
+
async runInWeb(fn) {
|
|
2811
2709
|
return fn()
|
|
2812
2710
|
}
|
|
2813
|
-
|
|
2814
|
-
/**
|
|
2815
|
-
*
|
|
2816
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2817
|
-
*
|
|
2818
|
-
* {{> flushNetworkTraffics }}
|
|
2819
|
-
*/
|
|
2820
|
-
flushNetworkTraffics() {
|
|
2821
|
-
if (!this.options.automationProtocol) {
|
|
2822
|
-
console.log(
|
|
2823
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2824
|
-
)
|
|
2825
|
-
return
|
|
2826
|
-
}
|
|
2827
|
-
this.requests = []
|
|
2828
|
-
}
|
|
2829
|
-
|
|
2830
|
-
/**
|
|
2831
|
-
*
|
|
2832
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2833
|
-
*
|
|
2834
|
-
* {{> stopRecordingTraffic }}
|
|
2835
|
-
*/
|
|
2836
|
-
stopRecordingTraffic() {
|
|
2837
|
-
if (!this.options.automationProtocol) {
|
|
2838
|
-
console.log(
|
|
2839
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2840
|
-
)
|
|
2841
|
-
return
|
|
2842
|
-
}
|
|
2843
|
-
this.page.removeAllListeners('request')
|
|
2844
|
-
this.recording = false
|
|
2845
|
-
}
|
|
2846
|
-
|
|
2847
|
-
/**
|
|
2848
|
-
*
|
|
2849
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2850
|
-
*
|
|
2851
|
-
* {{> startRecordingTraffic }}
|
|
2852
|
-
*
|
|
2853
|
-
*/
|
|
2854
|
-
async startRecordingTraffic() {
|
|
2855
|
-
if (!this.options.automationProtocol) {
|
|
2856
|
-
console.log(
|
|
2857
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2858
|
-
)
|
|
2859
|
-
return
|
|
2860
|
-
}
|
|
2861
|
-
this.flushNetworkTraffics()
|
|
2862
|
-
this.recording = true
|
|
2863
|
-
this.recordedAtLeastOnce = true
|
|
2864
|
-
|
|
2865
|
-
await this.page.setRequestInterception(true)
|
|
2866
|
-
|
|
2867
|
-
this.page.on('request', (request) => {
|
|
2868
|
-
const information = {
|
|
2869
|
-
url: request.url(),
|
|
2870
|
-
method: request.method(),
|
|
2871
|
-
requestHeaders: request.headers(),
|
|
2872
|
-
requestPostData: request.postData(),
|
|
2873
|
-
response: request.response(),
|
|
2874
|
-
}
|
|
2875
|
-
|
|
2876
|
-
this.debugSection('REQUEST: ', JSON.stringify(information))
|
|
2877
|
-
|
|
2878
|
-
if (typeof information.requestPostData === 'object') {
|
|
2879
|
-
information.requestPostData = JSON.parse(information.requestPostData)
|
|
2880
|
-
}
|
|
2881
|
-
request.continue()
|
|
2882
|
-
this.requests.push(information)
|
|
2883
|
-
})
|
|
2884
|
-
}
|
|
2885
|
-
|
|
2886
|
-
/**
|
|
2887
|
-
*
|
|
2888
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2889
|
-
*
|
|
2890
|
-
* {{> grabRecordedNetworkTraffics }}
|
|
2891
|
-
*/
|
|
2892
|
-
async grabRecordedNetworkTraffics() {
|
|
2893
|
-
if (!this.options.automationProtocol) {
|
|
2894
|
-
console.log(
|
|
2895
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2896
|
-
)
|
|
2897
|
-
return
|
|
2898
|
-
}
|
|
2899
|
-
return grabRecordedNetworkTraffics.call(this)
|
|
2900
|
-
}
|
|
2901
|
-
|
|
2902
|
-
/**
|
|
2903
|
-
*
|
|
2904
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2905
|
-
*
|
|
2906
|
-
* {{> seeTraffic }}
|
|
2907
|
-
*/
|
|
2908
|
-
async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) {
|
|
2909
|
-
if (!this.options.automationProtocol) {
|
|
2910
|
-
console.log(
|
|
2911
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2912
|
-
)
|
|
2913
|
-
return
|
|
2914
|
-
}
|
|
2915
|
-
await seeTraffic.call(this, ...arguments)
|
|
2916
|
-
}
|
|
2917
|
-
|
|
2918
|
-
/**
|
|
2919
|
-
*
|
|
2920
|
-
* _Note:_ Only works when devtoolsProtocol is enabled.
|
|
2921
|
-
*
|
|
2922
|
-
* {{> dontSeeTraffic }}
|
|
2923
|
-
*
|
|
2924
|
-
*/
|
|
2925
|
-
dontSeeTraffic({ name, url }) {
|
|
2926
|
-
if (!this.options.automationProtocol) {
|
|
2927
|
-
console.log(
|
|
2928
|
-
'* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration',
|
|
2929
|
-
)
|
|
2930
|
-
return
|
|
2931
|
-
}
|
|
2932
|
-
dontSeeTraffic.call(this, ...arguments)
|
|
2933
|
-
}
|
|
2934
2711
|
}
|
|
2935
2712
|
|
|
2936
2713
|
async function proceedSee(assertType, text, context, strict = false) {
|
|
@@ -2950,10 +2727,17 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
2950
2727
|
const smartWaitEnabled = assertType === 'assert'
|
|
2951
2728
|
const res = await this._locate(withStrictLocator(context), smartWaitEnabled)
|
|
2952
2729
|
assertElementExists(res, context)
|
|
2953
|
-
|
|
2730
|
+
let selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)))
|
|
2731
|
+
|
|
2732
|
+
// apply ignoreCase option
|
|
2733
|
+
if (store?.currentStep?.opts?.ignoreCase === true) {
|
|
2734
|
+
text = text.toLowerCase()
|
|
2735
|
+
selected = selected.map(elText => elText.toLowerCase())
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2954
2738
|
if (strict) {
|
|
2955
2739
|
if (Array.isArray(selected) && selected.length !== 0) {
|
|
2956
|
-
return selected.map(
|
|
2740
|
+
return selected.map(elText => equals(description)[assertType](text, elText))
|
|
2957
2741
|
}
|
|
2958
2742
|
return equals(description)[assertType](text, selected)
|
|
2959
2743
|
}
|
|
@@ -2981,7 +2765,7 @@ async function forEachAsync(array, callback, options = { expandArrayResults: tru
|
|
|
2981
2765
|
const res = await callback(inputArray[index], index, inputArray)
|
|
2982
2766
|
|
|
2983
2767
|
if (Array.isArray(res) && expandArrayResults) {
|
|
2984
|
-
res.forEach(
|
|
2768
|
+
res.forEach(val => values.push(val))
|
|
2985
2769
|
} else if (res) {
|
|
2986
2770
|
values.push(res)
|
|
2987
2771
|
}
|
|
@@ -3067,11 +2851,11 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
3067
2851
|
const elem = usingFirstElement(res)
|
|
3068
2852
|
const elemId = getElementId(elem)
|
|
3069
2853
|
|
|
3070
|
-
const proceedMultiple = async
|
|
2854
|
+
const proceedMultiple = async fields => {
|
|
3071
2855
|
const fieldResults = toArray(
|
|
3072
|
-
await forEachAsync(fields, async
|
|
2856
|
+
await forEachAsync(fields, async el => {
|
|
3073
2857
|
const elementId = getElementId(el)
|
|
3074
|
-
return this.browser.
|
|
2858
|
+
return this.browser.getElementAttribute(elementId, 'value')
|
|
3075
2859
|
}),
|
|
3076
2860
|
)
|
|
3077
2861
|
|
|
@@ -3080,27 +2864,24 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
3080
2864
|
} else {
|
|
3081
2865
|
// Assert that results were found so the forEach assert does not silently pass
|
|
3082
2866
|
equals(`no. of items matching > 0: ${field}`)[assertType](true, !!fieldResults.length)
|
|
3083
|
-
fieldResults.forEach(
|
|
2867
|
+
fieldResults.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val))
|
|
3084
2868
|
}
|
|
3085
2869
|
}
|
|
3086
2870
|
|
|
3087
|
-
const proceedSingle =
|
|
3088
|
-
el.getValue().then(
|
|
2871
|
+
const proceedSingle = el =>
|
|
2872
|
+
el.getValue().then(res => {
|
|
3089
2873
|
if (res === null) {
|
|
3090
2874
|
throw new Error(`Element ${el.selector} has no value attribute`)
|
|
3091
2875
|
}
|
|
3092
2876
|
stringIncludes(`fields by ${field}`)[assertType](value, res)
|
|
3093
2877
|
})
|
|
3094
2878
|
|
|
3095
|
-
const filterBySelected = async (elements
|
|
3096
|
-
filterAsync(elements, async (el) => this.browser.isElementSelected(getElementId(el)))
|
|
2879
|
+
const filterBySelected = async elements => filterAsync(elements, async el => this.browser.isElementSelected(getElementId(el)))
|
|
3097
2880
|
|
|
3098
2881
|
const filterSelectedByValue = async (elements, value) => {
|
|
3099
|
-
return filterAsync(elements, async
|
|
2882
|
+
return filterAsync(elements, async el => {
|
|
3100
2883
|
const elementId = getElementId(el)
|
|
3101
|
-
const currentValue = this.browser.
|
|
3102
|
-
? await el.getValue()
|
|
3103
|
-
: await this.browser.getElementAttribute(elementId, 'value')
|
|
2884
|
+
const currentValue = await this.browser.getElementAttribute(elementId, 'value')
|
|
3104
2885
|
const isSelected = await this.browser.isElementSelected(elementId)
|
|
3105
2886
|
return currentValue === value && isSelected
|
|
3106
2887
|
})
|
|
@@ -3108,7 +2889,13 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
3108
2889
|
|
|
3109
2890
|
const tag = await elem.getTagName()
|
|
3110
2891
|
if (tag === 'select') {
|
|
3111
|
-
|
|
2892
|
+
let subOptions
|
|
2893
|
+
|
|
2894
|
+
try {
|
|
2895
|
+
subOptions = await this.browser.findElementsFromElement(elemId, 'css', 'option')
|
|
2896
|
+
} catch (e) {
|
|
2897
|
+
subOptions = await this.browser.findElementsFromElement(elemId, 'xpath', 'option')
|
|
2898
|
+
}
|
|
3112
2899
|
|
|
3113
2900
|
if (value === '') {
|
|
3114
2901
|
// Don't filter by value
|
|
@@ -3149,7 +2936,7 @@ async function proceedSeeCheckbox(assertType, field) {
|
|
|
3149
2936
|
const res = await findFields.call(this, field)
|
|
3150
2937
|
assertElementExists(res, field, 'Field')
|
|
3151
2938
|
|
|
3152
|
-
const selected = await forEachAsync(res, async
|
|
2939
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementSelected(getElementId(el)))
|
|
3153
2940
|
return truth(`checkable field "${field}"`, 'to be checked')[assertType](selected)
|
|
3154
2941
|
}
|
|
3155
2942
|
|
|
@@ -3213,7 +3000,6 @@ function getElementId(el) {
|
|
|
3213
3000
|
// List of known key values to unicode code points
|
|
3214
3001
|
// https://www.w3.org/TR/webdriver/#keyboard-actions
|
|
3215
3002
|
const keyUnicodeMap = {
|
|
3216
|
-
/* eslint-disable quote-props */
|
|
3217
3003
|
Unidentified: '\uE000',
|
|
3218
3004
|
Cancel: '\uE001',
|
|
3219
3005
|
Clear: '\uE005',
|
|
@@ -3328,7 +3114,6 @@ const keyUnicodeMap = {
|
|
|
3328
3114
|
Semicolon: '\uE018', // ';' alias
|
|
3329
3115
|
Slash: '/', // '/' alias
|
|
3330
3116
|
ZenkakuHankaku: '\uE040',
|
|
3331
|
-
/* eslint-enable quote-props */
|
|
3332
3117
|
}
|
|
3333
3118
|
|
|
3334
3119
|
function convertKeyToRawKey(key) {
|
|
@@ -3352,7 +3137,7 @@ function getNormalizedKey(key) {
|
|
|
3352
3137
|
return convertKeyToRawKey(normalizedKey)
|
|
3353
3138
|
}
|
|
3354
3139
|
|
|
3355
|
-
const unicodeModifierKeys = modifierKeys.map(
|
|
3140
|
+
const unicodeModifierKeys = modifierKeys.map(k => convertKeyToRawKey(k))
|
|
3356
3141
|
function isModifierKey(key) {
|
|
3357
3142
|
return unicodeModifierKeys.includes(key)
|
|
3358
3143
|
}
|
|
@@ -3365,9 +3150,9 @@ function highlightActiveElement(element) {
|
|
|
3365
3150
|
|
|
3366
3151
|
function prepareLocateFn(context) {
|
|
3367
3152
|
if (!context) return this._locate.bind(this)
|
|
3368
|
-
return
|
|
3153
|
+
return l => {
|
|
3369
3154
|
l = new Locator(l, 'css')
|
|
3370
|
-
return this._locate(context, true).then(async
|
|
3155
|
+
return this._locate(context, true).then(async res => {
|
|
3371
3156
|
assertElementExists(res, context, 'Context element')
|
|
3372
3157
|
if (l.react) {
|
|
3373
3158
|
return res[0].react$$(l.react, l.props || undefined)
|
|
@@ -3377,4 +3162,8 @@ function prepareLocateFn(context) {
|
|
|
3377
3162
|
}
|
|
3378
3163
|
}
|
|
3379
3164
|
|
|
3165
|
+
function logEvents(event) {
|
|
3166
|
+
browserLogs.push(event.text) // add log message to the array
|
|
3167
|
+
}
|
|
3168
|
+
|
|
3380
3169
|
module.exports = WebDriver
|