codeceptjs 3.6.10 → 3.7.0-beta.10
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 +89 -119
- package/bin/codecept.js +9 -2
- 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 +87 -83
- package/lib/command/check.js +186 -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 +10 -8
- package/lib/command/gherkin/steps.js +1 -1
- package/lib/command/info.js +1 -3
- package/lib/command/init.js +8 -12
- package/lib/command/interactive.js +2 -2
- package/lib/command/list.js +1 -1
- package/lib/command/run-multiple.js +12 -35
- package/lib/command/run-workers.js +5 -57
- package/lib/command/utils.js +5 -6
- package/lib/command/workers/runTests.js +68 -232
- package/lib/container.js +354 -237
- 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 +218 -0
- package/lib/els.js +158 -0
- package/lib/event.js +19 -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 +45 -51
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +57 -37
- package/lib/helper/Nightmare.js +35 -53
- package/lib/helper/Playwright.js +211 -252
- package/lib/helper/Protractor.js +54 -77
- package/lib/helper/Puppeteer.js +139 -232
- package/lib/helper/REST.js +5 -17
- package/lib/helper/TestCafe.js +21 -44
- package/lib/helper/WebDriver.js +131 -169
- 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/steps.js +20 -18
- package/lib/listener/store.js +20 -0
- package/lib/mocha/asyncWrapper.js +216 -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 +24 -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 +21 -6
- package/lib/mocha/suite.js +81 -0
- package/lib/mocha/test.js +159 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +219 -0
- package/lib/output.js +82 -62
- package/lib/pause.js +155 -138
- package/lib/plugin/analyze.js +349 -0
- package/lib/plugin/autoDelay.js +6 -6
- package/lib/plugin/autoLogin.js +6 -7
- 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/pageInfo.js +140 -0
- package/lib/plugin/retryFailedStep.js +4 -4
- package/lib/plugin/retryTo.js +18 -118
- package/lib/plugin/screenshotOnFail.js +17 -49
- 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 +17 -107
- package/lib/plugin/wdio.js +8 -10
- package/lib/recorder.js +146 -125
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/secret.js +1 -1
- package/lib/step/base.js +228 -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 +10 -2
- package/lib/template/heal.js +2 -11
- package/lib/timeout.js +66 -0
- package/lib/utils.js +317 -216
- package/lib/within.js +73 -55
- package/lib/workers.js +259 -275
- package/package.json +56 -54
- package/typings/index.d.ts +175 -186
- package/typings/promiseBasedTypes.d.ts +164 -17
- package/typings/types.d.ts +284 -115
- 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,12 @@ 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
|
-
seeElementError,
|
|
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')
|
|
43
24
|
|
|
44
25
|
const SHADOW = 'shadow'
|
|
45
26
|
const webRoot = 'body'
|
|
27
|
+
let browserLogs = []
|
|
46
28
|
|
|
47
29
|
/**
|
|
48
30
|
* ## Configuration
|
|
@@ -595,10 +577,7 @@ class WebDriver extends Helper {
|
|
|
595
577
|
}
|
|
596
578
|
|
|
597
579
|
async _res(locator) {
|
|
598
|
-
const res =
|
|
599
|
-
this._isShadowLocator(locator) || this._isCustomLocator(locator)
|
|
600
|
-
? await this._locate(locator)
|
|
601
|
-
: await this.$$(withStrictLocator(locator))
|
|
580
|
+
const res = this._isShadowLocator(locator) || this._isCustomLocator(locator) ? await this._locate(locator) : await this.$$(withStrictLocator(locator))
|
|
602
581
|
return res
|
|
603
582
|
}
|
|
604
583
|
|
|
@@ -631,7 +610,7 @@ class WebDriver extends Helper {
|
|
|
631
610
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
632
611
|
|
|
633
612
|
if (this._isCustomLocatorStrategyDefined()) {
|
|
634
|
-
Object.keys(this.customLocatorStrategies).forEach(async
|
|
613
|
+
Object.keys(this.customLocatorStrategies).forEach(async customLocator => {
|
|
635
614
|
this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`)
|
|
636
615
|
const locatorFunction = this._lookupCustomLocator(customLocator)
|
|
637
616
|
this.browser.addLocatorStrategy(customLocator, locatorFunction)
|
|
@@ -642,6 +621,11 @@ class WebDriver extends Helper {
|
|
|
642
621
|
this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase()
|
|
643
622
|
}
|
|
644
623
|
|
|
624
|
+
this.browser.on('dialog', () => {})
|
|
625
|
+
|
|
626
|
+
await this.browser.sessionSubscribe({ events: ['log.entryAdded'] })
|
|
627
|
+
this.browser.on('log.entryAdded', logEvents)
|
|
628
|
+
|
|
645
629
|
return this.browser
|
|
646
630
|
}
|
|
647
631
|
|
|
@@ -667,7 +651,7 @@ class WebDriver extends Helper {
|
|
|
667
651
|
this.isRunning = false
|
|
668
652
|
return this.browser.deleteSession()
|
|
669
653
|
}
|
|
670
|
-
if (this.browser.isInsideFrame) await this.browser.
|
|
654
|
+
if (this.browser.isInsideFrame) await this.browser.switchFrame(null)
|
|
671
655
|
|
|
672
656
|
if (this.options.keepBrowserState) return
|
|
673
657
|
|
|
@@ -675,10 +659,11 @@ class WebDriver extends Helper {
|
|
|
675
659
|
this.debugSection('Session', 'cleaning cookies and localStorage')
|
|
676
660
|
await this.browser.deleteCookies()
|
|
677
661
|
}
|
|
678
|
-
await this.browser.execute('localStorage.clear();').catch(
|
|
662
|
+
await this.browser.execute('localStorage.clear();').catch(err => {
|
|
679
663
|
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
|
|
680
664
|
})
|
|
681
665
|
await this.closeOtherTabs()
|
|
666
|
+
browserLogs = []
|
|
682
667
|
return this.browser
|
|
683
668
|
}
|
|
684
669
|
|
|
@@ -705,17 +690,17 @@ class WebDriver extends Helper {
|
|
|
705
690
|
|
|
706
691
|
return browser
|
|
707
692
|
},
|
|
708
|
-
stop: async
|
|
693
|
+
stop: async browser => {
|
|
709
694
|
if (!browser) return
|
|
710
695
|
return browser.deleteSession()
|
|
711
696
|
},
|
|
712
|
-
loadVars: async
|
|
697
|
+
loadVars: async browser => {
|
|
713
698
|
if (this.context !== this.root) throw new Error("Can't start session inside within block")
|
|
714
699
|
this.browser = browser
|
|
715
700
|
this.$$ = this.browser.$$.bind(this.browser)
|
|
716
701
|
this.sessionWindows[this.activeSessionName] = browser
|
|
717
702
|
},
|
|
718
|
-
restoreVars: async
|
|
703
|
+
restoreVars: async session => {
|
|
719
704
|
if (!session) {
|
|
720
705
|
this.activeSessionName = ''
|
|
721
706
|
}
|
|
@@ -757,7 +742,7 @@ class WebDriver extends Helper {
|
|
|
757
742
|
this.browser.isInsideFrame = true
|
|
758
743
|
if (Array.isArray(frame)) {
|
|
759
744
|
// this.switchTo(null);
|
|
760
|
-
await forEachAsync(frame, async
|
|
745
|
+
await forEachAsync(frame, async f => this.switchTo(f))
|
|
761
746
|
return
|
|
762
747
|
}
|
|
763
748
|
await this.switchTo(frame)
|
|
@@ -835,10 +820,7 @@ class WebDriver extends Helper {
|
|
|
835
820
|
* @param {object} locator
|
|
836
821
|
*/
|
|
837
822
|
async _smartWait(locator) {
|
|
838
|
-
this.debugSection(
|
|
839
|
-
`SmartWait (${this.options.smartWait}ms)`,
|
|
840
|
-
`Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`,
|
|
841
|
-
)
|
|
823
|
+
this.debugSection(`SmartWait (${this.options.smartWait}ms)`, `Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`)
|
|
842
824
|
await this.defineTimeout({ implicit: this.options.smartWait })
|
|
843
825
|
}
|
|
844
826
|
|
|
@@ -913,7 +895,7 @@ class WebDriver extends Helper {
|
|
|
913
895
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
914
896
|
*/
|
|
915
897
|
async _locateCheckable(locator) {
|
|
916
|
-
return findCheckable.call(this, locator, this.$$.bind(this)).then(
|
|
898
|
+
return findCheckable.call(this, locator, this.$$.bind(this)).then(res => res)
|
|
917
899
|
}
|
|
918
900
|
|
|
919
901
|
/**
|
|
@@ -941,7 +923,7 @@ class WebDriver extends Helper {
|
|
|
941
923
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
942
924
|
*/
|
|
943
925
|
async _locateFields(locator) {
|
|
944
|
-
return findFields.call(this, locator).then(
|
|
926
|
+
return findFields.call(this, locator).then(res => res)
|
|
945
927
|
}
|
|
946
928
|
|
|
947
929
|
/**
|
|
@@ -1025,7 +1007,7 @@ class WebDriver extends Helper {
|
|
|
1025
1007
|
const elem = usingFirstElement(res)
|
|
1026
1008
|
highlightActiveElement.call(this, elem)
|
|
1027
1009
|
|
|
1028
|
-
return this.executeScript(
|
|
1010
|
+
return this.executeScript(el => {
|
|
1029
1011
|
if (document.activeElement instanceof HTMLElement) {
|
|
1030
1012
|
document.activeElement.blur()
|
|
1031
1013
|
}
|
|
@@ -1097,7 +1079,7 @@ class WebDriver extends Helper {
|
|
|
1097
1079
|
}
|
|
1098
1080
|
const elem = usingFirstElement(res)
|
|
1099
1081
|
|
|
1100
|
-
return this.executeScript(
|
|
1082
|
+
return this.executeScript(el => {
|
|
1101
1083
|
if (document.activeElement instanceof HTMLElement) {
|
|
1102
1084
|
document.activeElement.blur()
|
|
1103
1085
|
}
|
|
@@ -1160,15 +1142,9 @@ class WebDriver extends Helper {
|
|
|
1160
1142
|
}
|
|
1161
1143
|
|
|
1162
1144
|
// 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
|
-
)
|
|
1145
|
+
let els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byVisibleText(xpathLocator.literal(opt))))
|
|
1170
1146
|
|
|
1171
|
-
const clickOptionFn = async
|
|
1147
|
+
const clickOptionFn = async el => {
|
|
1172
1148
|
if (el[0]) el = el[0]
|
|
1173
1149
|
const elementId = getElementId(el)
|
|
1174
1150
|
if (elementId) return this.browser.elementClick(elementId)
|
|
@@ -1178,19 +1154,9 @@ class WebDriver extends Helper {
|
|
|
1178
1154
|
return forEachAsync(els, clickOptionFn)
|
|
1179
1155
|
}
|
|
1180
1156
|
// 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
|
-
)
|
|
1157
|
+
els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byValue(xpathLocator.literal(opt))))
|
|
1188
1158
|
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
|
-
)
|
|
1159
|
+
throw new ElementNotFound(select, `Option "${option}" in`, 'was not found neither by a visible text nor by a value')
|
|
1194
1160
|
}
|
|
1195
1161
|
return forEachAsync(els, clickOptionFn)
|
|
1196
1162
|
}
|
|
@@ -1217,9 +1183,7 @@ class WebDriver extends Helper {
|
|
|
1217
1183
|
this.debugSection('File', 'Uploading file to remote server')
|
|
1218
1184
|
file = await this.browser.uploadFile(file)
|
|
1219
1185
|
} 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
|
-
)
|
|
1186
|
+
throw new Error(`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`)
|
|
1223
1187
|
}
|
|
1224
1188
|
}
|
|
1225
1189
|
|
|
@@ -1272,7 +1236,11 @@ class WebDriver extends Helper {
|
|
|
1272
1236
|
*/
|
|
1273
1237
|
async grabTextFromAll(locator) {
|
|
1274
1238
|
const res = await this._locate(locator, true)
|
|
1275
|
-
|
|
1239
|
+
let val = []
|
|
1240
|
+
await forEachAsync(res, async el => {
|
|
1241
|
+
const text = await this.browser.getElementText(getElementId(el))
|
|
1242
|
+
val.push(text)
|
|
1243
|
+
})
|
|
1276
1244
|
this.debugSection('GrabText', String(val))
|
|
1277
1245
|
return val
|
|
1278
1246
|
}
|
|
@@ -1297,7 +1265,7 @@ class WebDriver extends Helper {
|
|
|
1297
1265
|
*/
|
|
1298
1266
|
async grabHTMLFromAll(locator) {
|
|
1299
1267
|
const elems = await this._locate(locator, true)
|
|
1300
|
-
const html = await forEachAsync(elems,
|
|
1268
|
+
const html = await forEachAsync(elems, elem => elem.getHTML(false))
|
|
1301
1269
|
this.debugSection('GrabHTML', String(html))
|
|
1302
1270
|
return html
|
|
1303
1271
|
}
|
|
@@ -1322,7 +1290,7 @@ class WebDriver extends Helper {
|
|
|
1322
1290
|
*/
|
|
1323
1291
|
async grabValueFromAll(locator) {
|
|
1324
1292
|
const res = await this._locate(locator, true)
|
|
1325
|
-
const val = await forEachAsync(res,
|
|
1293
|
+
const val = await forEachAsync(res, el => el.getValue())
|
|
1326
1294
|
this.debugSection('GrabValue', String(val))
|
|
1327
1295
|
|
|
1328
1296
|
return val
|
|
@@ -1347,7 +1315,7 @@ class WebDriver extends Helper {
|
|
|
1347
1315
|
*/
|
|
1348
1316
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
1349
1317
|
const res = await this._locate(locator, true)
|
|
1350
|
-
const val = await forEachAsync(res, async
|
|
1318
|
+
const val = await forEachAsync(res, async el => this.browser.getElementCSSValue(getElementId(el), cssProperty))
|
|
1351
1319
|
this.debugSection('Grab', String(val))
|
|
1352
1320
|
return val
|
|
1353
1321
|
}
|
|
@@ -1371,7 +1339,7 @@ class WebDriver extends Helper {
|
|
|
1371
1339
|
*/
|
|
1372
1340
|
async grabAttributeFromAll(locator, attr) {
|
|
1373
1341
|
const res = await this._locate(locator, true)
|
|
1374
|
-
const val = await forEachAsync(res, async
|
|
1342
|
+
const val = await forEachAsync(res, async el => el.getAttribute(attr))
|
|
1375
1343
|
this.debugSection('GrabAttribute', String(val))
|
|
1376
1344
|
return val
|
|
1377
1345
|
}
|
|
@@ -1488,7 +1456,7 @@ class WebDriver extends Helper {
|
|
|
1488
1456
|
async seeElement(locator) {
|
|
1489
1457
|
const res = await this._locate(locator, true)
|
|
1490
1458
|
assertElementExists(res, locator)
|
|
1491
|
-
const selected = await forEachAsync(res, async
|
|
1459
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1492
1460
|
try {
|
|
1493
1461
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').assert(selected)
|
|
1494
1462
|
} catch (e) {
|
|
@@ -1505,7 +1473,7 @@ class WebDriver extends Helper {
|
|
|
1505
1473
|
if (!res || res.length === 0) {
|
|
1506
1474
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(false)
|
|
1507
1475
|
}
|
|
1508
|
-
const selected = await forEachAsync(res, async
|
|
1476
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1509
1477
|
try {
|
|
1510
1478
|
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(selected)
|
|
1511
1479
|
} catch (e) {
|
|
@@ -1560,11 +1528,7 @@ class WebDriver extends Helper {
|
|
|
1560
1528
|
* {{> grabBrowserLogs }}
|
|
1561
1529
|
*/
|
|
1562
1530
|
async grabBrowserLogs() {
|
|
1563
|
-
|
|
1564
|
-
this.debug('Logs not available in W3C specification')
|
|
1565
|
-
return
|
|
1566
|
-
}
|
|
1567
|
-
return this.browser.getLogs('browser')
|
|
1531
|
+
return browserLogs
|
|
1568
1532
|
}
|
|
1569
1533
|
|
|
1570
1534
|
/**
|
|
@@ -1590,11 +1554,7 @@ class WebDriver extends Helper {
|
|
|
1590
1554
|
*/
|
|
1591
1555
|
async seeNumberOfElements(locator, num) {
|
|
1592
1556
|
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
|
-
)
|
|
1557
|
+
return assert.equal(res.length, num, `expected number of elements (${new Locator(locator)}) is ${num}, but found ${res.length}`)
|
|
1598
1558
|
}
|
|
1599
1559
|
|
|
1600
1560
|
/**
|
|
@@ -1603,11 +1563,7 @@ class WebDriver extends Helper {
|
|
|
1603
1563
|
*/
|
|
1604
1564
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1605
1565
|
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
|
-
)
|
|
1566
|
+
return assert.equal(res, num, `expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`)
|
|
1611
1567
|
}
|
|
1612
1568
|
|
|
1613
1569
|
/**
|
|
@@ -1632,19 +1588,16 @@ class WebDriver extends Helper {
|
|
|
1632
1588
|
}
|
|
1633
1589
|
}
|
|
1634
1590
|
|
|
1635
|
-
const values = Object.keys(cssPropertiesCamelCase).map(
|
|
1591
|
+
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key])
|
|
1636
1592
|
if (!Array.isArray(props)) props = [props]
|
|
1637
1593
|
let chunked = chunkArray(props, values.length)
|
|
1638
|
-
chunked = chunked.filter(
|
|
1594
|
+
chunked = chunked.filter(val => {
|
|
1639
1595
|
for (let i = 0; i < val.length; ++i) {
|
|
1640
|
-
// eslint-disable-next-line eqeqeq
|
|
1641
1596
|
if (val[i] != values[i]) return false
|
|
1642
1597
|
}
|
|
1643
1598
|
return true
|
|
1644
1599
|
})
|
|
1645
|
-
return equals(
|
|
1646
|
-
`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
|
|
1647
|
-
).assert(chunked.length, elemAmount)
|
|
1600
|
+
return equals(`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount)
|
|
1648
1601
|
}
|
|
1649
1602
|
|
|
1650
1603
|
/**
|
|
@@ -1655,28 +1608,24 @@ class WebDriver extends Helper {
|
|
|
1655
1608
|
assertElementExists(res, locator)
|
|
1656
1609
|
const elemAmount = res.length
|
|
1657
1610
|
|
|
1658
|
-
let attrs = await forEachAsync(res, async
|
|
1659
|
-
return forEachAsync(Object.keys(attributes), async
|
|
1611
|
+
let attrs = await forEachAsync(res, async el => {
|
|
1612
|
+
return forEachAsync(Object.keys(attributes), async attr => el.getAttribute(attr))
|
|
1660
1613
|
})
|
|
1661
1614
|
|
|
1662
|
-
const values = Object.keys(attributes).map(
|
|
1615
|
+
const values = Object.keys(attributes).map(key => attributes[key])
|
|
1663
1616
|
if (!Array.isArray(attrs)) attrs = [attrs]
|
|
1664
1617
|
let chunked = chunkArray(attrs, values.length)
|
|
1665
|
-
chunked = chunked.filter(
|
|
1618
|
+
chunked = chunked.filter(val => {
|
|
1666
1619
|
for (let i = 0; i < val.length; ++i) {
|
|
1667
1620
|
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)
|
|
1621
|
+
const _expected = Number.isNaN(values[i]) || typeof values[i] === 'string' ? values[i] : Number.parseInt(values[i], 10)
|
|
1670
1622
|
// the attribute could be a boolean
|
|
1671
1623
|
if (typeof _actual === 'boolean') return _actual === _expected
|
|
1672
1624
|
if (_actual !== _expected) return false
|
|
1673
1625
|
}
|
|
1674
1626
|
return true
|
|
1675
1627
|
})
|
|
1676
|
-
return assert.ok(
|
|
1677
|
-
chunked.length === elemAmount,
|
|
1678
|
-
`expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`,
|
|
1679
|
-
)
|
|
1628
|
+
return assert.ok(chunked.length === elemAmount, `expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`)
|
|
1680
1629
|
}
|
|
1681
1630
|
|
|
1682
1631
|
/**
|
|
@@ -1685,9 +1634,9 @@ class WebDriver extends Helper {
|
|
|
1685
1634
|
async grabNumberOfVisibleElements(locator) {
|
|
1686
1635
|
const res = await this._locate(locator)
|
|
1687
1636
|
|
|
1688
|
-
let selected = await forEachAsync(res, async
|
|
1637
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
1689
1638
|
if (!Array.isArray(selected)) selected = [selected]
|
|
1690
|
-
selected = selected.filter(
|
|
1639
|
+
selected = selected.filter(val => val === true)
|
|
1691
1640
|
return selected.length
|
|
1692
1641
|
}
|
|
1693
1642
|
|
|
@@ -1841,18 +1790,25 @@ class WebDriver extends Helper {
|
|
|
1841
1790
|
|
|
1842
1791
|
if (browser) {
|
|
1843
1792
|
this.debug(`Screenshot of ${sessionName} session has been saved to ${outputFile}`)
|
|
1844
|
-
|
|
1793
|
+
await browser.saveScreenshot(outputFile)
|
|
1845
1794
|
}
|
|
1846
1795
|
}
|
|
1847
1796
|
}
|
|
1848
1797
|
|
|
1849
1798
|
if (!fullPage) {
|
|
1850
1799
|
this.debug(`Screenshot has been saved to ${outputFile}`)
|
|
1851
|
-
|
|
1800
|
+
await this.browser.saveScreenshot(outputFile)
|
|
1852
1801
|
}
|
|
1853
1802
|
|
|
1854
1803
|
const originalWindowSize = await this.browser.getWindowSize()
|
|
1855
1804
|
|
|
1805
|
+
// this case running on device, so we could not set the windowSize
|
|
1806
|
+
if (this.browser.isMobile) {
|
|
1807
|
+
this.debug(`Screenshot has been saved to ${outputFile}, size: ${originalWindowSize.width}x${originalWindowSize.height}`)
|
|
1808
|
+
const buffer = await this.browser.saveScreenshot(outputFile)
|
|
1809
|
+
return buffer
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1856
1812
|
let { width, height } = await this.browser
|
|
1857
1813
|
.execute(function () {
|
|
1858
1814
|
return {
|
|
@@ -1860,7 +1816,7 @@ class WebDriver extends Helper {
|
|
|
1860
1816
|
width: document.body.scrollWidth,
|
|
1861
1817
|
}
|
|
1862
1818
|
})
|
|
1863
|
-
.then(
|
|
1819
|
+
.then(res => res)
|
|
1864
1820
|
|
|
1865
1821
|
if (height < 100) height = 500 // errors for very small height
|
|
1866
1822
|
|
|
@@ -1928,7 +1884,7 @@ class WebDriver extends Helper {
|
|
|
1928
1884
|
|
|
1929
1885
|
return promiseRetry(
|
|
1930
1886
|
async (retry, number) => {
|
|
1931
|
-
const _grabCookie = async
|
|
1887
|
+
const _grabCookie = async name => {
|
|
1932
1888
|
const cookie = await this.browser.getCookies([name])
|
|
1933
1889
|
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`)
|
|
1934
1890
|
}
|
|
@@ -1952,11 +1908,10 @@ class WebDriver extends Helper {
|
|
|
1952
1908
|
* libraries](http://jster.net/category/windows-modals-popups).
|
|
1953
1909
|
*/
|
|
1954
1910
|
async acceptPopup() {
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
})
|
|
1911
|
+
const text = await this.browser.getAlertText()
|
|
1912
|
+
if (text) {
|
|
1913
|
+
return await this.browser.acceptAlert()
|
|
1914
|
+
}
|
|
1960
1915
|
}
|
|
1961
1916
|
|
|
1962
1917
|
/**
|
|
@@ -1964,11 +1919,10 @@ class WebDriver extends Helper {
|
|
|
1964
1919
|
*
|
|
1965
1920
|
*/
|
|
1966
1921
|
async cancelPopup() {
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
})
|
|
1922
|
+
const text = await this.browser.getAlertText()
|
|
1923
|
+
if (text) {
|
|
1924
|
+
return await this.browser.dismissAlert()
|
|
1925
|
+
}
|
|
1972
1926
|
}
|
|
1973
1927
|
|
|
1974
1928
|
/**
|
|
@@ -1978,7 +1932,7 @@ class WebDriver extends Helper {
|
|
|
1978
1932
|
* @param {string} text value to check.
|
|
1979
1933
|
*/
|
|
1980
1934
|
async seeInPopup(text) {
|
|
1981
|
-
return this.browser.getAlertText().then(
|
|
1935
|
+
return await this.browser.getAlertText().then(res => {
|
|
1982
1936
|
if (res === null) {
|
|
1983
1937
|
throw new Error('Popup is not opened')
|
|
1984
1938
|
}
|
|
@@ -2259,9 +2213,9 @@ class WebDriver extends Helper {
|
|
|
2259
2213
|
async closeOtherTabs() {
|
|
2260
2214
|
const handles = await this.browser.getWindowHandles()
|
|
2261
2215
|
const currentHandle = await this.browser.getWindowHandle()
|
|
2262
|
-
const otherHandles = handles.filter(
|
|
2216
|
+
const otherHandles = handles.filter(handle => handle !== currentHandle)
|
|
2263
2217
|
|
|
2264
|
-
await forEachAsync(otherHandles, async
|
|
2218
|
+
await forEachAsync(otherHandles, async handle => {
|
|
2265
2219
|
await this.browser.switchToWindow(handle)
|
|
2266
2220
|
await this.browser.closeWindow()
|
|
2267
2221
|
})
|
|
@@ -2272,7 +2226,7 @@ class WebDriver extends Helper {
|
|
|
2272
2226
|
* {{> wait }}
|
|
2273
2227
|
*/
|
|
2274
2228
|
async wait(sec) {
|
|
2275
|
-
return new Promise(
|
|
2229
|
+
return new Promise(resolve => {
|
|
2276
2230
|
setTimeout(resolve, sec * 1000)
|
|
2277
2231
|
})
|
|
2278
2232
|
}
|
|
@@ -2289,9 +2243,9 @@ class WebDriver extends Helper {
|
|
|
2289
2243
|
if (!res || res.length === 0) {
|
|
2290
2244
|
return false
|
|
2291
2245
|
}
|
|
2292
|
-
const selected = await forEachAsync(res, async
|
|
2246
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementEnabled(getElementId(el)))
|
|
2293
2247
|
if (Array.isArray(selected)) {
|
|
2294
|
-
return selected.filter(
|
|
2248
|
+
return selected.filter(val => val === true).length > 0
|
|
2295
2249
|
}
|
|
2296
2250
|
return selected
|
|
2297
2251
|
},
|
|
@@ -2346,14 +2300,14 @@ class WebDriver extends Helper {
|
|
|
2346
2300
|
return client
|
|
2347
2301
|
.waitUntil(
|
|
2348
2302
|
function () {
|
|
2349
|
-
return this.getUrl().then(
|
|
2303
|
+
return this.getUrl().then(res => {
|
|
2350
2304
|
currUrl = decodeUrl(res)
|
|
2351
2305
|
return currUrl.indexOf(urlPart) > -1
|
|
2352
2306
|
})
|
|
2353
2307
|
},
|
|
2354
2308
|
{ timeout: aSec * 1000 },
|
|
2355
2309
|
)
|
|
2356
|
-
.catch(
|
|
2310
|
+
.catch(e => {
|
|
2357
2311
|
if (e.message.indexOf('timeout')) {
|
|
2358
2312
|
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
|
|
2359
2313
|
}
|
|
@@ -2373,12 +2327,12 @@ class WebDriver extends Helper {
|
|
|
2373
2327
|
let currUrl = ''
|
|
2374
2328
|
return this.browser
|
|
2375
2329
|
.waitUntil(function () {
|
|
2376
|
-
return this.getUrl().then(
|
|
2330
|
+
return this.getUrl().then(res => {
|
|
2377
2331
|
currUrl = decodeUrl(res)
|
|
2378
2332
|
return currUrl === urlPart
|
|
2379
2333
|
})
|
|
2380
2334
|
}, aSec * 1000)
|
|
2381
|
-
.catch(
|
|
2335
|
+
.catch(e => {
|
|
2382
2336
|
if (e.message.indexOf('timeout')) {
|
|
2383
2337
|
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
|
|
2384
2338
|
}
|
|
@@ -2398,9 +2352,9 @@ class WebDriver extends Helper {
|
|
|
2398
2352
|
async () => {
|
|
2399
2353
|
const res = await this.$$(withStrictLocator.call(this, _context))
|
|
2400
2354
|
if (!res || res.length === 0) return false
|
|
2401
|
-
const selected = await forEachAsync(res, async
|
|
2355
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)))
|
|
2402
2356
|
if (Array.isArray(selected)) {
|
|
2403
|
-
return selected.filter(
|
|
2357
|
+
return selected.filter(part => part.indexOf(text) >= 0).length > 0
|
|
2404
2358
|
}
|
|
2405
2359
|
return selected.indexOf(text) >= 0
|
|
2406
2360
|
},
|
|
@@ -2422,9 +2376,9 @@ class WebDriver extends Helper {
|
|
|
2422
2376
|
async () => {
|
|
2423
2377
|
const res = await findFields.call(this, field)
|
|
2424
2378
|
if (!res || res.length === 0) return false
|
|
2425
|
-
const selected = await forEachAsync(res, async
|
|
2379
|
+
const selected = await forEachAsync(res, async el => el.getValue())
|
|
2426
2380
|
if (Array.isArray(selected)) {
|
|
2427
|
-
return selected.filter(
|
|
2381
|
+
return selected.filter(part => part.indexOf(value) >= 0).length > 0
|
|
2428
2382
|
}
|
|
2429
2383
|
return selected.indexOf(value) >= 0
|
|
2430
2384
|
},
|
|
@@ -2446,9 +2400,9 @@ class WebDriver extends Helper {
|
|
|
2446
2400
|
async () => {
|
|
2447
2401
|
const res = await this._res(locator)
|
|
2448
2402
|
if (!res || res.length === 0) return false
|
|
2449
|
-
const selected = await forEachAsync(res, async
|
|
2403
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2450
2404
|
if (Array.isArray(selected)) {
|
|
2451
|
-
return selected.filter(
|
|
2405
|
+
return selected.filter(val => val === true).length > 0
|
|
2452
2406
|
}
|
|
2453
2407
|
return selected
|
|
2454
2408
|
},
|
|
@@ -2469,10 +2423,10 @@ class WebDriver extends Helper {
|
|
|
2469
2423
|
async () => {
|
|
2470
2424
|
const res = await this._res(locator)
|
|
2471
2425
|
if (!res || res.length === 0) return false
|
|
2472
|
-
let selected = await forEachAsync(res, async
|
|
2426
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2473
2427
|
|
|
2474
2428
|
if (!Array.isArray(selected)) selected = [selected]
|
|
2475
|
-
selected = selected.filter(
|
|
2429
|
+
selected = selected.filter(val => val === true)
|
|
2476
2430
|
return selected.length === num
|
|
2477
2431
|
},
|
|
2478
2432
|
{
|
|
@@ -2492,7 +2446,7 @@ class WebDriver extends Helper {
|
|
|
2492
2446
|
async () => {
|
|
2493
2447
|
const res = await this._res(locator)
|
|
2494
2448
|
if (!res || res.length === 0) return true
|
|
2495
|
-
const selected = await forEachAsync(res, async
|
|
2449
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed())
|
|
2496
2450
|
return !selected.length
|
|
2497
2451
|
},
|
|
2498
2452
|
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still visible after ${aSec} sec` },
|
|
@@ -2568,17 +2522,14 @@ class WebDriver extends Helper {
|
|
|
2568
2522
|
*/
|
|
2569
2523
|
async switchTo(locator) {
|
|
2570
2524
|
this.browser.isInsideFrame = true
|
|
2571
|
-
if (Number.isInteger(locator)) {
|
|
2572
|
-
return this.browser.switchToFrame(locator)
|
|
2573
|
-
}
|
|
2574
2525
|
if (!locator) {
|
|
2575
|
-
return this.browser.
|
|
2526
|
+
return this.browser.switchFrame(null)
|
|
2576
2527
|
}
|
|
2577
2528
|
|
|
2578
2529
|
let res = await this._locate(locator, true)
|
|
2579
2530
|
assertElementExists(res, locator)
|
|
2580
2531
|
res = usingFirstElement(res)
|
|
2581
|
-
return this.browser.
|
|
2532
|
+
return this.browser.switchFrame(res)
|
|
2582
2533
|
}
|
|
2583
2534
|
|
|
2584
2535
|
/**
|
|
@@ -2591,7 +2542,7 @@ class WebDriver extends Helper {
|
|
|
2591
2542
|
|
|
2592
2543
|
await this.browser.waitUntil(
|
|
2593
2544
|
async () => {
|
|
2594
|
-
await this.browser.getWindowHandles().then(
|
|
2545
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2595
2546
|
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
2596
2547
|
target = handles[handles.indexOf(current) + num]
|
|
2597
2548
|
}
|
|
@@ -2613,7 +2564,7 @@ class WebDriver extends Helper {
|
|
|
2613
2564
|
|
|
2614
2565
|
await this.browser.waitUntil(
|
|
2615
2566
|
async () => {
|
|
2616
|
-
await this.browser.getWindowHandles().then(
|
|
2567
|
+
await this.browser.getWindowHandles().then(handles => {
|
|
2617
2568
|
if (handles.indexOf(current) - num > -1) {
|
|
2618
2569
|
target = handles[handles.indexOf(current) - num]
|
|
2619
2570
|
}
|
|
@@ -2683,10 +2634,7 @@ class WebDriver extends Helper {
|
|
|
2683
2634
|
return client.execute(function () {
|
|
2684
2635
|
const body = document.body
|
|
2685
2636
|
const html = document.documentElement
|
|
2686
|
-
window.scrollTo(
|
|
2687
|
-
0,
|
|
2688
|
-
Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
|
|
2689
|
-
)
|
|
2637
|
+
window.scrollTo(0, Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight))
|
|
2690
2638
|
})
|
|
2691
2639
|
}
|
|
2692
2640
|
|
|
@@ -2760,10 +2708,17 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
2760
2708
|
const smartWaitEnabled = assertType === 'assert'
|
|
2761
2709
|
const res = await this._locate(withStrictLocator(context), smartWaitEnabled)
|
|
2762
2710
|
assertElementExists(res, context)
|
|
2763
|
-
|
|
2711
|
+
let selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)))
|
|
2712
|
+
|
|
2713
|
+
// apply ignoreCase option
|
|
2714
|
+
if (store?.currentStep?.opts?.ignoreCase === true) {
|
|
2715
|
+
text = text.toLowerCase()
|
|
2716
|
+
selected = selected.map(elText => elText.toLowerCase())
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2764
2719
|
if (strict) {
|
|
2765
2720
|
if (Array.isArray(selected) && selected.length !== 0) {
|
|
2766
|
-
return selected.map(
|
|
2721
|
+
return selected.map(elText => equals(description)[assertType](text, elText))
|
|
2767
2722
|
}
|
|
2768
2723
|
return equals(description)[assertType](text, selected)
|
|
2769
2724
|
}
|
|
@@ -2791,7 +2746,7 @@ async function forEachAsync(array, callback, options = { expandArrayResults: tru
|
|
|
2791
2746
|
const res = await callback(inputArray[index], index, inputArray)
|
|
2792
2747
|
|
|
2793
2748
|
if (Array.isArray(res) && expandArrayResults) {
|
|
2794
|
-
res.forEach(
|
|
2749
|
+
res.forEach(val => values.push(val))
|
|
2795
2750
|
} else if (res) {
|
|
2796
2751
|
values.push(res)
|
|
2797
2752
|
}
|
|
@@ -2877,11 +2832,11 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2877
2832
|
const elem = usingFirstElement(res)
|
|
2878
2833
|
const elemId = getElementId(elem)
|
|
2879
2834
|
|
|
2880
|
-
const proceedMultiple = async
|
|
2835
|
+
const proceedMultiple = async fields => {
|
|
2881
2836
|
const fieldResults = toArray(
|
|
2882
|
-
await forEachAsync(fields, async
|
|
2837
|
+
await forEachAsync(fields, async el => {
|
|
2883
2838
|
const elementId = getElementId(el)
|
|
2884
|
-
return this.browser.
|
|
2839
|
+
return this.browser.getElementAttribute(elementId, 'value')
|
|
2885
2840
|
}),
|
|
2886
2841
|
)
|
|
2887
2842
|
|
|
@@ -2890,27 +2845,24 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2890
2845
|
} else {
|
|
2891
2846
|
// Assert that results were found so the forEach assert does not silently pass
|
|
2892
2847
|
equals(`no. of items matching > 0: ${field}`)[assertType](true, !!fieldResults.length)
|
|
2893
|
-
fieldResults.forEach(
|
|
2848
|
+
fieldResults.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val))
|
|
2894
2849
|
}
|
|
2895
2850
|
}
|
|
2896
2851
|
|
|
2897
|
-
const proceedSingle =
|
|
2898
|
-
el.getValue().then(
|
|
2852
|
+
const proceedSingle = el =>
|
|
2853
|
+
el.getValue().then(res => {
|
|
2899
2854
|
if (res === null) {
|
|
2900
2855
|
throw new Error(`Element ${el.selector} has no value attribute`)
|
|
2901
2856
|
}
|
|
2902
2857
|
stringIncludes(`fields by ${field}`)[assertType](value, res)
|
|
2903
2858
|
})
|
|
2904
2859
|
|
|
2905
|
-
const filterBySelected = async (elements
|
|
2906
|
-
filterAsync(elements, async (el) => this.browser.isElementSelected(getElementId(el)))
|
|
2860
|
+
const filterBySelected = async elements => filterAsync(elements, async el => this.browser.isElementSelected(getElementId(el)))
|
|
2907
2861
|
|
|
2908
2862
|
const filterSelectedByValue = async (elements, value) => {
|
|
2909
|
-
return filterAsync(elements, async
|
|
2863
|
+
return filterAsync(elements, async el => {
|
|
2910
2864
|
const elementId = getElementId(el)
|
|
2911
|
-
const currentValue = this.browser.
|
|
2912
|
-
? await el.getValue()
|
|
2913
|
-
: await this.browser.getElementAttribute(elementId, 'value')
|
|
2865
|
+
const currentValue = await this.browser.getElementAttribute(elementId, 'value')
|
|
2914
2866
|
const isSelected = await this.browser.isElementSelected(elementId)
|
|
2915
2867
|
return currentValue === value && isSelected
|
|
2916
2868
|
})
|
|
@@ -2918,7 +2870,13 @@ async function proceedSeeField(assertType, field, value) {
|
|
|
2918
2870
|
|
|
2919
2871
|
const tag = await elem.getTagName()
|
|
2920
2872
|
if (tag === 'select') {
|
|
2921
|
-
|
|
2873
|
+
let subOptions
|
|
2874
|
+
|
|
2875
|
+
try {
|
|
2876
|
+
subOptions = await this.browser.findElementsFromElement(elemId, 'css', 'option')
|
|
2877
|
+
} catch (e) {
|
|
2878
|
+
subOptions = await this.browser.findElementsFromElement(elemId, 'xpath', 'option')
|
|
2879
|
+
}
|
|
2922
2880
|
|
|
2923
2881
|
if (value === '') {
|
|
2924
2882
|
// Don't filter by value
|
|
@@ -2959,7 +2917,7 @@ async function proceedSeeCheckbox(assertType, field) {
|
|
|
2959
2917
|
const res = await findFields.call(this, field)
|
|
2960
2918
|
assertElementExists(res, field, 'Field')
|
|
2961
2919
|
|
|
2962
|
-
const selected = await forEachAsync(res, async
|
|
2920
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementSelected(getElementId(el)))
|
|
2963
2921
|
return truth(`checkable field "${field}"`, 'to be checked')[assertType](selected)
|
|
2964
2922
|
}
|
|
2965
2923
|
|
|
@@ -3160,7 +3118,7 @@ function getNormalizedKey(key) {
|
|
|
3160
3118
|
return convertKeyToRawKey(normalizedKey)
|
|
3161
3119
|
}
|
|
3162
3120
|
|
|
3163
|
-
const unicodeModifierKeys = modifierKeys.map(
|
|
3121
|
+
const unicodeModifierKeys = modifierKeys.map(k => convertKeyToRawKey(k))
|
|
3164
3122
|
function isModifierKey(key) {
|
|
3165
3123
|
return unicodeModifierKeys.includes(key)
|
|
3166
3124
|
}
|
|
@@ -3173,9 +3131,9 @@ function highlightActiveElement(element) {
|
|
|
3173
3131
|
|
|
3174
3132
|
function prepareLocateFn(context) {
|
|
3175
3133
|
if (!context) return this._locate.bind(this)
|
|
3176
|
-
return
|
|
3134
|
+
return l => {
|
|
3177
3135
|
l = new Locator(l, 'css')
|
|
3178
|
-
return this._locate(context, true).then(async
|
|
3136
|
+
return this._locate(context, true).then(async res => {
|
|
3179
3137
|
assertElementExists(res, context, 'Context element')
|
|
3180
3138
|
if (l.react) {
|
|
3181
3139
|
return res[0].react$$(l.react, l.props || undefined)
|
|
@@ -3185,4 +3143,8 @@ function prepareLocateFn(context) {
|
|
|
3185
3143
|
}
|
|
3186
3144
|
}
|
|
3187
3145
|
|
|
3146
|
+
function logEvents(event) {
|
|
3147
|
+
browserLogs.push(event.text) // add log message to the array
|
|
3148
|
+
}
|
|
3149
|
+
|
|
3188
3150
|
module.exports = WebDriver
|