codeceptjs 4.0.0-beta.4 → 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 +139 -87
- package/lib/command/check.js +201 -0
- package/lib/command/configMigrate.js +2 -4
- package/lib/command/definitions.js +8 -26
- 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 +262 -220
- 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 +3 -6
- package/lib/helper/Appium.js +47 -51
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +75 -37
- package/lib/helper/Mochawesome.js +31 -9
- package/lib/helper/Nightmare.js +35 -53
- package/lib/helper/Playwright.js +262 -267
- package/lib/helper/Protractor.js +54 -77
- package/lib/helper/Puppeteer.js +246 -260
- package/lib/helper/REST.js +5 -17
- package/lib/helper/TestCafe.js +21 -44
- package/lib/helper/WebDriver.js +151 -170
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/testcafe/testcafe-utils.js +26 -27
- 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/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 +82 -62
- 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 -19
- 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 -1
- 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 -276
- package/package.json +76 -70
- package/translations/de-DE.js +4 -3
- package/translations/fr-FR.js +4 -3
- 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 +188 -186
- package/typings/promiseBasedTypes.d.ts +18 -705
- package/typings/types.d.ts +301 -804
- package/lib/cli.js +0 -256
- package/lib/helper/ExpectHelper.js +0 -391
- 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.
|
|
@@ -506,6 +490,10 @@ class WebDriver extends Helper {
|
|
|
506
490
|
config.capabilities = config.desiredCapabilities
|
|
507
491
|
}
|
|
508
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
|
+
|
|
509
497
|
config.capabilities.browserVersion = config.browserVersion || config.capabilities.browserVersion
|
|
510
498
|
if (config.capabilities.chromeOptions) {
|
|
511
499
|
config.capabilities['goog:chromeOptions'] = config.capabilities.chromeOptions
|
|
@@ -595,10 +583,7 @@ class WebDriver extends Helper {
|
|
|
595
583
|
}
|
|
596
584
|
|
|
597
585
|
async _res(locator) {
|
|
598
|
-
const res =
|
|
599
|
-
this._isShadowLocator(locator) || this._isCustomLocator(locator)
|
|
600
|
-
? await this._locate(locator)
|
|
601
|
-
: await this.$$(withStrictLocator(locator))
|
|
586
|
+
const res = this._isShadowLocator(locator) || this._isCustomLocator(locator) ? await this._locate(locator) : await this.$$(withStrictLocator(locator))
|
|
602
587
|
return res
|
|
603
588
|
}
|
|
604
589
|
|
|
@@ -631,7 +616,7 @@ class WebDriver extends Helper {
|
|
|
631
616
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
632
617
|
|
|
633
618
|
if (this._isCustomLocatorStrategyDefined()) {
|
|
634
|
-
Object.keys(this.customLocatorStrategies).forEach(async
|
|
619
|
+
Object.keys(this.customLocatorStrategies).forEach(async customLocator => {
|
|
635
620
|
this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`)
|
|
636
621
|
const locatorFunction = this._lookupCustomLocator(customLocator)
|
|
637
622
|
this.browser.addLocatorStrategy(customLocator, locatorFunction)
|
|
@@ -642,6 +627,11 @@ class WebDriver extends Helper {
|
|
|
642
627
|
this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase()
|
|
643
628
|
}
|
|
644
629
|
|
|
630
|
+
this.browser.on('dialog', () => {})
|
|
631
|
+
|
|
632
|
+
await this.browser.sessionSubscribe({ events: ['log.entryAdded'] })
|
|
633
|
+
this.browser.on('log.entryAdded', logEvents)
|
|
634
|
+
|
|
645
635
|
return this.browser
|
|
646
636
|
}
|
|
647
637
|
|
|
@@ -667,7 +657,7 @@ class WebDriver extends Helper {
|
|
|
667
657
|
this.isRunning = false
|
|
668
658
|
return this.browser.deleteSession()
|
|
669
659
|
}
|
|
670
|
-
if (this.browser.isInsideFrame) await this.browser.
|
|
660
|
+
if (this.browser.isInsideFrame) await this.browser.switchFrame(null)
|
|
671
661
|
|
|
672
662
|
if (this.options.keepBrowserState) return
|
|
673
663
|
|
|
@@ -675,10 +665,11 @@ class WebDriver extends Helper {
|
|
|
675
665
|
this.debugSection('Session', 'cleaning cookies and localStorage')
|
|
676
666
|
await this.browser.deleteCookies()
|
|
677
667
|
}
|
|
678
|
-
await this.browser.execute('localStorage.clear();').catch(
|
|
668
|
+
await this.browser.execute('localStorage.clear();').catch(err => {
|
|
679
669
|
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
|
|
680
670
|
})
|
|
681
671
|
await this.closeOtherTabs()
|
|
672
|
+
browserLogs = []
|
|
682
673
|
return this.browser
|
|
683
674
|
}
|
|
684
675
|
|
|
@@ -705,17 +696,17 @@ class WebDriver extends Helper {
|
|
|
705
696
|
|
|
706
697
|
return browser
|
|
707
698
|
},
|
|
708
|
-
stop: async
|
|
699
|
+
stop: async browser => {
|
|
709
700
|
if (!browser) return
|
|
710
701
|
return browser.deleteSession()
|
|
711
702
|
},
|
|
712
|
-
loadVars: async
|
|
703
|
+
loadVars: async browser => {
|
|
713
704
|
if (this.context !== this.root) throw new Error("Can't start session inside within block")
|
|
714
705
|
this.browser = browser
|
|
715
706
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
716
707
|
this.sessionWindows[this.activeSessionName] = browser
|
|
717
708
|
},
|
|
718
|
-
restoreVars: async
|
|
709
|
+
restoreVars: async session => {
|
|
719
710
|
if (!session) {
|
|
720
711
|
this.activeSessionName = ''
|
|
721
712
|
}
|
|
@@ -757,7 +748,7 @@ class WebDriver extends Helper {
|
|
|
757
748
|
this.browser.isInsideFrame = true
|
|
758
749
|
if (Array.isArray(frame)) {
|
|
759
750
|
// this.switchTo(null);
|
|
760
|
-
await forEachAsync(frame, async
|
|
751
|
+
await forEachAsync(frame, async f => this.switchTo(f))
|
|
761
752
|
return
|
|
762
753
|
}
|
|
763
754
|
await this.switchTo(frame)
|
|
@@ -835,10 +826,7 @@ class WebDriver extends Helper {
|
|
|
835
826
|
* @param {object} locator
|
|
836
827
|
*/
|
|
837
828
|
async _smartWait(locator) {
|
|
838
|
-
this.debugSection(
|
|
839
|
-
`SmartWait (${this.options.smartWait}ms)`,
|
|
840
|
-
`Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`,
|
|
841
|
-
)
|
|
829
|
+
this.debugSection(`SmartWait (${this.options.smartWait}ms)`, `Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`)
|
|
842
830
|
await this.defineTimeout({ implicit: this.options.smartWait })
|
|
843
831
|
}
|
|
844
832
|
|
|
@@ -913,7 +901,7 @@ class WebDriver extends Helper {
|
|
|
913
901
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
914
902
|
*/
|
|
915
903
|
async _locateCheckable(locator) {
|
|
916
|
-
return findCheckable.call(this, locator, this.$$.bind(this)).then(
|
|
904
|
+
return findCheckable.call(this, locator, this.$$.bind(this)).then(res => res)
|
|
917
905
|
}
|
|
918
906
|
|
|
919
907
|
/**
|
|
@@ -941,7 +929,7 @@ class WebDriver extends Helper {
|
|
|
941
929
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
942
930
|
*/
|
|
943
931
|
async _locateFields(locator) {
|
|
944
|
-
return findFields.call(this, locator).then(
|
|
932
|
+
return findFields.call(this, locator).then(res => res)
|
|
945
933
|
}
|
|
946
934
|
|
|
947
935
|
/**
|
|
@@ -949,7 +937,20 @@ class WebDriver extends Helper {
|
|
|
949
937
|
*
|
|
950
938
|
*/
|
|
951
939
|
async grabWebElements(locator) {
|
|
952
|
-
|
|
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)
|
|
953
954
|
}
|
|
954
955
|
|
|
955
956
|
/**
|
|
@@ -1025,7 +1026,7 @@ class WebDriver extends Helper {
|
|
|
1025
1026
|
const elem = usingFirstElement(res)
|
|
1026
1027
|
highlightActiveElement.call(this, elem)
|
|
1027
1028
|
|
|
1028
|
-
return this.executeScript(
|
|
1029
|
+
return this.executeScript(el => {
|
|
1029
1030
|
if (document.activeElement instanceof HTMLElement) {
|
|
1030
1031
|
document.activeElement.blur()
|
|
1031
1032
|
}
|
|
@@ -1097,7 +1098,7 @@ class WebDriver extends Helper {
|
|
|
1097
1098
|
}
|
|
1098
1099
|
const elem = usingFirstElement(res)
|
|
1099
1100
|
|
|
1100
|
-
return this.executeScript(
|
|
1101
|
+
return this.executeScript(el => {
|
|
1101
1102
|
if (document.activeElement instanceof HTMLElement) {
|
|
1102
1103
|
document.activeElement.blur()
|
|
1103
1104
|
}
|
|
@@ -1160,15 +1161,9 @@ class WebDriver extends Helper {
|
|
|
1160
1161
|
}
|
|
1161
1162
|
|
|
1162
1163
|
// select options by visible text
|
|
1163
|
-
let els = await forEachAsync(option, async (opt)
|
|
1164
|
-
this.browser.findElementsFromElement(
|
|
1165
|
-
getElementId(elem),
|
|
1166
|
-
'xpath',
|
|
1167
|
-
Locator.select.byVisibleText(xpathLocator.literal(opt)),
|
|
1168
|
-
),
|
|
1169
|
-
)
|
|
1164
|
+
let els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byVisibleText(xpathLocator.literal(opt))))
|
|
1170
1165
|
|
|
1171
|
-
const clickOptionFn = async
|
|
1166
|
+
const clickOptionFn = async el => {
|
|
1172
1167
|
if (el[0]) el = el[0]
|
|
1173
1168
|
const elementId = getElementId(el)
|
|
1174
1169
|
if (elementId) return this.browser.elementClick(elementId)
|
|
@@ -1178,19 +1173,9 @@ class WebDriver extends Helper {
|
|
|
1178
1173
|
return forEachAsync(els, clickOptionFn)
|
|
1179
1174
|
}
|
|
1180
1175
|
// select options by value
|
|
1181
|
-
els = await forEachAsync(option, async (opt)
|
|
1182
|
-
this.browser.findElementsFromElement(
|
|
1183
|
-
getElementId(elem),
|
|
1184
|
-
'xpath',
|
|
1185
|
-
Locator.select.byValue(xpathLocator.literal(opt)),
|
|
1186
|
-
),
|
|
1187
|
-
)
|
|
1176
|
+
els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byValue(xpathLocator.literal(opt))))
|
|
1188
1177
|
if (els.length === 0) {
|
|
1189
|
-
throw new ElementNotFound(
|
|
1190
|
-
select,
|
|
1191
|
-
`Option "${option}" in`,
|
|
1192
|
-
'was not found neither by a visible text nor by a value',
|
|
1193
|
-
)
|
|
1178
|
+
throw new ElementNotFound(select, `Option "${option}" in`, 'was not found neither by a visible text nor by a value')
|
|
1194
1179
|
}
|
|
1195
1180
|
return forEachAsync(els, clickOptionFn)
|
|
1196
1181
|
}
|
|
@@ -1217,9 +1202,7 @@ class WebDriver extends Helper {
|
|
|
1217
1202
|
this.debugSection('File', 'Uploading file to remote server')
|
|
1218
1203
|
file = await this.browser.uploadFile(file)
|
|
1219
1204
|
} catch (err) {
|
|
1220
|
-
throw new Error(
|
|
1221
|
-
`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`,
|
|
1222
|
-
)
|
|
1205
|
+
throw new Error(`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`)
|
|
1223
1206
|
}
|
|
1224
1207
|
}
|
|
1225
1208
|
|
|
@@ -1272,7 +1255,11 @@ class WebDriver extends Helper {
|
|
|
1272
1255
|
*/
|
|
1273
1256
|
async grabTextFromAll(locator) {
|
|
1274
1257
|
const res = await this._locate(locator, true)
|
|
1275
|
-
|
|
1258
|
+
let val = []
|
|
1259
|
+
await forEachAsync(res, async el => {
|
|
1260
|
+
const text = await this.browser.getElementText(getElementId(el))
|
|
1261
|
+
val.push(text)
|
|
1262
|
+
})
|
|
1276
1263
|
this.debugSection('GrabText', String(val))
|
|
1277
1264
|
return val
|
|
1278
1265
|
}
|
|
@@ -1297,7 +1284,7 @@ class WebDriver extends Helper {
|
|
|
1297
1284
|
*/
|
|
1298
1285
|
async grabHTMLFromAll(locator) {
|
|
1299
1286
|
const elems = await this._locate(locator, true)
|
|
1300
|
-
const html = await forEachAsync(elems,
|
|
1287
|
+
const html = await forEachAsync(elems, elem => elem.getHTML(false))
|
|
1301
1288
|
this.debugSection('GrabHTML', String(html))
|
|
1302
1289
|
return html
|
|
1303
1290
|
}
|
|
@@ -1322,7 +1309,7 @@ class WebDriver extends Helper {
|
|
|
1322
1309
|
*/
|
|
1323
1310
|
async grabValueFromAll(locator) {
|
|
1324
1311
|
const res = await this._locate(locator, true)
|
|
1325
|
-
const val = await forEachAsync(res,
|
|
1312
|
+
const val = await forEachAsync(res, el => el.getValue())
|
|
1326
1313
|
this.debugSection('GrabValue', String(val))
|
|
1327
1314
|
|
|
1328
1315
|
return val
|
|
@@ -1347,7 +1334,7 @@ class WebDriver extends Helper {
|
|
|
1347
1334
|
*/
|
|
1348
1335
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
1349
1336
|
const res = await this._locate(locator, true)
|
|
1350
|
-
const val = await forEachAsync(res, async
|
|
1337
|
+
const val = await forEachAsync(res, async el => this.browser.getElementCSSValue(getElementId(el), cssProperty))
|
|
1351
1338
|
this.debugSection('Grab', String(val))
|
|
1352
1339
|
return val
|
|
1353
1340
|
}
|
|
@@ -1371,7 +1358,7 @@ class WebDriver extends Helper {
|
|
|
1371
1358
|
*/
|
|
1372
1359
|
async grabAttributeFromAll(locator, attr) {
|
|
1373
1360
|
const res = await this._locate(locator, true)
|
|
1374
|
-
const val = await forEachAsync(res, async
|
|
1361
|
+
const val = await forEachAsync(res, async el => el.getAttribute(attr))
|
|
1375
1362
|
this.debugSection('GrabAttribute', String(val))
|
|
1376
1363
|
return val
|
|
1377
1364
|
}
|
|
@@ -1488,7 +1475,7 @@ class WebDriver extends Helper {
|
|
|
1488
1475
|
async seeElement(locator) {
|
|
1489
1476
|
const res = await this._locate(locator, true)
|
|
1490
1477
|
assertElementExists(res, locator)
|
|
1491
|
-
const selected = await forEachAsync(res, async
|
|
1478
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1492
1479
|
try {
|
|
1493
1480
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').assert(selected)
|
|
1494
1481
|
} catch (e) {
|
|
@@ -1505,7 +1492,7 @@ class WebDriver extends Helper {
|
|
|
1505
1492
|
if (!res || res.length === 0) {
|
|
1506
1493
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(false)
|
|
1507
1494
|
}
|
|
1508
|
-
const selected = await forEachAsync(res, async
|
|
1495
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1509
1496
|
try {
|
|
1510
1497
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(selected)
|
|
1511
1498
|
} catch (e) {
|
|
@@ -1560,11 +1547,7 @@ class WebDriver extends Helper {
|
|
|
1560
1547
|
* {{> grabBrowserLogs }}
|
|
1561
1548
|
*/
|
|
1562
1549
|
async grabBrowserLogs() {
|
|
1563
|
-
|
|
1564
|
-
this.debug('Logs not available in W3C specification')
|
|
1565
|
-
return
|
|
1566
|
-
}
|
|
1567
|
-
return this.browser.getLogs('browser')
|
|
1550
|
+
return browserLogs
|
|
1568
1551
|
}
|
|
1569
1552
|
|
|
1570
1553
|
/**
|
|
@@ -1590,11 +1573,7 @@ class WebDriver extends Helper {
|
|
|
1590
1573
|
*/
|
|
1591
1574
|
async seeNumberOfElements(locator, num) {
|
|
1592
1575
|
const res = await this._locate(locator)
|
|
1593
|
-
return assert.equal(
|
|
1594
|
-
res.length,
|
|
1595
|
-
num,
|
|
1596
|
-
`expected number of elements (${new Locator(locator)}) is ${num}, but found ${res.length}`,
|
|
1597
|
-
)
|
|
1576
|
+
return assert.equal(res.length, num, `expected number of elements (${new Locator(locator)}) is ${num}, but found ${res.length}`)
|
|
1598
1577
|
}
|
|
1599
1578
|
|
|
1600
1579
|
/**
|
|
@@ -1603,11 +1582,7 @@ class WebDriver extends Helper {
|
|
|
1603
1582
|
*/
|
|
1604
1583
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1605
1584
|
const res = await this.grabNumberOfVisibleElements(locator)
|
|
1606
|
-
return assert.equal(
|
|
1607
|
-
res,
|
|
1608
|
-
num,
|
|
1609
|
-
`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`,
|
|
1610
|
-
)
|
|
1585
|
+
return assert.equal(res, num, `expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`)
|
|
1611
1586
|
}
|
|
1612
1587
|
|
|
1613
1588
|
/**
|
|
@@ -1632,19 +1607,16 @@ class WebDriver extends Helper {
|
|
|
1632
1607
|
}
|
|
1633
1608
|
}
|
|
1634
1609
|
|
|
1635
|
-
const values = Object.keys(cssPropertiesCamelCase).map(
|
|
1610
|
+
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key])
|
|
1636
1611
|
if (!Array.isArray(props)) props = [props]
|
|
1637
1612
|
let chunked = chunkArray(props, values.length)
|
|
1638
|
-
chunked = chunked.filter(
|
|
1613
|
+
chunked = chunked.filter(val => {
|
|
1639
1614
|
for (let i = 0; i < val.length; ++i) {
|
|
1640
|
-
// eslint-disable-next-line eqeqeq
|
|
1641
1615
|
if (val[i] != values[i]) return false
|
|
1642
1616
|
}
|
|
1643
1617
|
return true
|
|
1644
1618
|
})
|
|
1645
|
-
return equals(
|
|
1646
|
-
`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
|
|
1647
|
-
).assert(chunked.length, elemAmount)
|
|
1619
|
+
return equals(`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount)
|
|
1648
1620
|
}
|
|
1649
1621
|
|
|
1650
1622
|
/**
|
|
@@ -1655,28 +1627,24 @@ class WebDriver extends Helper {
|
|
|
1655
1627
|
assertElementExists(res, locator)
|
|
1656
1628
|
const elemAmount = res.length
|
|
1657
1629
|
|
|
1658
|
-
let attrs = await forEachAsync(res, async
|
|
1659
|
-
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))
|
|
1660
1632
|
})
|
|
1661
1633
|
|
|
1662
|
-
const values = Object.keys(attributes).map(
|
|
1634
|
+
const values = Object.keys(attributes).map(key => attributes[key])
|
|
1663
1635
|
if (!Array.isArray(attrs)) attrs = [attrs]
|
|
1664
1636
|
let chunked = chunkArray(attrs, values.length)
|
|
1665
|
-
chunked = chunked.filter(
|
|
1637
|
+
chunked = chunked.filter(val => {
|
|
1666
1638
|
for (let i = 0; i < val.length; ++i) {
|
|
1667
1639
|
const _actual = Number.isNaN(val[i]) || typeof values[i] === 'string' ? val[i] : Number.parseInt(val[i], 10)
|
|
1668
|
-
const _expected =
|
|
1669
|
-
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)
|
|
1670
1641
|
// the attribute could be a boolean
|
|
1671
1642
|
if (typeof _actual === 'boolean') return _actual === _expected
|
|
1672
1643
|
if (_actual !== _expected) return false
|
|
1673
1644
|
}
|
|
1674
1645
|
return true
|
|
1675
1646
|
})
|
|
1676
|
-
return assert.ok(
|
|
1677
|
-
chunked.length === elemAmount,
|
|
1678
|
-
`expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`,
|
|
1679
|
-
)
|
|
1647
|
+
return assert.ok(chunked.length === elemAmount, `expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`)
|
|
1680
1648
|
}
|
|
1681
1649
|
|
|
1682
1650
|
/**
|
|
@@ -1685,9 +1653,9 @@ class WebDriver extends Helper {
|
|
|
1685
1653
|
async grabNumberOfVisibleElements(locator) {
|
|
1686
1654
|
const res = await this._locate(locator)
|
|
1687
1655
|
|
|
1688
|
-
let selected = await forEachAsync(res, async
|
|
1656
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1689
1657
|
if (!Array.isArray(selected)) selected = [selected]
|
|
1690
|
-
selected = selected.filter(
|
|
1658
|
+
selected = selected.filter(val => val === true)
|
|
1691
1659
|
return selected.length
|
|
1692
1660
|
}
|
|
1693
1661
|
|
|
@@ -1841,18 +1809,25 @@ class WebDriver extends Helper {
|
|
|
1841
1809
|
|
|
1842
1810
|
if (browser) {
|
|
1843
1811
|
this.debug(`Screenshot of ${sessionName} session has been saved to ${outputFile}`)
|
|
1844
|
-
|
|
1812
|
+
await browser.saveScreenshot(outputFile)
|
|
1845
1813
|
}
|
|
1846
1814
|
}
|
|
1847
1815
|
}
|
|
1848
1816
|
|
|
1849
1817
|
if (!fullPage) {
|
|
1850
1818
|
this.debug(`Screenshot has been saved to ${outputFile}`)
|
|
1851
|
-
|
|
1819
|
+
await this.browser.saveScreenshot(outputFile)
|
|
1852
1820
|
}
|
|
1853
1821
|
|
|
1854
1822
|
const originalWindowSize = await this.browser.getWindowSize()
|
|
1855
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
|
+
|
|
1856
1831
|
let { width, height } = await this.browser
|
|
1857
1832
|
.execute(function () {
|
|
1858
1833
|
return {
|
|
@@ -1860,7 +1835,7 @@ class WebDriver extends Helper {
|
|
|
1860
1835
|
width: document.body.scrollWidth,
|
|
1861
1836
|
}
|
|
1862
1837
|
})
|
|
1863
|
-
.then(
|
|
1838
|
+
.then(res => res)
|
|
1864
1839
|
|
|
1865
1840
|
if (height < 100) height = 500 // errors for very small height
|
|
1866
1841
|
|
|
@@ -1928,7 +1903,7 @@ class WebDriver extends Helper {
|
|
|
1928
1903
|
|
|
1929
1904
|
return promiseRetry(
|
|
1930
1905
|
async (retry, number) => {
|
|
1931
|
-
const _grabCookie = async
|
|
1906
|
+
const _grabCookie = async name => {
|
|
1932
1907
|
const cookie = await this.browser.getCookies([name])
|
|
1933
1908
|
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
|
|
1934
1909
|
}
|
|
@@ -1952,11 +1927,10 @@ class WebDriver extends Helper {
|
|
|
1952
1927
|
* libraries](http://jster.net/category/windows-modals-popups).
|
|
1953
1928
|
*/
|
|
1954
1929
|
async acceptPopup() {
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
})
|
|
1930
|
+
const text = await this.browser.getAlertText()
|
|
1931
|
+
if (text) {
|
|
1932
|
+
return await this.browser.acceptAlert()
|
|
1933
|
+
}
|
|
1960
1934
|
}
|
|
1961
1935
|
|
|
1962
1936
|
/**
|
|
@@ -1964,11 +1938,10 @@ class WebDriver extends Helper {
|
|
|
1964
1938
|
*
|
|
1965
1939
|
*/
|
|
1966
1940
|
async cancelPopup() {
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
})
|
|
1941
|
+
const text = await this.browser.getAlertText()
|
|
1942
|
+
if (text) {
|
|
1943
|
+
return await this.browser.dismissAlert()
|
|
1944
|
+
}
|
|
1972
1945
|
}
|
|
1973
1946
|
|
|
1974
1947
|
/**
|
|
@@ -1978,7 +1951,7 @@ class WebDriver extends Helper {
|
|
|
1978
1951
|
* @param {string} text value to check.
|
|
1979
1952
|
*/
|
|
1980
1953
|
async seeInPopup(text) {
|
|
1981
|
-
return this.browser.getAlertText().then(
|
|
1954
|
+
return await this.browser.getAlertText().then(res => {
|
|
1982
1955
|
if (res === null) {
|
|
1983
1956
|
throw new Error('Popup is not opened')
|
|
1984
1957
|
}
|
|
@@ -2259,9 +2232,9 @@ class WebDriver extends Helper {
|
|
|
2259
2232
|
async closeOtherTabs() {
|
|
2260
2233
|
const handles = await this.browser.getWindowHandles()
|
|
2261
2234
|
const currentHandle = await this.browser.getWindowHandle()
|
|
2262
|
-
const otherHandles = handles.filter(
|
|
2235
|
+
const otherHandles = handles.filter(handle => handle !== currentHandle)
|
|
2263
2236
|
|
|
2264
|
-
await forEachAsync(otherHandles, async
|
|
2237
|
+
await forEachAsync(otherHandles, async handle => {
|
|
2265
2238
|
await this.browser.switchToWindow(handle)
|
|
2266
2239
|
await this.browser.closeWindow()
|
|
2267
2240
|
})
|
|
@@ -2272,7 +2245,7 @@ class WebDriver extends Helper {
|
|
|
2272
2245
|
* {{> wait }}
|
|
2273
2246
|
*/
|
|
2274
2247
|
async wait(sec) {
|
|
2275
|
-
return new Promise(
|
|
2248
|
+
return new Promise(resolve => {
|
|
2276
2249
|
setTimeout(resolve, sec * 1000)
|
|
2277
2250
|
})
|
|
2278
2251
|
}
|
|
@@ -2289,9 +2262,9 @@ class WebDriver extends Helper {
|
|
|
2289
2262
|
if (!res || res.length === 0) {
|
|
2290
2263
|
return false
|
|
2291
2264
|
}
|
|
2292
|
-
const selected = await forEachAsync(res, async
|
|
2265
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementEnabled(getElementId(el)))
|
|
2293
2266
|
if (Array.isArray(selected)) {
|
|
2294
|
-
return selected.filter(
|
|
2267
|
+
return selected.filter(val => val === true).length > 0
|
|
2295
2268
|
}
|
|
2296
2269
|
return selected
|
|
2297
2270
|
},
|
|
@@ -2346,14 +2319,14 @@ class WebDriver extends Helper {
|
|
|
2346
2319
|
return client
|
|
2347
2320
|
.waitUntil(
|
|
2348
2321
|
function () {
|
|
2349
|
-
return this.getUrl().then(
|
|
2322
|
+
return this.getUrl().then(res => {
|
|
2350
2323
|
currUrl = decodeUrl(res)
|
|
2351
2324
|
return currUrl.indexOf(urlPart) > -1
|
|
2352
2325
|
})
|
|
2353
2326
|
},
|
|
2354
2327
|
{ timeout: aSec * 1000 },
|
|
2355
2328
|
)
|
|
2356
|
-
.catch(
|
|
2329
|
+
.catch(e => {
|
|
2357
2330
|
if (e.message.indexOf('timeout')) {
|
|
2358
2331
|
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
|
|
2359
2332
|
}
|
|
@@ -2373,12 +2346,12 @@ class WebDriver extends Helper {
|
|
|
2373
2346
|
let currUrl = ''
|
|
2374
2347
|
return this.browser
|
|
2375
2348
|
.waitUntil(function () {
|
|
2376
|
-
return this.getUrl().then(
|
|
2349
|
+
return this.getUrl().then(res => {
|
|
2377
2350
|
currUrl = decodeUrl(res)
|
|
2378
2351
|
return currUrl === urlPart
|
|
2379
2352
|
})
|
|
2380
2353
|
}, aSec * 1000)
|
|
2381
|
-
.catch(
|
|
2354
|
+
.catch(e => {
|
|
2382
2355
|
if (e.message.indexOf('timeout')) {
|
|
2383
2356
|
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
|
|
2384
2357
|
}
|
|
@@ -2398,9 +2371,9 @@ class WebDriver extends Helper {
|
|
|
2398
2371
|
async () => {
|
|
2399
2372
|
const res = await this.$$(withStrictLocator.call(this, _context))
|
|
2400
2373
|
if (!res || res.length === 0) return false
|
|
2401
|
-
const selected = await forEachAsync(res, async
|
|
2374
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)))
|
|
2402
2375
|
if (Array.isArray(selected)) {
|
|
2403
|
-
return selected.filter(
|
|
2376
|
+
return selected.filter(part => part.indexOf(text) >= 0).length > 0
|
|
2404
2377
|
}
|
|
2405
2378
|
return selected.indexOf(text) >= 0
|
|
2406
2379
|
},
|
|
@@ -2422,9 +2395,9 @@ class WebDriver extends Helper {
|
|
|
2422
2395
|
async () => {
|
|
2423
2396
|
const res = await findFields.call(this, field)
|
|
2424
2397
|
if (!res || res.length === 0) return false
|
|
2425
|
-
const selected = await forEachAsync(res, async
|
|
2398
|
+
const selected = await forEachAsync(res, async el => el.getValue())
|
|
2426
2399
|
if (Array.isArray(selected)) {
|
|
2427
|
-
return selected.filter(
|
|
2400
|
+
return selected.filter(part => part.indexOf(value) >= 0).length > 0
|
|
2428
2401
|
}
|
|
2429
2402
|
return selected.indexOf(value) >= 0
|
|
2430
2403
|
},
|
|
@@ -2446,9 +2419,9 @@ class WebDriver extends Helper {
|
|
|
2446
2419
|
async () => {
|
|
2447
2420
|
const res = await this._res(locator)
|
|
2448
2421
|
if (!res || res.length === 0) return false
|
|
2449
|
-
const selected = await forEachAsync(res, async
|
|
2422
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2450
2423
|
if (Array.isArray(selected)) {
|
|
2451
|
-
return selected.filter(
|
|
2424
|
+
return selected.filter(val => val === true).length > 0
|
|
2452
2425
|
}
|
|
2453
2426
|
return selected
|
|
2454
2427
|
},
|
|
@@ -2469,10 +2442,10 @@ class WebDriver extends Helper {
|
|
|
2469
2442
|
async () => {
|
|
2470
2443
|
const res = await this._res(locator)
|
|
2471
2444
|
if (!res || res.length === 0) return false
|
|
2472
|
-
let selected = await forEachAsync(res, async
|
|
2445
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2473
2446
|
|
|
2474
2447
|
if (!Array.isArray(selected)) selected = [selected]
|
|
2475
|
-
selected = selected.filter(
|
|
2448
|
+
selected = selected.filter(val => val === true)
|
|
2476
2449
|
return selected.length === num
|
|
2477
2450
|
},
|
|
2478
2451
|
{
|
|
@@ -2492,7 +2465,7 @@ class WebDriver extends Helper {
|
|
|
2492
2465
|
async () => {
|
|
2493
2466
|
const res = await this._res(locator)
|
|
2494
2467
|
if (!res || res.length === 0) return true
|
|
2495
|
-
const selected = await forEachAsync(res, async
|
|
2468
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2496
2469
|
return !selected.length
|
|
2497
2470
|
},
|
|
2498
2471
|
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still visible after ${aSec} sec` },
|
|
@@ -2568,17 +2541,14 @@ class WebDriver extends Helper {
|
|
|
2568
2541
|
*/
|
|
2569
2542
|
async switchTo(locator) {
|
|
2570
2543
|
this.browser.isInsideFrame = true
|
|
2571
|
-
if (Number.isInteger(locator)) {
|
|
2572
|
-
return this.browser.switchToFrame(locator)
|
|
2573
|
-
}
|
|
2574
2544
|
if (!locator) {
|
|
2575
|
-
return this.browser.
|
|
2545
|
+
return this.browser.switchFrame(null)
|
|
2576
2546
|
}
|
|
2577
2547
|
|
|
2578
2548
|
let res = await this._locate(locator, true)
|
|
2579
2549
|
assertElementExists(res, locator)
|
|
2580
2550
|
res = usingFirstElement(res)
|
|
2581
|
-
return this.browser.
|
|
2551
|
+
return this.browser.switchFrame(res)
|
|
2582
2552
|
}
|
|
2583
2553
|
|
|
2584
2554
|
/**
|
|
@@ -2591,7 +2561,7 @@ class WebDriver extends Helper {
|
|
|
2591
2561
|
|
|
2592
2562
|
await this.browser.waitUntil(
|
|
2593
2563
|
async () => {
|
|
2594
|
-
await this.browser.getWindowHandles().then(
|
|
2564
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2595
2565
|
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
2596
2566
|
target = handles[handles.indexOf(current) + num]
|
|
2597
2567
|
}
|
|
@@ -2613,7 +2583,7 @@ class WebDriver extends Helper {
|
|
|
2613
2583
|
|
|
2614
2584
|
await this.browser.waitUntil(
|
|
2615
2585
|
async () => {
|
|
2616
|
-
await this.browser.getWindowHandles().then(
|
|
2586
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2617
2587
|
if (handles.indexOf(current) - num > -1) {
|
|
2618
2588
|
target = handles[handles.indexOf(current) - num]
|
|
2619
2589
|
}
|
|
@@ -2683,10 +2653,7 @@ class WebDriver extends Helper {
|
|
|
2683
2653
|
return client.execute(function () {
|
|
2684
2654
|
const body = document.body
|
|
2685
2655
|
const html = document.documentElement
|
|
2686
|
-
window.scrollTo(
|
|
2687
|
-
0,
|
|
2688
|
-
Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
|
|
2689
|
-
)
|
|
2656
|
+
window.scrollTo(0, Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight))
|
|
2690
2657
|
})
|
|
2691
2658
|
}
|
|
2692
2659
|
|
|
@@ -2760,10 +2727,17 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
2760
2727
|
const smartWaitEnabled = assertType === 'assert'
|
|
2761
2728
|
const res = await this._locate(withStrictLocator(context), smartWaitEnabled)
|
|
2762
2729
|
assertElementExists(res, context)
|
|
2763
|
-
|
|
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
|
+
|
|
2764
2738
|
if (strict) {
|
|
2765
2739
|
if (Array.isArray(selected) && selected.length !== 0) {
|
|
2766
|
-
return selected.map(
|
|
2740
|
+
return selected.map(elText => equals(description)[assertType](text, elText))
|
|
2767
2741
|
}
|
|
2768
2742
|
return equals(description)[assertType](text, selected)
|
|
2769
2743
|
}
|
|
@@ -2791,7 +2765,7 @@ async function forEachAsync(array, callback, options = { expandArrayResults: tru
|
|
|
2791
2765
|
const res = await callback(inputArray[index], index, inputArray)
|
|
2792
2766
|
|
|
2793
2767
|
if (Array.isArray(res) && expandArrayResults) {
|
|
2794
|
-
res.forEach(
|
|
2768
|
+
res.forEach(val => values.push(val))
|
|
2795
2769
|
} else if (res) {
|
|
2796
2770
|
values.push(res)
|
|
2797
2771
|
}
|
|
@@ -2877,11 +2851,11 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2877
2851
|
const elem = usingFirstElement(res)
|
|
2878
2852
|
const elemId = getElementId(elem)
|
|
2879
2853
|
|
|
2880
|
-
const proceedMultiple = async
|
|
2854
|
+
const proceedMultiple = async fields => {
|
|
2881
2855
|
const fieldResults = toArray(
|
|
2882
|
-
await forEachAsync(fields, async
|
|
2856
|
+
await forEachAsync(fields, async el => {
|
|
2883
2857
|
const elementId = getElementId(el)
|
|
2884
|
-
return this.browser.
|
|
2858
|
+
return this.browser.getElementAttribute(elementId, 'value')
|
|
2885
2859
|
}),
|
|
2886
2860
|
)
|
|
2887
2861
|
|
|
@@ -2890,27 +2864,24 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2890
2864
|
} else {
|
|
2891
2865
|
// Assert that results were found so the forEach assert does not silently pass
|
|
2892
2866
|
equals(`no. of items matching > 0: ${field}`)[assertType](true, !!fieldResults.length)
|
|
2893
|
-
fieldResults.forEach(
|
|
2867
|
+
fieldResults.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val))
|
|
2894
2868
|
}
|
|
2895
2869
|
}
|
|
2896
2870
|
|
|
2897
|
-
const proceedSingle =
|
|
2898
|
-
el.getValue().then(
|
|
2871
|
+
const proceedSingle = el =>
|
|
2872
|
+
el.getValue().then(res => {
|
|
2899
2873
|
if (res === null) {
|
|
2900
2874
|
throw new Error(`Element ${el.selector} has no value attribute`)
|
|
2901
2875
|
}
|
|
2902
2876
|
stringIncludes(`fields by ${field}`)[assertType](value, res)
|
|
2903
2877
|
})
|
|
2904
2878
|
|
|
2905
|
-
const filterBySelected = async (elements
|
|
2906
|
-
filterAsync(elements, async (el) => this.browser.isElementSelected(getElementId(el)))
|
|
2879
|
+
const filterBySelected = async elements => filterAsync(elements, async el => this.browser.isElementSelected(getElementId(el)))
|
|
2907
2880
|
|
|
2908
2881
|
const filterSelectedByValue = async (elements, value) => {
|
|
2909
|
-
return filterAsync(elements, async
|
|
2882
|
+
return filterAsync(elements, async el => {
|
|
2910
2883
|
const elementId = getElementId(el)
|
|
2911
|
-
const currentValue = this.browser.
|
|
2912
|
-
? await el.getValue()
|
|
2913
|
-
: await this.browser.getElementAttribute(elementId, 'value')
|
|
2884
|
+
const currentValue = await this.browser.getElementAttribute(elementId, 'value')
|
|
2914
2885
|
const isSelected = await this.browser.isElementSelected(elementId)
|
|
2915
2886
|
return currentValue === value && isSelected
|
|
2916
2887
|
})
|
|
@@ -2918,7 +2889,13 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2918
2889
|
|
|
2919
2890
|
const tag = await elem.getTagName()
|
|
2920
2891
|
if (tag === 'select') {
|
|
2921
|
-
|
|
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
|
+
}
|
|
2922
2899
|
|
|
2923
2900
|
if (value === '') {
|
|
2924
2901
|
// Don't filter by value
|
|
@@ -2959,7 +2936,7 @@ async function proceedSeeCheckbox(assertType, field) {
|
|
|
2959
2936
|
const res = await findFields.call(this, field)
|
|
2960
2937
|
assertElementExists(res, field, 'Field')
|
|
2961
2938
|
|
|
2962
|
-
const selected = await forEachAsync(res, async
|
|
2939
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementSelected(getElementId(el)))
|
|
2963
2940
|
return truth(`checkable field "${field}"`, 'to be checked')[assertType](selected)
|
|
2964
2941
|
}
|
|
2965
2942
|
|
|
@@ -3160,7 +3137,7 @@ function getNormalizedKey(key) {
|
|
|
3160
3137
|
return convertKeyToRawKey(normalizedKey)
|
|
3161
3138
|
}
|
|
3162
3139
|
|
|
3163
|
-
const unicodeModifierKeys = modifierKeys.map(
|
|
3140
|
+
const unicodeModifierKeys = modifierKeys.map(k => convertKeyToRawKey(k))
|
|
3164
3141
|
function isModifierKey(key) {
|
|
3165
3142
|
return unicodeModifierKeys.includes(key)
|
|
3166
3143
|
}
|
|
@@ -3173,9 +3150,9 @@ function highlightActiveElement(element) {
|
|
|
3173
3150
|
|
|
3174
3151
|
function prepareLocateFn(context) {
|
|
3175
3152
|
if (!context) return this._locate.bind(this)
|
|
3176
|
-
return
|
|
3153
|
+
return l => {
|
|
3177
3154
|
l = new Locator(l, 'css')
|
|
3178
|
-
return this._locate(context, true).then(async
|
|
3155
|
+
return this._locate(context, true).then(async res => {
|
|
3179
3156
|
assertElementExists(res, context, 'Context element')
|
|
3180
3157
|
if (l.react) {
|
|
3181
3158
|
return res[0].react$$(l.react, l.props || undefined)
|
|
@@ -3185,4 +3162,8 @@ function prepareLocateFn(context) {
|
|
|
3185
3162
|
}
|
|
3186
3163
|
}
|
|
3187
3164
|
|
|
3165
|
+
function logEvents(event) {
|
|
3166
|
+
browserLogs.push(event.text) // add log message to the array
|
|
3167
|
+
}
|
|
3168
|
+
|
|
3188
3169
|
module.exports = WebDriver
|