codeceptjs 3.6.6 → 4.0.0-beta.1
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/bin/codecept.js +81 -84
- package/lib/actor.js +13 -13
- package/lib/ai.js +13 -10
- package/lib/assert/empty.js +21 -20
- package/lib/assert/equal.js +39 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +47 -46
- package/lib/assert/throws.js +11 -13
- package/lib/assert/truth.js +22 -19
- package/lib/assert.js +2 -4
- package/lib/cli.js +49 -57
- package/lib/codecept.js +155 -142
- package/lib/colorUtils.js +3 -3
- package/lib/command/configMigrate.js +52 -58
- package/lib/command/definitions.js +89 -88
- package/lib/command/dryRun.js +68 -71
- package/lib/command/generate.js +188 -197
- package/lib/command/gherkin/init.js +16 -27
- package/lib/command/gherkin/snippets.js +20 -20
- package/lib/command/gherkin/steps.js +8 -8
- package/lib/command/info.js +38 -40
- package/lib/command/init.js +288 -290
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +3 -3
- package/lib/command/run-multiple/run.js +2 -6
- package/lib/command/run-multiple.js +93 -113
- package/lib/command/run-rerun.js +25 -20
- package/lib/command/run-workers.js +66 -64
- package/lib/command/run.js +29 -26
- package/lib/command/utils.js +65 -80
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +9 -10
- package/lib/container.js +48 -40
- package/lib/data/context.js +59 -60
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +20 -26
- package/lib/dirname.js +5 -0
- package/lib/event.js +167 -163
- package/lib/heal.js +17 -13
- package/lib/helper/AI.js +41 -130
- package/lib/helper/ApiDataFactory.js +69 -73
- package/lib/helper/Appium.js +381 -412
- package/lib/helper/Expect.js +425 -0
- package/lib/helper/ExpectHelper.js +48 -40
- package/lib/helper/FileSystem.js +79 -80
- package/lib/helper/GraphQL.js +43 -44
- package/lib/helper/GraphQLDataFactory.js +50 -50
- package/lib/helper/JSONResponse.js +62 -65
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +14 -12
- package/lib/helper/Nightmare.js +566 -662
- package/lib/helper/Playwright.js +1216 -1361
- package/lib/helper/Protractor.js +627 -663
- package/lib/helper/Puppeteer.js +1128 -1231
- package/lib/helper/REST.js +68 -159
- package/lib/helper/SoftExpectHelper.js +2 -2
- package/lib/helper/TestCafe.js +484 -490
- package/lib/helper/WebDriver.js +1156 -1297
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/errors/ElementAssertion.js +2 -2
- package/lib/helper/errors/ElementNotFound.js +2 -2
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
- package/lib/helper/extras/Console.js +1 -1
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
- package/lib/helper/extras/PlaywrightRestartOpts.js +18 -21
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +3 -3
- package/lib/helper/network/actions.js +7 -14
- package/lib/helper/network/utils.js +2 -3
- package/lib/helper/scripts/blurElement.js +1 -1
- package/lib/helper/scripts/focusElement.js +1 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/helper/scripts/isElementClickable.js +1 -1
- package/lib/helper/testcafe/testControllerHolder.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +7 -6
- package/lib/helper.js +3 -1
- package/lib/history.js +5 -6
- package/lib/hooks.js +6 -6
- package/lib/html.js +7 -7
- package/lib/index.js +41 -25
- package/lib/interfaces/bdd.js +64 -47
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +118 -124
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -24
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +30 -32
- package/lib/listener/steps.js +53 -50
- package/lib/listener/timeout.js +54 -54
- package/lib/locator.js +10 -6
- package/lib/mochaFactory.js +15 -18
- package/lib/output.js +10 -6
- package/lib/parser.js +12 -15
- package/lib/pause.js +33 -40
- package/lib/plugin/allure.js +15 -15
- package/lib/plugin/autoDelay.js +37 -29
- package/lib/plugin/autoLogin.js +65 -70
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +67 -115
- package/lib/plugin/customLocator.js +20 -21
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +38 -38
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +108 -67
- package/lib/plugin/pauseOnFail.js +11 -11
- package/lib/plugin/retryFailedStep.js +39 -32
- package/lib/plugin/retryTo.js +40 -46
- package/lib/plugin/screenshotOnFail.js +87 -109
- package/lib/plugin/selenoid.js +118 -131
- package/lib/plugin/standardActingHelpers.js +8 -2
- package/lib/plugin/stepByStepReport.js +91 -110
- package/lib/plugin/stepTimeout.js +23 -24
- package/lib/plugin/subtitles.js +35 -34
- package/lib/plugin/tryTo.js +30 -40
- package/lib/plugin/wdio.js +75 -78
- package/lib/recorder.js +17 -14
- package/lib/rerun.js +10 -11
- package/lib/scenario.js +23 -25
- package/lib/secret.js +2 -4
- package/lib/session.js +10 -10
- package/lib/step.js +9 -12
- package/lib/store.js +3 -2
- package/lib/transform.js +1 -1
- package/lib/translation.js +8 -7
- package/lib/ui.js +14 -12
- package/lib/utils.js +72 -70
- package/lib/within.js +10 -10
- package/lib/workerStorage.js +25 -27
- package/lib/workers.js +32 -29
- package/package.json +53 -51
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +13 -9
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/index.d.ts +65 -415
- package/typings/promiseBasedTypes.d.ts +32 -0
- package/typings/types.d.ts +32 -0
package/lib/helper/WebDriver.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const { truth } = require('../assert/truth')
|
|
13
|
-
const {
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import Helper from '@codeceptjs/helper';
|
|
4
|
+
import promiseRetry from 'promise-retry';
|
|
5
|
+
import { includes as stringIncludes } from '../assert/include.js';
|
|
6
|
+
import { urlEquals, equals } from '../assert/equal.js';
|
|
7
|
+
import { debug } from '../output.js';
|
|
8
|
+
import { empty } from '../assert/empty.js';
|
|
9
|
+
import { truth } from '../assert/truth';
|
|
10
|
+
|
|
11
|
+
import {
|
|
14
12
|
xpathLocator,
|
|
15
13
|
fileExists,
|
|
16
14
|
decodeUrl,
|
|
@@ -19,30 +17,32 @@ const {
|
|
|
19
17
|
screenshotOutputFolder,
|
|
20
18
|
getNormalizedKeyAttributeValue,
|
|
21
19
|
modifierKeys,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
|
|
21
|
+
} from '../utils.js';
|
|
22
|
+
|
|
23
|
+
import { isColorProperty, convertColorToRGBA } from '../colorUtils';
|
|
24
|
+
import ElementNotFound from './errors/ElementNotFound.js';
|
|
25
|
+
import ConnectionRefused from './errors/ConnectionRefused.js';
|
|
26
|
+
import Locator from '../locator.js';
|
|
27
|
+
import { highlightElement } from './scripts/highlightElement';
|
|
28
|
+
import { focusElement } from './scripts/focusElement';
|
|
29
|
+
import { blurElement } from './scripts/blurElement';
|
|
30
|
+
|
|
31
|
+
import {
|
|
31
32
|
dontSeeElementError,
|
|
32
33
|
seeElementError,
|
|
33
34
|
seeElementInDOMError,
|
|
34
35
|
dontSeeElementInDOMError,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
seeTraffic,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const webRoot = 'body'
|
|
36
|
+
} from './errors/ElementAssertion';
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics,
|
|
40
|
+
} from './network/actions';
|
|
41
|
+
|
|
42
|
+
let webdriverio;
|
|
43
|
+
|
|
44
|
+
const SHADOW = 'shadow';
|
|
45
|
+
const webRoot = 'body';
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* ## Configuration
|
|
@@ -74,7 +74,7 @@ const webRoot = 'body'
|
|
|
74
74
|
* @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
75
|
* @prop {boolean} [devtoolsProtocol=false] - enable devtools protocol. Default: false. More info: https://webdriver.io/docs/automationProtocols/#devtools-protocol.
|
|
76
76
|
*/
|
|
77
|
-
const config = {}
|
|
77
|
+
const config = {};
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* WebDriver helper which wraps [webdriverio](http://webdriver.io/) library to
|
|
@@ -445,34 +445,34 @@ const config = {}
|
|
|
445
445
|
*/
|
|
446
446
|
class WebDriver extends Helper {
|
|
447
447
|
constructor(config) {
|
|
448
|
-
super(config)
|
|
449
|
-
webdriverio = require('webdriverio')
|
|
448
|
+
super(config);
|
|
449
|
+
webdriverio = require('webdriverio');
|
|
450
450
|
|
|
451
451
|
// set defaults
|
|
452
|
-
this.root = webRoot
|
|
453
|
-
this.isWeb = true
|
|
454
|
-
this.isRunning = false
|
|
455
|
-
this.sessionWindows = {}
|
|
456
|
-
this.activeSessionName = ''
|
|
457
|
-
this.customLocatorStrategies = config.customLocatorStrategies
|
|
452
|
+
this.root = webRoot;
|
|
453
|
+
this.isWeb = true;
|
|
454
|
+
this.isRunning = false;
|
|
455
|
+
this.sessionWindows = {};
|
|
456
|
+
this.activeSessionName = '';
|
|
457
|
+
this.customLocatorStrategies = config.customLocatorStrategies;
|
|
458
458
|
|
|
459
459
|
// for network stuff
|
|
460
|
-
this.requests = []
|
|
461
|
-
this.recording = false
|
|
462
|
-
this.recordedAtLeastOnce = false
|
|
460
|
+
this.requests = [];
|
|
461
|
+
this.recording = false;
|
|
462
|
+
this.recordedAtLeastOnce = false;
|
|
463
463
|
|
|
464
|
-
this._setConfig(config)
|
|
464
|
+
this._setConfig(config);
|
|
465
465
|
|
|
466
466
|
Locator.addFilter((locator, result) => {
|
|
467
467
|
if (typeof locator === 'string' && locator.indexOf('~') === 0) {
|
|
468
468
|
// accessibility locator
|
|
469
469
|
if (this.isWeb) {
|
|
470
|
-
result.value = `[aria-label="${locator.slice(1)}"]
|
|
471
|
-
result.type = 'css'
|
|
472
|
-
result.output = `aria-label=${locator.slice(1)}
|
|
470
|
+
result.value = `[aria-label="${locator.slice(1)}"]`;
|
|
471
|
+
result.type = 'css';
|
|
472
|
+
result.output = `aria-label=${locator.slice(1)}`;
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
|
-
})
|
|
475
|
+
});
|
|
476
476
|
}
|
|
477
477
|
|
|
478
478
|
_validateConfig(config) {
|
|
@@ -492,41 +492,41 @@ class WebDriver extends Helper {
|
|
|
492
492
|
keepBrowserState: false,
|
|
493
493
|
deprecationWarnings: false,
|
|
494
494
|
highlightElement: false,
|
|
495
|
-
}
|
|
495
|
+
};
|
|
496
496
|
|
|
497
497
|
// override defaults with config
|
|
498
|
-
config = Object.assign(defaults, config)
|
|
498
|
+
config = Object.assign(defaults, config);
|
|
499
499
|
|
|
500
500
|
if (config.host) {
|
|
501
501
|
// webdriverio spec
|
|
502
|
-
config.hostname = config.host
|
|
503
|
-
config.path = config.path ? config.path : '/wd/hub'
|
|
502
|
+
config.hostname = config.host;
|
|
503
|
+
config.path = config.path ? config.path : '/wd/hub';
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
-
config.baseUrl = config.url || config.baseUrl
|
|
506
|
+
config.baseUrl = config.url || config.baseUrl;
|
|
507
507
|
if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
|
|
508
|
-
config.capabilities = config.desiredCapabilities
|
|
508
|
+
config.capabilities = config.desiredCapabilities;
|
|
509
509
|
}
|
|
510
|
-
config.capabilities.browserName = config.browser || config.capabilities.browserName
|
|
511
|
-
config.capabilities.browserVersion = config.browserVersion || config.capabilities.browserVersion
|
|
510
|
+
config.capabilities.browserName = config.browser || config.capabilities.browserName;
|
|
511
|
+
config.capabilities.browserVersion = config.browserVersion || config.capabilities.browserVersion;
|
|
512
512
|
if (config.capabilities.chromeOptions) {
|
|
513
|
-
config.capabilities['goog:chromeOptions'] = config.capabilities.chromeOptions
|
|
514
|
-
delete config.capabilities.chromeOptions
|
|
513
|
+
config.capabilities['goog:chromeOptions'] = config.capabilities.chromeOptions;
|
|
514
|
+
delete config.capabilities.chromeOptions;
|
|
515
515
|
}
|
|
516
516
|
if (config.capabilities.firefoxOptions) {
|
|
517
|
-
config.capabilities['moz:firefoxOptions'] = config.capabilities.firefoxOptions
|
|
518
|
-
delete config.capabilities.firefoxOptions
|
|
517
|
+
config.capabilities['moz:firefoxOptions'] = config.capabilities.firefoxOptions;
|
|
518
|
+
delete config.capabilities.firefoxOptions;
|
|
519
519
|
}
|
|
520
520
|
if (config.capabilities.ieOptions) {
|
|
521
|
-
config.capabilities['se:ieOptions'] = config.capabilities.ieOptions
|
|
522
|
-
delete config.capabilities.ieOptions
|
|
521
|
+
config.capabilities['se:ieOptions'] = config.capabilities.ieOptions;
|
|
522
|
+
delete config.capabilities.ieOptions;
|
|
523
523
|
}
|
|
524
524
|
if (config.capabilities.selenoidOptions) {
|
|
525
|
-
config.capabilities['selenoid:options'] = config.capabilities.selenoidOptions
|
|
526
|
-
delete config.capabilities.selenoidOptions
|
|
525
|
+
config.capabilities['selenoid:options'] = config.capabilities.selenoidOptions;
|
|
526
|
+
delete config.capabilities.selenoidOptions;
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
-
config.waitForTimeoutInSeconds = config.waitForTimeout / 1000 // convert to seconds
|
|
529
|
+
config.waitForTimeoutInSeconds = config.waitForTimeout / 1000; // convert to seconds
|
|
530
530
|
|
|
531
531
|
if (!config.capabilities.platformName && (!config.url || !config.browser)) {
|
|
532
532
|
throw new Error(`
|
|
@@ -540,201 +540,196 @@ class WebDriver extends Helper {
|
|
|
540
540
|
}
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
|
-
`)
|
|
543
|
+
`);
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
return config
|
|
546
|
+
return config;
|
|
547
547
|
}
|
|
548
548
|
|
|
549
549
|
static _checkRequirements() {
|
|
550
550
|
try {
|
|
551
|
-
require('webdriverio')
|
|
551
|
+
require('webdriverio');
|
|
552
552
|
} catch (e) {
|
|
553
|
-
return ['webdriverio@^6.12.1']
|
|
553
|
+
return ['webdriverio@^6.12.1'];
|
|
554
554
|
}
|
|
555
555
|
}
|
|
556
556
|
|
|
557
557
|
static _config() {
|
|
558
|
-
return [
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
default: 'chrome',
|
|
568
|
-
},
|
|
569
|
-
]
|
|
558
|
+
return [{
|
|
559
|
+
name: 'url',
|
|
560
|
+
message: 'Base url of site to be tested',
|
|
561
|
+
default: 'http://localhost',
|
|
562
|
+
}, {
|
|
563
|
+
name: 'browser',
|
|
564
|
+
message: 'Browser in which testing will be performed',
|
|
565
|
+
default: 'chrome',
|
|
566
|
+
}];
|
|
570
567
|
}
|
|
571
568
|
|
|
572
569
|
_beforeSuite() {
|
|
573
570
|
if (!this.options.restart && !this.options.manualStart && !this.isRunning) {
|
|
574
|
-
this.debugSection('Session', 'Starting singleton browser session')
|
|
575
|
-
return this._startBrowser()
|
|
571
|
+
this.debugSection('Session', 'Starting singleton browser session');
|
|
572
|
+
return this._startBrowser();
|
|
576
573
|
}
|
|
577
574
|
}
|
|
578
575
|
|
|
579
576
|
_lookupCustomLocator(customStrategy) {
|
|
580
|
-
if (typeof this.customLocatorStrategies !== 'object') {
|
|
581
|
-
return null
|
|
577
|
+
if (typeof (this.customLocatorStrategies) !== 'object') {
|
|
578
|
+
return null;
|
|
582
579
|
}
|
|
583
|
-
const strategy = this.customLocatorStrategies[customStrategy]
|
|
584
|
-
return typeof strategy === 'function' ? strategy : null
|
|
580
|
+
const strategy = this.customLocatorStrategies[customStrategy];
|
|
581
|
+
return typeof (strategy) === 'function' ? strategy : null;
|
|
585
582
|
}
|
|
586
583
|
|
|
587
584
|
_isCustomLocator(locator) {
|
|
588
|
-
const locatorObj = new Locator(locator)
|
|
585
|
+
const locatorObj = new Locator(locator);
|
|
589
586
|
if (locatorObj.isCustom()) {
|
|
590
|
-
const customLocator = this._lookupCustomLocator(locatorObj.type)
|
|
587
|
+
const customLocator = this._lookupCustomLocator(locatorObj.type);
|
|
591
588
|
if (customLocator) {
|
|
592
|
-
return true
|
|
589
|
+
return true;
|
|
593
590
|
}
|
|
594
|
-
throw new Error('Please define "customLocatorStrategies" as an Object and the Locator Strategy as a "function".')
|
|
591
|
+
throw new Error('Please define "customLocatorStrategies" as an Object and the Locator Strategy as a "function".');
|
|
595
592
|
}
|
|
596
|
-
return false
|
|
593
|
+
return false;
|
|
597
594
|
}
|
|
598
595
|
|
|
599
596
|
async _res(locator) {
|
|
600
|
-
const res =
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
return res
|
|
597
|
+
const res = (this._isShadowLocator(locator) || this._isCustomLocator(locator))
|
|
598
|
+
? await this._locate(locator)
|
|
599
|
+
: await this.$$(withStrictLocator(locator));
|
|
600
|
+
return res;
|
|
605
601
|
}
|
|
606
602
|
|
|
607
603
|
async _startBrowser() {
|
|
608
604
|
try {
|
|
609
605
|
if (this.options.multiremote) {
|
|
610
|
-
this.browser = await webdriverio.multiremote(this.options.multiremote)
|
|
606
|
+
this.browser = await webdriverio.multiremote(this.options.multiremote);
|
|
611
607
|
} else {
|
|
612
608
|
// remove non w3c capabilities
|
|
613
|
-
delete this.options.capabilities.protocol
|
|
614
|
-
delete this.options.capabilities.hostname
|
|
615
|
-
delete this.options.capabilities.port
|
|
616
|
-
delete this.options.capabilities.path
|
|
609
|
+
delete this.options.capabilities.protocol;
|
|
610
|
+
delete this.options.capabilities.hostname;
|
|
611
|
+
delete this.options.capabilities.port;
|
|
612
|
+
delete this.options.capabilities.path;
|
|
617
613
|
if (this.options.devtoolsProtocol) {
|
|
618
|
-
if (!['chrome', 'chromium'].includes(this.options.browser.toLowerCase()))
|
|
619
|
-
|
|
620
|
-
this.options.automationProtocol = 'devtools'
|
|
614
|
+
if (!['chrome', 'chromium'].includes(this.options.browser.toLowerCase())) throw Error('The devtools protocol is only working with Chrome or Chromium');
|
|
615
|
+
this.options.automationProtocol = 'devtools';
|
|
621
616
|
}
|
|
622
|
-
this.browser = await webdriverio.remote(this.options)
|
|
617
|
+
this.browser = await webdriverio.remote(this.options);
|
|
623
618
|
}
|
|
624
619
|
} catch (err) {
|
|
625
620
|
if (err.toString().indexOf('ECONNREFUSED')) {
|
|
626
|
-
throw new ConnectionRefused(err)
|
|
621
|
+
throw new ConnectionRefused(err);
|
|
627
622
|
}
|
|
628
|
-
throw err
|
|
623
|
+
throw err;
|
|
629
624
|
}
|
|
630
625
|
|
|
631
|
-
this.isRunning = true
|
|
626
|
+
this.isRunning = true;
|
|
632
627
|
if (this.options.timeouts && this.isWeb) {
|
|
633
|
-
await this.defineTimeout(this.options.timeouts)
|
|
628
|
+
await this.defineTimeout(this.options.timeouts);
|
|
634
629
|
}
|
|
635
630
|
|
|
636
|
-
await this._resizeWindowIfNeeded(this.browser, this.options.windowSize)
|
|
631
|
+
await this._resizeWindowIfNeeded(this.browser, this.options.windowSize);
|
|
637
632
|
|
|
638
|
-
this.$$ = this.browser.$$.bind(this.browser)
|
|
633
|
+
this.$$ = this.browser.$$.bind(this.browser);
|
|
639
634
|
|
|
640
635
|
if (this._isCustomLocatorStrategyDefined()) {
|
|
641
636
|
Object.keys(this.customLocatorStrategies).forEach(async (customLocator) => {
|
|
642
|
-
this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`)
|
|
643
|
-
const locatorFunction = this._lookupCustomLocator(customLocator)
|
|
644
|
-
this.browser.addLocatorStrategy(customLocator, locatorFunction)
|
|
645
|
-
})
|
|
637
|
+
this.debugSection('Weddriver', `adding custom locator strategy: ${customLocator}`);
|
|
638
|
+
const locatorFunction = this._lookupCustomLocator(customLocator);
|
|
639
|
+
this.browser.addLocatorStrategy(customLocator, locatorFunction);
|
|
640
|
+
});
|
|
646
641
|
}
|
|
647
642
|
|
|
648
643
|
if (this.browser.capabilities && this.browser.capabilities.platformName) {
|
|
649
|
-
this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase()
|
|
644
|
+
this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase();
|
|
650
645
|
}
|
|
651
646
|
|
|
652
647
|
if (this.options.automationProtocol) {
|
|
653
|
-
this.puppeteerBrowser = await this.browser.getPuppeteer()
|
|
654
|
-
this.page = (await this.puppeteerBrowser.pages())[0]
|
|
648
|
+
this.puppeteerBrowser = await this.browser.getPuppeteer();
|
|
655
649
|
}
|
|
656
650
|
|
|
657
|
-
return this.browser
|
|
651
|
+
return this.browser;
|
|
658
652
|
}
|
|
659
653
|
|
|
660
654
|
_isCustomLocatorStrategyDefined() {
|
|
661
|
-
return this.customLocatorStrategies && Object.keys(this.customLocatorStrategies).length
|
|
655
|
+
return this.customLocatorStrategies && Object.keys(this.customLocatorStrategies).length;
|
|
662
656
|
}
|
|
663
657
|
|
|
664
658
|
async _stopBrowser() {
|
|
665
|
-
if (this.browser && this.isRunning) await this.browser.deleteSession()
|
|
659
|
+
if (this.browser && this.isRunning) await this.browser.deleteSession();
|
|
666
660
|
}
|
|
667
661
|
|
|
668
662
|
async _before() {
|
|
669
|
-
this.context = this.root
|
|
670
|
-
if (this.options.restart && !this.options.manualStart) return this._startBrowser()
|
|
671
|
-
if (!this.isRunning && !this.options.manualStart) return this._startBrowser()
|
|
672
|
-
if (this.browser) this.$$ = this.browser.$$.bind(this.browser)
|
|
673
|
-
return this.browser
|
|
663
|
+
this.context = this.root;
|
|
664
|
+
if (this.options.restart && !this.options.manualStart) return this._startBrowser();
|
|
665
|
+
if (!this.isRunning && !this.options.manualStart) return this._startBrowser();
|
|
666
|
+
if (this.browser) this.$$ = this.browser.$$.bind(this.browser);
|
|
667
|
+
return this.browser;
|
|
674
668
|
}
|
|
675
669
|
|
|
676
670
|
async _after() {
|
|
677
|
-
if (!this.isRunning) return
|
|
671
|
+
if (!this.isRunning) return;
|
|
678
672
|
if (this.options.restart) {
|
|
679
|
-
this.isRunning = false
|
|
680
|
-
return this.browser.deleteSession()
|
|
673
|
+
this.isRunning = false;
|
|
674
|
+
return this.browser.deleteSession();
|
|
681
675
|
}
|
|
682
|
-
if (this.browser.isInsideFrame) await this.browser.switchToFrame(null)
|
|
676
|
+
if (this.browser.isInsideFrame) await this.browser.switchToFrame(null);
|
|
683
677
|
|
|
684
|
-
if (this.options.keepBrowserState) return
|
|
678
|
+
if (this.options.keepBrowserState) return;
|
|
685
679
|
|
|
686
680
|
if (!this.options.keepCookies && this.options.capabilities.browserName) {
|
|
687
|
-
this.debugSection('Session', 'cleaning cookies and localStorage')
|
|
688
|
-
await this.browser.deleteCookies()
|
|
681
|
+
this.debugSection('Session', 'cleaning cookies and localStorage');
|
|
682
|
+
await this.browser.deleteCookies();
|
|
689
683
|
}
|
|
690
684
|
await this.browser.execute('localStorage.clear();').catch((err) => {
|
|
691
|
-
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
|
|
692
|
-
})
|
|
693
|
-
await this.closeOtherTabs()
|
|
694
|
-
return this.browser
|
|
685
|
+
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
|
|
686
|
+
});
|
|
687
|
+
await this.closeOtherTabs();
|
|
688
|
+
return this.browser;
|
|
695
689
|
}
|
|
696
690
|
|
|
697
|
-
_afterSuite() {
|
|
691
|
+
_afterSuite() {
|
|
692
|
+
}
|
|
698
693
|
|
|
699
694
|
_finishTest() {
|
|
700
|
-
if (!this.options.restart && this.isRunning) return this._stopBrowser()
|
|
695
|
+
if (!this.options.restart && this.isRunning) return this._stopBrowser();
|
|
701
696
|
}
|
|
702
697
|
|
|
703
698
|
_session() {
|
|
704
|
-
const defaultSession = this.browser
|
|
699
|
+
const defaultSession = this.browser;
|
|
705
700
|
return {
|
|
706
701
|
start: async (sessionName, opts) => {
|
|
707
702
|
// opts.disableScreenshots = true; // screenshots cant be saved as session will be already closed
|
|
708
|
-
opts = this._validateConfig(Object.assign(this.options, opts))
|
|
709
|
-
this.debugSection('New Browser', JSON.stringify(opts))
|
|
710
|
-
const browser = await webdriverio.remote(opts)
|
|
711
|
-
this.activeSessionName = sessionName
|
|
703
|
+
opts = this._validateConfig(Object.assign(this.options, opts));
|
|
704
|
+
this.debugSection('New Browser', JSON.stringify(opts));
|
|
705
|
+
const browser = await webdriverio.remote(opts);
|
|
706
|
+
this.activeSessionName = sessionName;
|
|
712
707
|
if (opts.timeouts && this.isWeb) {
|
|
713
|
-
await this._defineBrowserTimeout(browser, opts.timeouts)
|
|
708
|
+
await this._defineBrowserTimeout(browser, opts.timeouts);
|
|
714
709
|
}
|
|
715
710
|
|
|
716
|
-
await this._resizeWindowIfNeeded(browser, opts.windowSize)
|
|
711
|
+
await this._resizeWindowIfNeeded(browser, opts.windowSize);
|
|
717
712
|
|
|
718
|
-
return browser
|
|
713
|
+
return browser;
|
|
719
714
|
},
|
|
720
715
|
stop: async (browser) => {
|
|
721
|
-
if (!browser) return
|
|
722
|
-
return browser.deleteSession()
|
|
716
|
+
if (!browser) return;
|
|
717
|
+
return browser.deleteSession();
|
|
723
718
|
},
|
|
724
719
|
loadVars: async (browser) => {
|
|
725
|
-
if (this.context !== this.root) throw new Error(
|
|
726
|
-
this.browser = browser
|
|
727
|
-
this.$$ = this.browser.$$.bind(this.browser)
|
|
728
|
-
this.sessionWindows[this.activeSessionName] = browser
|
|
720
|
+
if (this.context !== this.root) throw new Error('Can\'t start session inside within block');
|
|
721
|
+
this.browser = browser;
|
|
722
|
+
this.$$ = this.browser.$$.bind(this.browser);
|
|
723
|
+
this.sessionWindows[this.activeSessionName] = browser;
|
|
729
724
|
},
|
|
730
725
|
restoreVars: async (session) => {
|
|
731
726
|
if (!session) {
|
|
732
|
-
this.activeSessionName = ''
|
|
727
|
+
this.activeSessionName = '';
|
|
733
728
|
}
|
|
734
|
-
this.browser = defaultSession
|
|
735
|
-
this.$$ = this.browser.$$.bind(this.browser)
|
|
729
|
+
this.browser = defaultSession;
|
|
730
|
+
this.$$ = this.browser.$$.bind(this.browser);
|
|
736
731
|
},
|
|
737
|
-
}
|
|
732
|
+
};
|
|
738
733
|
}
|
|
739
734
|
|
|
740
735
|
/**
|
|
@@ -756,41 +751,41 @@ class WebDriver extends Helper {
|
|
|
756
751
|
* @param {function} fn async functuion that executed with WebDriver helper as argument
|
|
757
752
|
*/
|
|
758
753
|
useWebDriverTo(description, fn) {
|
|
759
|
-
return this._useTo(...arguments)
|
|
754
|
+
return this._useTo(...arguments);
|
|
760
755
|
}
|
|
761
756
|
|
|
762
757
|
async _failed() {
|
|
763
|
-
if (this.context !== this.root) await this._withinEnd()
|
|
758
|
+
if (this.context !== this.root) await this._withinEnd();
|
|
764
759
|
}
|
|
765
760
|
|
|
766
761
|
async _withinBegin(locator) {
|
|
767
|
-
const frame = isFrameLocator(locator)
|
|
762
|
+
const frame = isFrameLocator(locator);
|
|
768
763
|
if (frame) {
|
|
769
|
-
this.browser.isInsideFrame = true
|
|
764
|
+
this.browser.isInsideFrame = true;
|
|
770
765
|
if (Array.isArray(frame)) {
|
|
771
766
|
// this.switchTo(null);
|
|
772
|
-
await forEachAsync(frame, async
|
|
773
|
-
return
|
|
767
|
+
await forEachAsync(frame, async f => this.switchTo(f));
|
|
768
|
+
return;
|
|
774
769
|
}
|
|
775
|
-
await this.switchTo(frame)
|
|
776
|
-
return
|
|
770
|
+
await this.switchTo(frame);
|
|
771
|
+
return;
|
|
777
772
|
}
|
|
778
|
-
this.context = locator
|
|
773
|
+
this.context = locator;
|
|
779
774
|
|
|
780
|
-
let res = await this.browser.$$(withStrictLocator(locator))
|
|
781
|
-
assertElementExists(res, locator)
|
|
782
|
-
res = usingFirstElement(res)
|
|
783
|
-
this.context = res.selector
|
|
784
|
-
this.$$ = res.$$.bind(res)
|
|
775
|
+
let res = await this.browser.$$(withStrictLocator(locator));
|
|
776
|
+
assertElementExists(res, locator);
|
|
777
|
+
res = usingFirstElement(res);
|
|
778
|
+
this.context = res.selector;
|
|
779
|
+
this.$$ = res.$$.bind(res);
|
|
785
780
|
}
|
|
786
781
|
|
|
787
782
|
async _withinEnd() {
|
|
788
783
|
if (this.browser.isInsideFrame) {
|
|
789
|
-
this.browser.isInsideFrame = false
|
|
790
|
-
return this.switchTo(null)
|
|
784
|
+
this.browser.isInsideFrame = false;
|
|
785
|
+
return this.switchTo(null);
|
|
791
786
|
}
|
|
792
|
-
this.context = this.root
|
|
793
|
-
this.$$ = this.browser.$$.bind(this.browser)
|
|
787
|
+
this.context = this.root;
|
|
788
|
+
this.$$ = this.browser.$$.bind(this.browser);
|
|
794
789
|
}
|
|
795
790
|
|
|
796
791
|
/**
|
|
@@ -799,7 +794,7 @@ class WebDriver extends Helper {
|
|
|
799
794
|
* @param {object} locator
|
|
800
795
|
*/
|
|
801
796
|
_isShadowLocator(locator) {
|
|
802
|
-
return locator.type === SHADOW || locator[SHADOW]
|
|
797
|
+
return locator.type === SHADOW || locator[SHADOW];
|
|
803
798
|
}
|
|
804
799
|
|
|
805
800
|
/**
|
|
@@ -808,37 +803,35 @@ class WebDriver extends Helper {
|
|
|
808
803
|
* @param {object} locator
|
|
809
804
|
*/
|
|
810
805
|
async _locateShadow(locator) {
|
|
811
|
-
const shadow = locator.value ? locator.value : locator[SHADOW]
|
|
812
|
-
const shadowSequence = []
|
|
813
|
-
let elements
|
|
806
|
+
const shadow = locator.value ? locator.value : locator[SHADOW];
|
|
807
|
+
const shadowSequence = [];
|
|
808
|
+
let elements;
|
|
814
809
|
|
|
815
810
|
if (!Array.isArray(shadow)) {
|
|
816
|
-
throw new Error(`Shadow '${shadow}' should be defined as an Array of elements.`)
|
|
811
|
+
throw new Error(`Shadow '${shadow}' should be defined as an Array of elements.`);
|
|
817
812
|
}
|
|
818
813
|
|
|
819
814
|
// traverse through the Shadow locators in sequence
|
|
820
815
|
for (let index = 0; index < shadow.length; index++) {
|
|
821
|
-
const shadowElement = shadow[index]
|
|
822
|
-
shadowSequence.push(shadowElement)
|
|
816
|
+
const shadowElement = shadow[index];
|
|
817
|
+
shadowSequence.push(shadowElement);
|
|
823
818
|
|
|
824
819
|
if (!elements) {
|
|
825
|
-
elements = await this.browser.$$(shadowElement)
|
|
820
|
+
elements = await (this.browser.$$(shadowElement));
|
|
826
821
|
} else if (Array.isArray(elements)) {
|
|
827
|
-
elements = await elements[0].shadow$$(shadowElement)
|
|
822
|
+
elements = await elements[0].shadow$$(shadowElement);
|
|
828
823
|
} else if (elements) {
|
|
829
|
-
elements = await elements.shadow$$(shadowElement)
|
|
824
|
+
elements = await elements.shadow$$(shadowElement);
|
|
830
825
|
}
|
|
831
826
|
|
|
832
827
|
if (!elements || !elements[0]) {
|
|
833
|
-
throw new Error(
|
|
834
|
-
`Shadow Element '${shadowElement}' is not found. It is possible the element is incorrect or elements sequence is incorrect. Please verify the sequence '${shadowSequence.join('>')}' is correctly chained.`,
|
|
835
|
-
)
|
|
828
|
+
throw new Error(`Shadow Element '${shadowElement}' is not found. It is possible the element is incorrect or elements sequence is incorrect. Please verify the sequence '${shadowSequence.join('>')}' is correctly chained.`);
|
|
836
829
|
}
|
|
837
830
|
}
|
|
838
831
|
|
|
839
|
-
this.debugSection('Elements', `Found ${elements.length} '${SHADOW}' elements`)
|
|
832
|
+
this.debugSection('Elements', `Found ${elements.length} '${SHADOW}' elements`);
|
|
840
833
|
|
|
841
|
-
return elements
|
|
834
|
+
return elements;
|
|
842
835
|
}
|
|
843
836
|
|
|
844
837
|
/**
|
|
@@ -847,11 +840,8 @@ class WebDriver extends Helper {
|
|
|
847
840
|
* @param {object} locator
|
|
848
841
|
*/
|
|
849
842
|
async _smartWait(locator) {
|
|
850
|
-
this.debugSection(
|
|
851
|
-
|
|
852
|
-
`Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`,
|
|
853
|
-
)
|
|
854
|
-
await this.defineTimeout({ implicit: this.options.smartWait })
|
|
843
|
+
this.debugSection(`SmartWait (${this.options.smartWait}ms)`, `Locating ${JSON.stringify(locator)} in ${this.options.smartWait}`);
|
|
844
|
+
await this.defineTimeout({ implicit: this.options.smartWait });
|
|
855
845
|
}
|
|
856
846
|
|
|
857
847
|
/**
|
|
@@ -866,53 +856,53 @@ class WebDriver extends Helper {
|
|
|
866
856
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
867
857
|
*/
|
|
868
858
|
async _locate(locator, smartWait = false) {
|
|
869
|
-
if (require('../store').debugMode) smartWait = false
|
|
859
|
+
if (require('../store.js').debugMode) smartWait = false;
|
|
870
860
|
|
|
871
861
|
// special locator type for Shadow DOM
|
|
872
862
|
if (this._isShadowLocator(locator)) {
|
|
873
863
|
if (!this.options.smartWait || !smartWait) {
|
|
874
|
-
const els = await this._locateShadow(locator)
|
|
875
|
-
return els
|
|
864
|
+
const els = await this._locateShadow(locator);
|
|
865
|
+
return els;
|
|
876
866
|
}
|
|
877
867
|
|
|
878
|
-
const els = await this._locateShadow(locator)
|
|
879
|
-
return els
|
|
868
|
+
const els = await this._locateShadow(locator);
|
|
869
|
+
return els;
|
|
880
870
|
}
|
|
881
871
|
|
|
882
872
|
// special locator type for React
|
|
883
873
|
if (locator.react) {
|
|
884
|
-
const els = await this.browser.react$$(locator.react, locator.props || undefined, locator.state || undefined)
|
|
885
|
-
this.debugSection('Elements', `Found ${els.length} react components`)
|
|
886
|
-
return els
|
|
874
|
+
const els = await this.browser.react$$(locator.react, locator.props || undefined, locator.state || undefined);
|
|
875
|
+
this.debugSection('Elements', `Found ${els.length} react components`);
|
|
876
|
+
return els;
|
|
887
877
|
}
|
|
888
878
|
|
|
889
879
|
if (!this.options.smartWait || !smartWait) {
|
|
890
880
|
if (this._isCustomLocator(locator)) {
|
|
891
|
-
const locatorObj = new Locator(locator)
|
|
892
|
-
return this.browser.custom$$(locatorObj.type, locatorObj.value)
|
|
881
|
+
const locatorObj = new Locator(locator);
|
|
882
|
+
return this.browser.custom$$(locatorObj.type, locatorObj.value);
|
|
893
883
|
}
|
|
894
884
|
|
|
895
|
-
const els = await this.$$(withStrictLocator(locator))
|
|
896
|
-
return els
|
|
885
|
+
const els = await this.$$(withStrictLocator(locator));
|
|
886
|
+
return els;
|
|
897
887
|
}
|
|
898
888
|
|
|
899
|
-
await this._smartWait(locator)
|
|
889
|
+
await this._smartWait(locator);
|
|
900
890
|
|
|
901
891
|
if (this._isCustomLocator(locator)) {
|
|
902
|
-
const locatorObj = new Locator(locator)
|
|
903
|
-
return this.browser.custom$$(locatorObj.type, locatorObj.value)
|
|
892
|
+
const locatorObj = new Locator(locator);
|
|
893
|
+
return this.browser.custom$$(locatorObj.type, locatorObj.value);
|
|
904
894
|
}
|
|
905
895
|
|
|
906
|
-
const els = await this.$$(withStrictLocator(locator))
|
|
907
|
-
await this.defineTimeout({ implicit: 0 })
|
|
908
|
-
return els
|
|
896
|
+
const els = await this.$$(withStrictLocator(locator));
|
|
897
|
+
await this.defineTimeout({ implicit: 0 });
|
|
898
|
+
return els;
|
|
909
899
|
}
|
|
910
900
|
|
|
911
901
|
_grabCustomLocator(locator) {
|
|
912
902
|
if (typeof locator === 'string') {
|
|
913
|
-
locator = new Locator(locator)
|
|
903
|
+
locator = new Locator(locator);
|
|
914
904
|
}
|
|
915
|
-
return locator.value ? locator.value : locator.custom
|
|
905
|
+
return locator.value ? locator.value : locator.custom;
|
|
916
906
|
}
|
|
917
907
|
|
|
918
908
|
/**
|
|
@@ -925,7 +915,7 @@ class WebDriver extends Helper {
|
|
|
925
915
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
926
916
|
*/
|
|
927
917
|
async _locateCheckable(locator) {
|
|
928
|
-
return findCheckable.call(this, locator, this.$$.bind(this)).then(
|
|
918
|
+
return findCheckable.call(this, locator, this.$$.bind(this)).then(res => res);
|
|
929
919
|
}
|
|
930
920
|
|
|
931
921
|
/**
|
|
@@ -939,8 +929,8 @@ class WebDriver extends Helper {
|
|
|
939
929
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
940
930
|
*/
|
|
941
931
|
async _locateClickable(locator, context) {
|
|
942
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
943
|
-
return findClickable.call(this, locator, locateFn)
|
|
932
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
933
|
+
return findClickable.call(this, locator, locateFn);
|
|
944
934
|
}
|
|
945
935
|
|
|
946
936
|
/**
|
|
@@ -953,7 +943,7 @@ class WebDriver extends Helper {
|
|
|
953
943
|
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
954
944
|
*/
|
|
955
945
|
async _locateFields(locator) {
|
|
956
|
-
return findFields.call(this, locator).then(
|
|
946
|
+
return findFields.call(this, locator).then(res => res);
|
|
957
947
|
}
|
|
958
948
|
|
|
959
949
|
/**
|
|
@@ -961,7 +951,7 @@ class WebDriver extends Helper {
|
|
|
961
951
|
*
|
|
962
952
|
*/
|
|
963
953
|
async grabWebElements(locator) {
|
|
964
|
-
return this._locate(locator)
|
|
954
|
+
return this._locate(locator);
|
|
965
955
|
}
|
|
966
956
|
|
|
967
957
|
/**
|
|
@@ -977,11 +967,11 @@ class WebDriver extends Helper {
|
|
|
977
967
|
* @param {*} timeouts WebDriver timeouts object.
|
|
978
968
|
*/
|
|
979
969
|
defineTimeout(timeouts) {
|
|
980
|
-
return this._defineBrowserTimeout(this.browser, timeouts)
|
|
970
|
+
return this._defineBrowserTimeout(this.browser, timeouts);
|
|
981
971
|
}
|
|
982
972
|
|
|
983
973
|
_defineBrowserTimeout(browser, timeouts) {
|
|
984
|
-
return browser.setTimeout(timeouts)
|
|
974
|
+
return browser.setTimeout(timeouts);
|
|
985
975
|
}
|
|
986
976
|
|
|
987
977
|
/**
|
|
@@ -989,15 +979,15 @@ class WebDriver extends Helper {
|
|
|
989
979
|
*
|
|
990
980
|
*/
|
|
991
981
|
amOnPage(url) {
|
|
992
|
-
let split_url
|
|
982
|
+
let split_url;
|
|
993
983
|
if (this.options.basicAuth) {
|
|
994
984
|
if (url.startsWith('/')) {
|
|
995
|
-
url = this.options.url + url
|
|
985
|
+
url = this.options.url + url;
|
|
996
986
|
}
|
|
997
|
-
split_url = url.split('//')
|
|
998
|
-
url = `${split_url[0]}//${this.options.basicAuth.username}:${this.options.basicAuth.password}@${split_url[1]}
|
|
987
|
+
split_url = url.split('//');
|
|
988
|
+
url = `${split_url[0]}//${this.options.basicAuth.username}:${this.options.basicAuth.password}@${split_url[1]}`;
|
|
999
989
|
}
|
|
1000
|
-
return this.browser.url(url)
|
|
990
|
+
return this.browser.url(url);
|
|
1001
991
|
}
|
|
1002
992
|
|
|
1003
993
|
/**
|
|
@@ -1006,18 +996,18 @@ class WebDriver extends Helper {
|
|
|
1006
996
|
* {{ react }}
|
|
1007
997
|
*/
|
|
1008
998
|
async click(locator, context = null) {
|
|
1009
|
-
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick'
|
|
1010
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
999
|
+
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick';
|
|
1000
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1011
1001
|
|
|
1012
|
-
const res = await findClickable.call(this, locator, locateFn)
|
|
1002
|
+
const res = await findClickable.call(this, locator, locateFn);
|
|
1013
1003
|
if (context) {
|
|
1014
|
-
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`)
|
|
1004
|
+
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`);
|
|
1015
1005
|
} else {
|
|
1016
|
-
assertElementExists(res, locator, 'Clickable element')
|
|
1006
|
+
assertElementExists(res, locator, 'Clickable element');
|
|
1017
1007
|
}
|
|
1018
|
-
const elem = usingFirstElement(res)
|
|
1019
|
-
highlightActiveElement.call(this, elem)
|
|
1020
|
-
return this.browser[clickMethod](getElementId(elem))
|
|
1008
|
+
const elem = usingFirstElement(res);
|
|
1009
|
+
highlightActiveElement.call(this, elem);
|
|
1010
|
+
return this.browser[clickMethod](getElementId(elem));
|
|
1021
1011
|
}
|
|
1022
1012
|
|
|
1023
1013
|
/**
|
|
@@ -1026,25 +1016,25 @@ class WebDriver extends Helper {
|
|
|
1026
1016
|
* {{ react }}
|
|
1027
1017
|
*/
|
|
1028
1018
|
async forceClick(locator, context = null) {
|
|
1029
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1019
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1030
1020
|
|
|
1031
|
-
const res = await findClickable.call(this, locator, locateFn)
|
|
1021
|
+
const res = await findClickable.call(this, locator, locateFn);
|
|
1032
1022
|
if (context) {
|
|
1033
|
-
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`)
|
|
1023
|
+
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`);
|
|
1034
1024
|
} else {
|
|
1035
|
-
assertElementExists(res, locator, 'Clickable element')
|
|
1025
|
+
assertElementExists(res, locator, 'Clickable element');
|
|
1036
1026
|
}
|
|
1037
|
-
const elem = usingFirstElement(res)
|
|
1038
|
-
highlightActiveElement.call(this, elem)
|
|
1027
|
+
const elem = usingFirstElement(res);
|
|
1028
|
+
highlightActiveElement.call(this, elem);
|
|
1039
1029
|
|
|
1040
1030
|
return this.executeScript((el) => {
|
|
1041
1031
|
if (document.activeElement instanceof HTMLElement) {
|
|
1042
|
-
document.activeElement.blur()
|
|
1032
|
+
document.activeElement.blur();
|
|
1043
1033
|
}
|
|
1044
|
-
const event = document.createEvent('MouseEvent')
|
|
1045
|
-
event.initEvent('click', true, true)
|
|
1046
|
-
return el.dispatchEvent(event)
|
|
1047
|
-
}, elem)
|
|
1034
|
+
const event = document.createEvent('MouseEvent');
|
|
1035
|
+
event.initEvent('click', true, true);
|
|
1036
|
+
return el.dispatchEvent(event);
|
|
1037
|
+
}, elem);
|
|
1048
1038
|
}
|
|
1049
1039
|
|
|
1050
1040
|
/**
|
|
@@ -1053,18 +1043,18 @@ class WebDriver extends Helper {
|
|
|
1053
1043
|
* {{ react }}
|
|
1054
1044
|
*/
|
|
1055
1045
|
async doubleClick(locator, context = null) {
|
|
1056
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1046
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1057
1047
|
|
|
1058
|
-
const res = await findClickable.call(this, locator, locateFn)
|
|
1048
|
+
const res = await findClickable.call(this, locator, locateFn);
|
|
1059
1049
|
if (context) {
|
|
1060
|
-
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`)
|
|
1050
|
+
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`);
|
|
1061
1051
|
} else {
|
|
1062
|
-
assertElementExists(res, locator, 'Clickable element')
|
|
1052
|
+
assertElementExists(res, locator, 'Clickable element');
|
|
1063
1053
|
}
|
|
1064
1054
|
|
|
1065
|
-
const elem = usingFirstElement(res)
|
|
1066
|
-
highlightActiveElement.call(this, elem)
|
|
1067
|
-
return elem.doubleClick()
|
|
1055
|
+
const elem = usingFirstElement(res);
|
|
1056
|
+
highlightActiveElement.call(this, elem);
|
|
1057
|
+
return elem.doubleClick();
|
|
1068
1058
|
}
|
|
1069
1059
|
|
|
1070
1060
|
/**
|
|
@@ -1073,24 +1063,24 @@ class WebDriver extends Helper {
|
|
|
1073
1063
|
* {{ react }}
|
|
1074
1064
|
*/
|
|
1075
1065
|
async rightClick(locator, context) {
|
|
1076
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1066
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1077
1067
|
|
|
1078
|
-
const res = await findClickable.call(this, locator, locateFn)
|
|
1068
|
+
const res = await findClickable.call(this, locator, locateFn);
|
|
1079
1069
|
if (context) {
|
|
1080
|
-
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`)
|
|
1070
|
+
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`);
|
|
1081
1071
|
} else {
|
|
1082
|
-
assertElementExists(res, locator, 'Clickable element')
|
|
1072
|
+
assertElementExists(res, locator, 'Clickable element');
|
|
1083
1073
|
}
|
|
1084
1074
|
|
|
1085
|
-
const el = usingFirstElement(res)
|
|
1075
|
+
const el = usingFirstElement(res);
|
|
1086
1076
|
|
|
1087
|
-
await el.moveTo()
|
|
1077
|
+
await el.moveTo();
|
|
1088
1078
|
|
|
1089
1079
|
if (this.browser.isW3C) {
|
|
1090
|
-
return el.click({ button: 'right' })
|
|
1080
|
+
return el.click({ button: 'right' });
|
|
1091
1081
|
}
|
|
1092
1082
|
// JSON Wire version
|
|
1093
|
-
await this.browser.buttonDown(2)
|
|
1083
|
+
await this.browser.buttonDown(2);
|
|
1094
1084
|
}
|
|
1095
1085
|
|
|
1096
1086
|
/**
|
|
@@ -1099,24 +1089,24 @@ class WebDriver extends Helper {
|
|
|
1099
1089
|
* {{ react }}
|
|
1100
1090
|
*/
|
|
1101
1091
|
async forceRightClick(locator, context = null) {
|
|
1102
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1092
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1103
1093
|
|
|
1104
|
-
const res = await findClickable.call(this, locator, locateFn)
|
|
1094
|
+
const res = await findClickable.call(this, locator, locateFn);
|
|
1105
1095
|
if (context) {
|
|
1106
|
-
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`)
|
|
1096
|
+
assertElementExists(res, locator, 'Clickable element', `was not found inside element ${new Locator(context)}`);
|
|
1107
1097
|
} else {
|
|
1108
|
-
assertElementExists(res, locator, 'Clickable element')
|
|
1098
|
+
assertElementExists(res, locator, 'Clickable element');
|
|
1109
1099
|
}
|
|
1110
|
-
const elem = usingFirstElement(res)
|
|
1100
|
+
const elem = usingFirstElement(res);
|
|
1111
1101
|
|
|
1112
1102
|
return this.executeScript((el) => {
|
|
1113
1103
|
if (document.activeElement instanceof HTMLElement) {
|
|
1114
|
-
document.activeElement.blur()
|
|
1104
|
+
document.activeElement.blur();
|
|
1115
1105
|
}
|
|
1116
|
-
const event = document.createEvent('MouseEvent')
|
|
1117
|
-
event.initEvent('contextmenu', true, true)
|
|
1118
|
-
return el.dispatchEvent(event)
|
|
1119
|
-
}, elem)
|
|
1106
|
+
const event = document.createEvent('MouseEvent');
|
|
1107
|
+
event.initEvent('contextmenu', true, true);
|
|
1108
|
+
return el.dispatchEvent(event);
|
|
1109
|
+
}, elem);
|
|
1120
1110
|
}
|
|
1121
1111
|
|
|
1122
1112
|
/**
|
|
@@ -1126,12 +1116,12 @@ class WebDriver extends Helper {
|
|
|
1126
1116
|
*
|
|
1127
1117
|
*/
|
|
1128
1118
|
async fillField(field, value) {
|
|
1129
|
-
const res = await findFields.call(this, field)
|
|
1130
|
-
assertElementExists(res, field, 'Field')
|
|
1131
|
-
const elem = usingFirstElement(res)
|
|
1132
|
-
highlightActiveElement.call(this, elem)
|
|
1133
|
-
await elem.clearValue()
|
|
1134
|
-
await elem.setValue(value.toString())
|
|
1119
|
+
const res = await findFields.call(this, field);
|
|
1120
|
+
assertElementExists(res, field, 'Field');
|
|
1121
|
+
const elem = usingFirstElement(res);
|
|
1122
|
+
highlightActiveElement.call(this, elem);
|
|
1123
|
+
await elem.clearValue();
|
|
1124
|
+
await elem.setValue(value.toString());
|
|
1135
1125
|
}
|
|
1136
1126
|
|
|
1137
1127
|
/**
|
|
@@ -1139,15 +1129,15 @@ class WebDriver extends Helper {
|
|
|
1139
1129
|
* {{ react }}
|
|
1140
1130
|
*/
|
|
1141
1131
|
async appendField(field, value) {
|
|
1142
|
-
const res = await findFields.call(this, field)
|
|
1143
|
-
assertElementExists(res, field, 'Field')
|
|
1144
|
-
const elem = usingFirstElement(res)
|
|
1145
|
-
highlightActiveElement.call(this, elem)
|
|
1132
|
+
const res = await findFields.call(this, field);
|
|
1133
|
+
assertElementExists(res, field, 'Field');
|
|
1134
|
+
const elem = usingFirstElement(res);
|
|
1135
|
+
highlightActiveElement.call(this, elem);
|
|
1146
1136
|
if (this.options.automationProtocol) {
|
|
1147
|
-
const curentValue = await elem.getValue()
|
|
1148
|
-
return elem.setValue(curentValue + value.toString())
|
|
1137
|
+
const curentValue = await elem.getValue();
|
|
1138
|
+
return elem.setValue(curentValue + value.toString());
|
|
1149
1139
|
}
|
|
1150
|
-
return elem.addValue(value.toString())
|
|
1140
|
+
return elem.addValue(value.toString());
|
|
1151
1141
|
}
|
|
1152
1142
|
|
|
1153
1143
|
/**
|
|
@@ -1155,63 +1145,47 @@ class WebDriver extends Helper {
|
|
|
1155
1145
|
*
|
|
1156
1146
|
*/
|
|
1157
1147
|
async clearField(field) {
|
|
1158
|
-
const res = await findFields.call(this, field)
|
|
1159
|
-
assertElementExists(res, field, 'Field')
|
|
1160
|
-
const elem = usingFirstElement(res)
|
|
1161
|
-
highlightActiveElement.call(this, elem)
|
|
1148
|
+
const res = await findFields.call(this, field);
|
|
1149
|
+
assertElementExists(res, field, 'Field');
|
|
1150
|
+
const elem = usingFirstElement(res);
|
|
1151
|
+
highlightActiveElement.call(this, elem);
|
|
1162
1152
|
if (this.options.automationProtocol) {
|
|
1163
|
-
return elem.setValue('')
|
|
1153
|
+
return elem.setValue('');
|
|
1164
1154
|
}
|
|
1165
|
-
return elem.clearValue(getElementId(elem))
|
|
1155
|
+
return elem.clearValue(getElementId(elem));
|
|
1166
1156
|
}
|
|
1167
1157
|
|
|
1168
1158
|
/**
|
|
1169
1159
|
* {{> selectOption }}
|
|
1170
1160
|
*/
|
|
1171
1161
|
async selectOption(select, option) {
|
|
1172
|
-
const res = await findFields.call(this, select)
|
|
1173
|
-
assertElementExists(res, select, 'Selectable field')
|
|
1174
|
-
const elem = usingFirstElement(res)
|
|
1175
|
-
highlightActiveElement.call(this, elem)
|
|
1162
|
+
const res = await findFields.call(this, select);
|
|
1163
|
+
assertElementExists(res, select, 'Selectable field');
|
|
1164
|
+
const elem = usingFirstElement(res);
|
|
1165
|
+
highlightActiveElement.call(this, elem);
|
|
1176
1166
|
|
|
1177
1167
|
if (!Array.isArray(option)) {
|
|
1178
|
-
option = [option]
|
|
1168
|
+
option = [option];
|
|
1179
1169
|
}
|
|
1180
1170
|
|
|
1181
1171
|
// 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
|
-
)
|
|
1172
|
+
let els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byVisibleText(xpathLocator.literal(opt))));
|
|
1189
1173
|
|
|
1190
1174
|
const clickOptionFn = async (el) => {
|
|
1191
|
-
if (el[0]) el = el[0]
|
|
1192
|
-
const elementId = getElementId(el)
|
|
1193
|
-
if (elementId) return this.browser.elementClick(elementId)
|
|
1194
|
-
}
|
|
1175
|
+
if (el[0]) el = el[0];
|
|
1176
|
+
const elementId = getElementId(el);
|
|
1177
|
+
if (elementId) return this.browser.elementClick(elementId);
|
|
1178
|
+
};
|
|
1195
1179
|
|
|
1196
1180
|
if (Array.isArray(els) && els.length) {
|
|
1197
|
-
return forEachAsync(els, clickOptionFn)
|
|
1181
|
+
return forEachAsync(els, clickOptionFn);
|
|
1198
1182
|
}
|
|
1199
1183
|
// 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
|
-
)
|
|
1184
|
+
els = await forEachAsync(option, async opt => this.browser.findElementsFromElement(getElementId(elem), 'xpath', Locator.select.byValue(xpathLocator.literal(opt))));
|
|
1207
1185
|
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
|
-
)
|
|
1186
|
+
throw new ElementNotFound(select, `Option "${option}" in`, 'was not found neither by a visible text nor by a value');
|
|
1213
1187
|
}
|
|
1214
|
-
return forEachAsync(els, clickOptionFn)
|
|
1188
|
+
return forEachAsync(els, clickOptionFn);
|
|
1215
1189
|
}
|
|
1216
1190
|
|
|
1217
1191
|
/**
|
|
@@ -1220,29 +1194,27 @@ class WebDriver extends Helper {
|
|
|
1220
1194
|
* {{> attachFile }}
|
|
1221
1195
|
*/
|
|
1222
1196
|
async attachFile(locator, pathToFile) {
|
|
1223
|
-
let file = path.join(global.codecept_dir, pathToFile)
|
|
1197
|
+
let file = path.join(global.codecept_dir, pathToFile);
|
|
1224
1198
|
if (!fileExists(file)) {
|
|
1225
|
-
throw new Error(`File at ${file} can not be found on local system`)
|
|
1199
|
+
throw new Error(`File at ${file} can not be found on local system`);
|
|
1226
1200
|
}
|
|
1227
1201
|
|
|
1228
|
-
const res = await findFields.call(this, locator)
|
|
1229
|
-
this.debug(`Uploading ${file}`)
|
|
1230
|
-
assertElementExists(res, locator, 'File field')
|
|
1231
|
-
const el = usingFirstElement(res)
|
|
1202
|
+
const res = await findFields.call(this, locator);
|
|
1203
|
+
this.debug(`Uploading ${file}`);
|
|
1204
|
+
assertElementExists(res, locator, 'File field');
|
|
1205
|
+
const el = usingFirstElement(res);
|
|
1232
1206
|
|
|
1233
1207
|
// Remote Upload (when running Selenium Server)
|
|
1234
1208
|
if (this.options.remoteFileUpload && !this.options.automationProtocol) {
|
|
1235
1209
|
try {
|
|
1236
|
-
this.debugSection('File', 'Uploading file to remote server')
|
|
1237
|
-
file = await this.browser.uploadFile(file)
|
|
1210
|
+
this.debugSection('File', 'Uploading file to remote server');
|
|
1211
|
+
file = await this.browser.uploadFile(file);
|
|
1238
1212
|
} 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
|
-
)
|
|
1213
|
+
throw new Error(`File can't be transferred to remote server. Set \`remoteFileUpload: false\` in config to upload file locally.\n${err.message}`);
|
|
1242
1214
|
}
|
|
1243
1215
|
}
|
|
1244
1216
|
|
|
1245
|
-
return el.addValue(file)
|
|
1217
|
+
return el.addValue(file);
|
|
1246
1218
|
}
|
|
1247
1219
|
|
|
1248
1220
|
/**
|
|
@@ -1250,19 +1222,19 @@ class WebDriver extends Helper {
|
|
|
1250
1222
|
* {{> checkOption }}
|
|
1251
1223
|
*/
|
|
1252
1224
|
async checkOption(field, context = null) {
|
|
1253
|
-
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick'
|
|
1254
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1225
|
+
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick';
|
|
1226
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1255
1227
|
|
|
1256
|
-
const res = await findCheckable.call(this, field, locateFn)
|
|
1228
|
+
const res = await findCheckable.call(this, field, locateFn);
|
|
1257
1229
|
|
|
1258
|
-
assertElementExists(res, field, 'Checkable')
|
|
1259
|
-
const elem = usingFirstElement(res)
|
|
1260
|
-
const elementId = getElementId(elem)
|
|
1261
|
-
highlightActiveElement.call(this, elem)
|
|
1230
|
+
assertElementExists(res, field, 'Checkable');
|
|
1231
|
+
const elem = usingFirstElement(res);
|
|
1232
|
+
const elementId = getElementId(elem);
|
|
1233
|
+
highlightActiveElement.call(this, elem);
|
|
1262
1234
|
|
|
1263
|
-
const isSelected = await this.browser.isElementSelected(elementId)
|
|
1264
|
-
if (isSelected) return Promise.resolve(true)
|
|
1265
|
-
return this.browser[clickMethod](elementId)
|
|
1235
|
+
const isSelected = await this.browser.isElementSelected(elementId);
|
|
1236
|
+
if (isSelected) return Promise.resolve(true);
|
|
1237
|
+
return this.browser[clickMethod](elementId);
|
|
1266
1238
|
}
|
|
1267
1239
|
|
|
1268
1240
|
/**
|
|
@@ -1270,19 +1242,19 @@ class WebDriver extends Helper {
|
|
|
1270
1242
|
* {{> uncheckOption }}
|
|
1271
1243
|
*/
|
|
1272
1244
|
async uncheckOption(field, context = null) {
|
|
1273
|
-
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick'
|
|
1274
|
-
const locateFn = prepareLocateFn.call(this, context)
|
|
1245
|
+
const clickMethod = this.browser.isMobile && !this.browser.isW3C ? 'touchClick' : 'elementClick';
|
|
1246
|
+
const locateFn = prepareLocateFn.call(this, context);
|
|
1275
1247
|
|
|
1276
|
-
const res = await findCheckable.call(this, field, locateFn)
|
|
1248
|
+
const res = await findCheckable.call(this, field, locateFn);
|
|
1277
1249
|
|
|
1278
|
-
assertElementExists(res, field, 'Checkable')
|
|
1279
|
-
const elem = usingFirstElement(res)
|
|
1280
|
-
const elementId = getElementId(elem)
|
|
1281
|
-
highlightActiveElement.call(this, elem)
|
|
1250
|
+
assertElementExists(res, field, 'Checkable');
|
|
1251
|
+
const elem = usingFirstElement(res);
|
|
1252
|
+
const elementId = getElementId(elem);
|
|
1253
|
+
highlightActiveElement.call(this, elem);
|
|
1282
1254
|
|
|
1283
|
-
const isSelected = await this.browser.isElementSelected(elementId)
|
|
1284
|
-
if (!isSelected) return Promise.resolve(true)
|
|
1285
|
-
return this.browser[clickMethod](elementId)
|
|
1255
|
+
const isSelected = await this.browser.isElementSelected(elementId);
|
|
1256
|
+
if (!isSelected) return Promise.resolve(true);
|
|
1257
|
+
return this.browser[clickMethod](elementId);
|
|
1286
1258
|
}
|
|
1287
1259
|
|
|
1288
1260
|
/**
|
|
@@ -1290,10 +1262,10 @@ class WebDriver extends Helper {
|
|
|
1290
1262
|
*
|
|
1291
1263
|
*/
|
|
1292
1264
|
async grabTextFromAll(locator) {
|
|
1293
|
-
const res = await this._locate(locator, true)
|
|
1294
|
-
const val = await forEachAsync(res,
|
|
1295
|
-
this.debugSection('GrabText', String(val))
|
|
1296
|
-
return val
|
|
1265
|
+
const res = await this._locate(locator, true);
|
|
1266
|
+
const val = await forEachAsync(res, el => this.browser.getElementText(getElementId(el)));
|
|
1267
|
+
this.debugSection('GrabText', String(val));
|
|
1268
|
+
return val;
|
|
1297
1269
|
}
|
|
1298
1270
|
|
|
1299
1271
|
/**
|
|
@@ -1301,13 +1273,13 @@ class WebDriver extends Helper {
|
|
|
1301
1273
|
*
|
|
1302
1274
|
*/
|
|
1303
1275
|
async grabTextFrom(locator) {
|
|
1304
|
-
const texts = await this.grabTextFromAll(locator)
|
|
1305
|
-
assertElementExists(texts, locator)
|
|
1276
|
+
const texts = await this.grabTextFromAll(locator);
|
|
1277
|
+
assertElementExists(texts, locator);
|
|
1306
1278
|
if (texts.length > 1) {
|
|
1307
|
-
this.debugSection('GrabText', `Using first element out of ${texts.length}`)
|
|
1279
|
+
this.debugSection('GrabText', `Using first element out of ${texts.length}`);
|
|
1308
1280
|
}
|
|
1309
1281
|
|
|
1310
|
-
return texts[0]
|
|
1282
|
+
return texts[0];
|
|
1311
1283
|
}
|
|
1312
1284
|
|
|
1313
1285
|
/**
|
|
@@ -1315,10 +1287,10 @@ class WebDriver extends Helper {
|
|
|
1315
1287
|
*
|
|
1316
1288
|
*/
|
|
1317
1289
|
async grabHTMLFromAll(locator) {
|
|
1318
|
-
const elems = await this._locate(locator, true)
|
|
1319
|
-
const html = await forEachAsync(elems,
|
|
1320
|
-
this.debugSection('GrabHTML', String(html))
|
|
1321
|
-
return html
|
|
1290
|
+
const elems = await this._locate(locator, true);
|
|
1291
|
+
const html = await forEachAsync(elems, elem => elem.getHTML(false));
|
|
1292
|
+
this.debugSection('GrabHTML', String(html));
|
|
1293
|
+
return html;
|
|
1322
1294
|
}
|
|
1323
1295
|
|
|
1324
1296
|
/**
|
|
@@ -1326,13 +1298,13 @@ class WebDriver extends Helper {
|
|
|
1326
1298
|
*
|
|
1327
1299
|
*/
|
|
1328
1300
|
async grabHTMLFrom(locator) {
|
|
1329
|
-
const html = await this.grabHTMLFromAll(locator)
|
|
1330
|
-
assertElementExists(html, locator)
|
|
1301
|
+
const html = await this.grabHTMLFromAll(locator);
|
|
1302
|
+
assertElementExists(html, locator);
|
|
1331
1303
|
if (html.length > 1) {
|
|
1332
|
-
this.debugSection('GrabHTML', `Using first element out of ${html.length}`)
|
|
1304
|
+
this.debugSection('GrabHTML', `Using first element out of ${html.length}`);
|
|
1333
1305
|
}
|
|
1334
1306
|
|
|
1335
|
-
return html[0]
|
|
1307
|
+
return html[0];
|
|
1336
1308
|
}
|
|
1337
1309
|
|
|
1338
1310
|
/**
|
|
@@ -1340,11 +1312,11 @@ class WebDriver extends Helper {
|
|
|
1340
1312
|
*
|
|
1341
1313
|
*/
|
|
1342
1314
|
async grabValueFromAll(locator) {
|
|
1343
|
-
const res = await this._locate(locator, true)
|
|
1344
|
-
const val = await forEachAsync(res,
|
|
1345
|
-
this.debugSection('GrabValue', String(val))
|
|
1315
|
+
const res = await this._locate(locator, true);
|
|
1316
|
+
const val = await forEachAsync(res, el => el.getValue());
|
|
1317
|
+
this.debugSection('GrabValue', String(val));
|
|
1346
1318
|
|
|
1347
|
-
return val
|
|
1319
|
+
return val;
|
|
1348
1320
|
}
|
|
1349
1321
|
|
|
1350
1322
|
/**
|
|
@@ -1352,92 +1324,92 @@ class WebDriver extends Helper {
|
|
|
1352
1324
|
*
|
|
1353
1325
|
*/
|
|
1354
1326
|
async grabValueFrom(locator) {
|
|
1355
|
-
const values = await this.grabValueFromAll(locator)
|
|
1356
|
-
assertElementExists(values, locator)
|
|
1327
|
+
const values = await this.grabValueFromAll(locator);
|
|
1328
|
+
assertElementExists(values, locator);
|
|
1357
1329
|
if (values.length > 1) {
|
|
1358
|
-
this.debugSection('GrabValue', `Using first element out of ${values.length}`)
|
|
1330
|
+
this.debugSection('GrabValue', `Using first element out of ${values.length}`);
|
|
1359
1331
|
}
|
|
1360
1332
|
|
|
1361
|
-
return values[0]
|
|
1333
|
+
return values[0];
|
|
1362
1334
|
}
|
|
1363
1335
|
|
|
1364
1336
|
/**
|
|
1365
1337
|
* {{> grabCssPropertyFromAll }}
|
|
1366
1338
|
*/
|
|
1367
1339
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
1368
|
-
const res = await this._locate(locator, true)
|
|
1369
|
-
const val = await forEachAsync(res, async
|
|
1370
|
-
this.debugSection('Grab', String(val))
|
|
1371
|
-
return val
|
|
1340
|
+
const res = await this._locate(locator, true);
|
|
1341
|
+
const val = await forEachAsync(res, async el => this.browser.getElementCSSValue(getElementId(el), cssProperty));
|
|
1342
|
+
this.debugSection('Grab', String(val));
|
|
1343
|
+
return val;
|
|
1372
1344
|
}
|
|
1373
1345
|
|
|
1374
1346
|
/**
|
|
1375
1347
|
* {{> grabCssPropertyFrom }}
|
|
1376
1348
|
*/
|
|
1377
1349
|
async grabCssPropertyFrom(locator, cssProperty) {
|
|
1378
|
-
const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
|
|
1379
|
-
assertElementExists(cssValues, locator)
|
|
1350
|
+
const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty);
|
|
1351
|
+
assertElementExists(cssValues, locator);
|
|
1380
1352
|
|
|
1381
1353
|
if (cssValues.length > 1) {
|
|
1382
|
-
this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`)
|
|
1354
|
+
this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`);
|
|
1383
1355
|
}
|
|
1384
1356
|
|
|
1385
|
-
return cssValues[0]
|
|
1357
|
+
return cssValues[0];
|
|
1386
1358
|
}
|
|
1387
1359
|
|
|
1388
1360
|
/**
|
|
1389
1361
|
* {{> grabAttributeFromAll }}
|
|
1390
1362
|
*/
|
|
1391
1363
|
async grabAttributeFromAll(locator, attr) {
|
|
1392
|
-
const res = await this._locate(locator, true)
|
|
1393
|
-
const val = await forEachAsync(res, async
|
|
1394
|
-
this.debugSection('GrabAttribute', String(val))
|
|
1395
|
-
return val
|
|
1364
|
+
const res = await this._locate(locator, true);
|
|
1365
|
+
const val = await forEachAsync(res, async el => el.getAttribute(attr));
|
|
1366
|
+
this.debugSection('GrabAttribute', String(val));
|
|
1367
|
+
return val;
|
|
1396
1368
|
}
|
|
1397
1369
|
|
|
1398
1370
|
/**
|
|
1399
1371
|
* {{> grabAttributeFrom }}
|
|
1400
1372
|
*/
|
|
1401
1373
|
async grabAttributeFrom(locator, attr) {
|
|
1402
|
-
const attrs = await this.grabAttributeFromAll(locator, attr)
|
|
1403
|
-
assertElementExists(attrs, locator)
|
|
1374
|
+
const attrs = await this.grabAttributeFromAll(locator, attr);
|
|
1375
|
+
assertElementExists(attrs, locator);
|
|
1404
1376
|
if (attrs.length > 1) {
|
|
1405
|
-
this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
|
|
1377
|
+
this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
|
|
1406
1378
|
}
|
|
1407
|
-
return attrs[0]
|
|
1379
|
+
return attrs[0];
|
|
1408
1380
|
}
|
|
1409
1381
|
|
|
1410
1382
|
/**
|
|
1411
1383
|
* {{> seeInTitle }}
|
|
1412
1384
|
*/
|
|
1413
1385
|
async seeInTitle(text) {
|
|
1414
|
-
const title = await this.browser.getTitle()
|
|
1415
|
-
return stringIncludes('web page title').assert(text, title)
|
|
1386
|
+
const title = await this.browser.getTitle();
|
|
1387
|
+
return stringIncludes('web page title').assert(text, title);
|
|
1416
1388
|
}
|
|
1417
1389
|
|
|
1418
1390
|
/**
|
|
1419
1391
|
* {{> seeTitleEquals }}
|
|
1420
1392
|
*/
|
|
1421
1393
|
async seeTitleEquals(text) {
|
|
1422
|
-
const title = await this.browser.getTitle()
|
|
1423
|
-
return assert.equal(title, text, `expected web page title to be ${text}, but found ${title}`)
|
|
1394
|
+
const title = await this.browser.getTitle();
|
|
1395
|
+
return assert.equal(title, text, `expected web page title to be ${text}, but found ${title}`);
|
|
1424
1396
|
}
|
|
1425
1397
|
|
|
1426
1398
|
/**
|
|
1427
1399
|
* {{> dontSeeInTitle }}
|
|
1428
1400
|
*/
|
|
1429
1401
|
async dontSeeInTitle(text) {
|
|
1430
|
-
const title = await this.browser.getTitle()
|
|
1431
|
-
return stringIncludes('web page title').negate(text, title)
|
|
1402
|
+
const title = await this.browser.getTitle();
|
|
1403
|
+
return stringIncludes('web page title').negate(text, title);
|
|
1432
1404
|
}
|
|
1433
1405
|
|
|
1434
1406
|
/**
|
|
1435
1407
|
* {{> grabTitle }}
|
|
1436
1408
|
*/
|
|
1437
1409
|
async grabTitle() {
|
|
1438
|
-
const title = await this.browser.getTitle()
|
|
1439
|
-
this.debugSection('Title', title)
|
|
1440
|
-
return title
|
|
1410
|
+
const title = await this.browser.getTitle();
|
|
1411
|
+
this.debugSection('Title', title);
|
|
1412
|
+
return title;
|
|
1441
1413
|
}
|
|
1442
1414
|
|
|
1443
1415
|
/**
|
|
@@ -1446,14 +1418,14 @@ class WebDriver extends Helper {
|
|
|
1446
1418
|
* {{ react }}
|
|
1447
1419
|
*/
|
|
1448
1420
|
async see(text, context = null) {
|
|
1449
|
-
return proceedSee.call(this, 'assert', text, context)
|
|
1421
|
+
return proceedSee.call(this, 'assert', text, context);
|
|
1450
1422
|
}
|
|
1451
1423
|
|
|
1452
1424
|
/**
|
|
1453
1425
|
* {{> seeTextEquals }}
|
|
1454
1426
|
*/
|
|
1455
1427
|
async seeTextEquals(text, context = null) {
|
|
1456
|
-
return proceedSee.call(this, 'assert', text, context, true)
|
|
1428
|
+
return proceedSee.call(this, 'assert', text, context, true);
|
|
1457
1429
|
}
|
|
1458
1430
|
|
|
1459
1431
|
/**
|
|
@@ -1462,7 +1434,7 @@ class WebDriver extends Helper {
|
|
|
1462
1434
|
* {{ react }}
|
|
1463
1435
|
*/
|
|
1464
1436
|
async dontSee(text, context = null) {
|
|
1465
|
-
return proceedSee.call(this, 'negate', text, context)
|
|
1437
|
+
return proceedSee.call(this, 'negate', text, context);
|
|
1466
1438
|
}
|
|
1467
1439
|
|
|
1468
1440
|
/**
|
|
@@ -1470,8 +1442,8 @@ class WebDriver extends Helper {
|
|
|
1470
1442
|
*
|
|
1471
1443
|
*/
|
|
1472
1444
|
async seeInField(field, value) {
|
|
1473
|
-
const _value = typeof value === 'boolean' ? value : value.toString()
|
|
1474
|
-
return proceedSeeField.call(this, 'assert', field, _value)
|
|
1445
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1446
|
+
return proceedSeeField.call(this, 'assert', field, _value);
|
|
1475
1447
|
}
|
|
1476
1448
|
|
|
1477
1449
|
/**
|
|
@@ -1479,8 +1451,8 @@ class WebDriver extends Helper {
|
|
|
1479
1451
|
*
|
|
1480
1452
|
*/
|
|
1481
1453
|
async dontSeeInField(field, value) {
|
|
1482
|
-
const _value = typeof value === 'boolean' ? value : value.toString()
|
|
1483
|
-
return proceedSeeField.call(this, 'negate', field, _value)
|
|
1454
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
1455
|
+
return proceedSeeField.call(this, 'negate', field, _value);
|
|
1484
1456
|
}
|
|
1485
1457
|
|
|
1486
1458
|
/**
|
|
@@ -1488,7 +1460,7 @@ class WebDriver extends Helper {
|
|
|
1488
1460
|
* {{> seeCheckboxIsChecked }}
|
|
1489
1461
|
*/
|
|
1490
1462
|
async seeCheckboxIsChecked(field) {
|
|
1491
|
-
return proceedSeeCheckbox.call(this, 'assert', field)
|
|
1463
|
+
return proceedSeeCheckbox.call(this, 'assert', field);
|
|
1492
1464
|
}
|
|
1493
1465
|
|
|
1494
1466
|
/**
|
|
@@ -1496,7 +1468,7 @@ class WebDriver extends Helper {
|
|
|
1496
1468
|
* {{> dontSeeCheckboxIsChecked }}
|
|
1497
1469
|
*/
|
|
1498
1470
|
async dontSeeCheckboxIsChecked(field) {
|
|
1499
|
-
return proceedSeeCheckbox.call(this, 'negate', field)
|
|
1471
|
+
return proceedSeeCheckbox.call(this, 'negate', field);
|
|
1500
1472
|
}
|
|
1501
1473
|
|
|
1502
1474
|
/**
|
|
@@ -1505,13 +1477,13 @@ class WebDriver extends Helper {
|
|
|
1505
1477
|
*
|
|
1506
1478
|
*/
|
|
1507
1479
|
async seeElement(locator) {
|
|
1508
|
-
const res = await this._locate(locator, true)
|
|
1509
|
-
assertElementExists(res, locator)
|
|
1510
|
-
const selected = await forEachAsync(res, async
|
|
1480
|
+
const res = await this._locate(locator, true);
|
|
1481
|
+
assertElementExists(res, locator);
|
|
1482
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
1511
1483
|
try {
|
|
1512
|
-
return truth(`elements of ${new Locator(locator)}`, 'to be seen').assert(selected)
|
|
1484
|
+
return truth(`elements of ${(new Locator(locator))}`, 'to be seen').assert(selected);
|
|
1513
1485
|
} catch (e) {
|
|
1514
|
-
dontSeeElementError(locator)
|
|
1486
|
+
dontSeeElementError(locator);
|
|
1515
1487
|
}
|
|
1516
1488
|
}
|
|
1517
1489
|
|
|
@@ -1520,15 +1492,15 @@ class WebDriver extends Helper {
|
|
|
1520
1492
|
* {{ react }}
|
|
1521
1493
|
*/
|
|
1522
1494
|
async dontSeeElement(locator) {
|
|
1523
|
-
const res = await this._locate(locator, false)
|
|
1495
|
+
const res = await this._locate(locator, false);
|
|
1524
1496
|
if (!res || res.length === 0) {
|
|
1525
|
-
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(false)
|
|
1497
|
+
return truth(`elements of ${(new Locator(locator))}`, 'to be seen').negate(false);
|
|
1526
1498
|
}
|
|
1527
|
-
const selected = await forEachAsync(res, async
|
|
1499
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
1528
1500
|
try {
|
|
1529
|
-
return truth(`elements of ${new Locator(locator)}`, 'to be seen').negate(selected)
|
|
1501
|
+
return truth(`elements of ${(new Locator(locator))}`, 'to be seen').negate(selected);
|
|
1530
1502
|
} catch (e) {
|
|
1531
|
-
seeElementError(locator)
|
|
1503
|
+
seeElementError(locator);
|
|
1532
1504
|
}
|
|
1533
1505
|
}
|
|
1534
1506
|
|
|
@@ -1537,11 +1509,11 @@ class WebDriver extends Helper {
|
|
|
1537
1509
|
*
|
|
1538
1510
|
*/
|
|
1539
1511
|
async seeElementInDOM(locator) {
|
|
1540
|
-
const res = await this._res(locator)
|
|
1512
|
+
const res = await this._res(locator);
|
|
1541
1513
|
try {
|
|
1542
|
-
return empty('elements').negate(res)
|
|
1514
|
+
return empty('elements').negate(res);
|
|
1543
1515
|
} catch (e) {
|
|
1544
|
-
dontSeeElementInDOMError(locator)
|
|
1516
|
+
dontSeeElementInDOMError(locator);
|
|
1545
1517
|
}
|
|
1546
1518
|
}
|
|
1547
1519
|
|
|
@@ -1550,11 +1522,11 @@ class WebDriver extends Helper {
|
|
|
1550
1522
|
*
|
|
1551
1523
|
*/
|
|
1552
1524
|
async dontSeeElementInDOM(locator) {
|
|
1553
|
-
const res = await this._res(locator)
|
|
1525
|
+
const res = await this._res(locator);
|
|
1554
1526
|
try {
|
|
1555
|
-
return empty('elements').assert(res)
|
|
1527
|
+
return empty('elements').assert(res);
|
|
1556
1528
|
} catch (e) {
|
|
1557
|
-
seeElementInDOMError(locator)
|
|
1529
|
+
seeElementInDOMError(locator);
|
|
1558
1530
|
}
|
|
1559
1531
|
}
|
|
1560
1532
|
|
|
@@ -1563,8 +1535,8 @@ class WebDriver extends Helper {
|
|
|
1563
1535
|
*
|
|
1564
1536
|
*/
|
|
1565
1537
|
async seeInSource(text) {
|
|
1566
|
-
const source = await this.browser.getPageSource()
|
|
1567
|
-
return stringIncludes('HTML source of a page').assert(text, source)
|
|
1538
|
+
const source = await this.browser.getPageSource();
|
|
1539
|
+
return stringIncludes('HTML source of a page').assert(text, source);
|
|
1568
1540
|
}
|
|
1569
1541
|
|
|
1570
1542
|
/**
|
|
@@ -1572,7 +1544,7 @@ class WebDriver extends Helper {
|
|
|
1572
1544
|
*
|
|
1573
1545
|
*/
|
|
1574
1546
|
async grabSource() {
|
|
1575
|
-
return this.browser.getPageSource()
|
|
1547
|
+
return this.browser.getPageSource();
|
|
1576
1548
|
}
|
|
1577
1549
|
|
|
1578
1550
|
/**
|
|
@@ -1580,27 +1552,27 @@ class WebDriver extends Helper {
|
|
|
1580
1552
|
*/
|
|
1581
1553
|
async grabBrowserLogs() {
|
|
1582
1554
|
if (this.browser.isW3C) {
|
|
1583
|
-
this.debug('Logs not available in W3C specification')
|
|
1584
|
-
return
|
|
1555
|
+
this.debug('Logs not available in W3C specification');
|
|
1556
|
+
return;
|
|
1585
1557
|
}
|
|
1586
|
-
return this.browser.getLogs('browser')
|
|
1558
|
+
return this.browser.getLogs('browser');
|
|
1587
1559
|
}
|
|
1588
1560
|
|
|
1589
1561
|
/**
|
|
1590
1562
|
* {{> grabCurrentUrl }}
|
|
1591
1563
|
*/
|
|
1592
1564
|
async grabCurrentUrl() {
|
|
1593
|
-
const res = await this.browser.getUrl()
|
|
1594
|
-
this.debugSection('Url', res)
|
|
1595
|
-
return res
|
|
1565
|
+
const res = await this.browser.getUrl();
|
|
1566
|
+
this.debugSection('Url', res);
|
|
1567
|
+
return res;
|
|
1596
1568
|
}
|
|
1597
1569
|
|
|
1598
1570
|
/**
|
|
1599
1571
|
* {{> dontSeeInSource }}
|
|
1600
1572
|
*/
|
|
1601
1573
|
async dontSeeInSource(text) {
|
|
1602
|
-
const source = await this.browser.getPageSource()
|
|
1603
|
-
return stringIncludes('HTML source of a page').negate(text, source)
|
|
1574
|
+
const source = await this.browser.getPageSource();
|
|
1575
|
+
return stringIncludes('HTML source of a page').negate(text, source);
|
|
1604
1576
|
}
|
|
1605
1577
|
|
|
1606
1578
|
/**
|
|
@@ -1608,12 +1580,8 @@ class WebDriver extends Helper {
|
|
|
1608
1580
|
* {{ react }}
|
|
1609
1581
|
*/
|
|
1610
1582
|
async seeNumberOfElements(locator, num) {
|
|
1611
|
-
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
|
-
)
|
|
1583
|
+
const res = await this._locate(locator);
|
|
1584
|
+
return assert.equal(res.length, num, `expected number of elements (${(new Locator(locator))}) is ${num}, but found ${res.length}`);
|
|
1617
1585
|
}
|
|
1618
1586
|
|
|
1619
1587
|
/**
|
|
@@ -1621,93 +1589,86 @@ class WebDriver extends Helper {
|
|
|
1621
1589
|
* {{ react }}
|
|
1622
1590
|
*/
|
|
1623
1591
|
async seeNumberOfVisibleElements(locator, num) {
|
|
1624
|
-
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
|
-
)
|
|
1592
|
+
const res = await this.grabNumberOfVisibleElements(locator);
|
|
1593
|
+
return assert.equal(res, num, `expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`);
|
|
1630
1594
|
}
|
|
1631
1595
|
|
|
1632
1596
|
/**
|
|
1633
1597
|
* {{> seeCssPropertiesOnElements }}
|
|
1634
1598
|
*/
|
|
1635
1599
|
async seeCssPropertiesOnElements(locator, cssProperties) {
|
|
1636
|
-
const res = await this._locate(locator)
|
|
1637
|
-
assertElementExists(res, locator)
|
|
1600
|
+
const res = await this._locate(locator);
|
|
1601
|
+
assertElementExists(res, locator);
|
|
1638
1602
|
|
|
1639
|
-
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties)
|
|
1640
|
-
const elemAmount = res.length
|
|
1641
|
-
let props = []
|
|
1603
|
+
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
|
|
1604
|
+
const elemAmount = res.length;
|
|
1605
|
+
let props = [];
|
|
1642
1606
|
|
|
1643
1607
|
for (const element of res) {
|
|
1644
1608
|
for (const prop of Object.keys(cssProperties)) {
|
|
1645
|
-
const cssProp = await this.grabCssPropertyFrom(locator, prop)
|
|
1609
|
+
const cssProp = await this.grabCssPropertyFrom(locator, prop);
|
|
1646
1610
|
if (isColorProperty(prop)) {
|
|
1647
|
-
props.push(convertColorToRGBA(cssProp))
|
|
1611
|
+
props.push(convertColorToRGBA(cssProp));
|
|
1648
1612
|
} else {
|
|
1649
|
-
props.push(cssProp)
|
|
1613
|
+
props.push(cssProp);
|
|
1650
1614
|
}
|
|
1651
1615
|
}
|
|
1652
1616
|
}
|
|
1653
1617
|
|
|
1654
|
-
const values = Object.keys(cssPropertiesCamelCase).map(
|
|
1655
|
-
if (!Array.isArray(props)) props = [props]
|
|
1656
|
-
let chunked = chunkArray(props, values.length)
|
|
1618
|
+
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
|
|
1619
|
+
if (!Array.isArray(props)) props = [props];
|
|
1620
|
+
let chunked = chunkArray(props, values.length);
|
|
1657
1621
|
chunked = chunked.filter((val) => {
|
|
1658
1622
|
for (let i = 0; i < val.length; ++i) {
|
|
1659
1623
|
// eslint-disable-next-line eqeqeq
|
|
1660
|
-
if (val[i] != values[i]) return false
|
|
1624
|
+
if (val[i] != values[i]) return false;
|
|
1661
1625
|
}
|
|
1662
|
-
return true
|
|
1663
|
-
})
|
|
1664
|
-
return equals(
|
|
1665
|
-
`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
|
|
1666
|
-
).assert(chunked.length, elemAmount)
|
|
1626
|
+
return true;
|
|
1627
|
+
});
|
|
1628
|
+
return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(chunked.length, elemAmount);
|
|
1667
1629
|
}
|
|
1668
1630
|
|
|
1669
1631
|
/**
|
|
1670
1632
|
* {{> seeAttributesOnElements }}
|
|
1671
1633
|
*/
|
|
1672
1634
|
async seeAttributesOnElements(locator, attributes) {
|
|
1673
|
-
const res = await this._locate(locator)
|
|
1674
|
-
assertElementExists(res, locator)
|
|
1675
|
-
const elemAmount = res.length
|
|
1635
|
+
const res = await this._locate(locator);
|
|
1636
|
+
assertElementExists(res, locator);
|
|
1637
|
+
const elemAmount = res.length;
|
|
1676
1638
|
|
|
1677
1639
|
let attrs = await forEachAsync(res, async (el) => {
|
|
1678
|
-
return forEachAsync(Object.keys(attributes), async
|
|
1679
|
-
})
|
|
1640
|
+
return forEachAsync(Object.keys(attributes), async attr => el.getAttribute(attr));
|
|
1641
|
+
});
|
|
1680
1642
|
|
|
1681
|
-
const values = Object.keys(attributes).map(
|
|
1682
|
-
if (!Array.isArray(attrs)) attrs = [attrs]
|
|
1683
|
-
let chunked = chunkArray(attrs, values.length)
|
|
1643
|
+
const values = Object.keys(attributes).map(key => attributes[key]);
|
|
1644
|
+
if (!Array.isArray(attrs)) attrs = [attrs];
|
|
1645
|
+
let chunked = chunkArray(attrs, values.length);
|
|
1684
1646
|
chunked = chunked.filter((val) => {
|
|
1685
1647
|
for (let i = 0; i < val.length; ++i) {
|
|
1686
|
-
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)
|
|
1648
|
+
const _actual = Number.isNaN(val[i]) || (typeof values[i]) === 'string' ? val[i] : Number.parseInt(val[i], 10);
|
|
1649
|
+
const _expected = Number.isNaN(values[i]) || (typeof values[i]) === 'string' ? values[i] : Number.parseInt(values[i], 10);
|
|
1689
1650
|
// the attribute could be a boolean
|
|
1690
|
-
if (typeof _actual === 'boolean') return _actual === _expected
|
|
1691
|
-
if (_actual !== _expected) return false
|
|
1651
|
+
if (typeof _actual === 'boolean') return _actual === _expected;
|
|
1652
|
+
if (_actual !== _expected) return false;
|
|
1692
1653
|
}
|
|
1693
|
-
return true
|
|
1694
|
-
})
|
|
1654
|
+
return true;
|
|
1655
|
+
});
|
|
1695
1656
|
return assert.ok(
|
|
1696
1657
|
chunked.length === elemAmount,
|
|
1697
|
-
`expected all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`,
|
|
1698
|
-
)
|
|
1658
|
+
`expected all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`,
|
|
1659
|
+
);
|
|
1699
1660
|
}
|
|
1700
1661
|
|
|
1701
1662
|
/**
|
|
1702
1663
|
* {{> grabNumberOfVisibleElements }}
|
|
1703
1664
|
*/
|
|
1704
1665
|
async grabNumberOfVisibleElements(locator) {
|
|
1705
|
-
const res = await this._locate(locator)
|
|
1666
|
+
const res = await this._locate(locator);
|
|
1706
1667
|
|
|
1707
|
-
let selected = await forEachAsync(res, async
|
|
1708
|
-
if (!Array.isArray(selected)) selected = [selected]
|
|
1709
|
-
selected = selected.filter(
|
|
1710
|
-
return selected.length
|
|
1668
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
1669
|
+
if (!Array.isArray(selected)) selected = [selected];
|
|
1670
|
+
selected = selected.filter(val => val === true);
|
|
1671
|
+
return selected.length;
|
|
1711
1672
|
}
|
|
1712
1673
|
|
|
1713
1674
|
/**
|
|
@@ -1715,8 +1676,8 @@ class WebDriver extends Helper {
|
|
|
1715
1676
|
*
|
|
1716
1677
|
*/
|
|
1717
1678
|
async seeInCurrentUrl(url) {
|
|
1718
|
-
const res = await this.browser.getUrl()
|
|
1719
|
-
return stringIncludes('url').assert(url, decodeUrl(res))
|
|
1679
|
+
const res = await this.browser.getUrl();
|
|
1680
|
+
return stringIncludes('url').assert(url, decodeUrl(res));
|
|
1720
1681
|
}
|
|
1721
1682
|
|
|
1722
1683
|
/**
|
|
@@ -1724,8 +1685,8 @@ class WebDriver extends Helper {
|
|
|
1724
1685
|
*
|
|
1725
1686
|
*/
|
|
1726
1687
|
async dontSeeInCurrentUrl(url) {
|
|
1727
|
-
const res = await this.browser.getUrl()
|
|
1728
|
-
return stringIncludes('url').negate(url, decodeUrl(res))
|
|
1688
|
+
const res = await this.browser.getUrl();
|
|
1689
|
+
return stringIncludes('url').negate(url, decodeUrl(res));
|
|
1729
1690
|
}
|
|
1730
1691
|
|
|
1731
1692
|
/**
|
|
@@ -1733,8 +1694,8 @@ class WebDriver extends Helper {
|
|
|
1733
1694
|
*
|
|
1734
1695
|
*/
|
|
1735
1696
|
async seeCurrentUrlEquals(url) {
|
|
1736
|
-
const res = await this.browser.getUrl()
|
|
1737
|
-
return urlEquals(this.options.url).assert(url, decodeUrl(res))
|
|
1697
|
+
const res = await this.browser.getUrl();
|
|
1698
|
+
return urlEquals(this.options.url).assert(url, decodeUrl(res));
|
|
1738
1699
|
}
|
|
1739
1700
|
|
|
1740
1701
|
/**
|
|
@@ -1742,8 +1703,8 @@ class WebDriver extends Helper {
|
|
|
1742
1703
|
*
|
|
1743
1704
|
*/
|
|
1744
1705
|
async dontSeeCurrentUrlEquals(url) {
|
|
1745
|
-
const res = await this.browser.getUrl()
|
|
1746
|
-
return urlEquals(this.options.url).negate(url, decodeUrl(res))
|
|
1706
|
+
const res = await this.browser.getUrl();
|
|
1707
|
+
return urlEquals(this.options.url).negate(url, decodeUrl(res));
|
|
1747
1708
|
}
|
|
1748
1709
|
|
|
1749
1710
|
/**
|
|
@@ -1752,7 +1713,7 @@ class WebDriver extends Helper {
|
|
|
1752
1713
|
* {{> executeScript }}
|
|
1753
1714
|
*/
|
|
1754
1715
|
executeScript(...args) {
|
|
1755
|
-
return this.browser.execute.apply(this.browser, args)
|
|
1716
|
+
return this.browser.execute.apply(this.browser, args);
|
|
1756
1717
|
}
|
|
1757
1718
|
|
|
1758
1719
|
/**
|
|
@@ -1760,7 +1721,7 @@ class WebDriver extends Helper {
|
|
|
1760
1721
|
*
|
|
1761
1722
|
*/
|
|
1762
1723
|
executeAsyncScript(...args) {
|
|
1763
|
-
return this.browser.executeAsync.apply(this.browser, args)
|
|
1724
|
+
return this.browser.executeAsync.apply(this.browser, args);
|
|
1764
1725
|
}
|
|
1765
1726
|
|
|
1766
1727
|
/**
|
|
@@ -1768,10 +1729,10 @@ class WebDriver extends Helper {
|
|
|
1768
1729
|
*
|
|
1769
1730
|
*/
|
|
1770
1731
|
async scrollIntoView(locator, scrollIntoViewOptions) {
|
|
1771
|
-
const res = await this._locate(withStrictLocator(locator), true)
|
|
1772
|
-
assertElementExists(res, locator)
|
|
1773
|
-
const elem = usingFirstElement(res)
|
|
1774
|
-
return elem.scrollIntoView(scrollIntoViewOptions)
|
|
1732
|
+
const res = await this._locate(withStrictLocator(locator), true);
|
|
1733
|
+
assertElementExists(res, locator);
|
|
1734
|
+
const elem = usingFirstElement(res);
|
|
1735
|
+
return elem.scrollIntoView(scrollIntoViewOptions);
|
|
1775
1736
|
}
|
|
1776
1737
|
|
|
1777
1738
|
/**
|
|
@@ -1780,40 +1741,28 @@ class WebDriver extends Helper {
|
|
|
1780
1741
|
*/
|
|
1781
1742
|
async scrollTo(locator, offsetX = 0, offsetY = 0) {
|
|
1782
1743
|
if (typeof locator === 'number' && typeof offsetX === 'number') {
|
|
1783
|
-
offsetY = offsetX
|
|
1784
|
-
offsetX = locator
|
|
1785
|
-
locator = null
|
|
1744
|
+
offsetY = offsetX;
|
|
1745
|
+
offsetX = locator;
|
|
1746
|
+
locator = null;
|
|
1786
1747
|
}
|
|
1787
1748
|
|
|
1788
1749
|
if (locator) {
|
|
1789
|
-
const res = await this._locate(withStrictLocator(locator), true)
|
|
1790
|
-
assertElementExists(res, locator)
|
|
1791
|
-
const elem = usingFirstElement(res)
|
|
1792
|
-
const elementId = getElementId(elem)
|
|
1793
|
-
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(offsetX, offsetY, elementId)
|
|
1794
|
-
const location = await elem.getLocation()
|
|
1795
|
-
assertElementExists(location, locator, 'Failed to receive', 'location')
|
|
1750
|
+
const res = await this._locate(withStrictLocator(locator), true);
|
|
1751
|
+
assertElementExists(res, locator);
|
|
1752
|
+
const elem = usingFirstElement(res);
|
|
1753
|
+
const elementId = getElementId(elem);
|
|
1754
|
+
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(offsetX, offsetY, elementId);
|
|
1755
|
+
const location = await elem.getLocation();
|
|
1756
|
+
assertElementExists(location, locator, 'Failed to receive', 'location');
|
|
1796
1757
|
/* eslint-disable prefer-arrow-callback */
|
|
1797
|
-
return this.browser.execute(
|
|
1798
|
-
function (x, y) {
|
|
1799
|
-
return window.scrollTo(x, y)
|
|
1800
|
-
},
|
|
1801
|
-
location.x + offsetX,
|
|
1802
|
-
location.y + offsetY,
|
|
1803
|
-
)
|
|
1758
|
+
return this.browser.execute(function (x, y) { return window.scrollTo(x, y); }, location.x + offsetX, location.y + offsetY);
|
|
1804
1759
|
/* eslint-enable */
|
|
1805
1760
|
}
|
|
1806
1761
|
|
|
1807
|
-
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(locator, offsetX, offsetY)
|
|
1762
|
+
if (this.browser.isMobile && !this.browser.isW3C) return this.browser.touchScroll(locator, offsetX, offsetY);
|
|
1808
1763
|
|
|
1809
1764
|
/* eslint-disable prefer-arrow-callback, comma-dangle */
|
|
1810
|
-
return this.browser.execute(
|
|
1811
|
-
function (x, y) {
|
|
1812
|
-
return window.scrollTo(x, y)
|
|
1813
|
-
},
|
|
1814
|
-
offsetX,
|
|
1815
|
-
offsetY,
|
|
1816
|
-
)
|
|
1765
|
+
return this.browser.execute(function (x, y) { return window.scrollTo(x, y); }, offsetX, offsetY);
|
|
1817
1766
|
/* eslint-enable */
|
|
1818
1767
|
}
|
|
1819
1768
|
|
|
@@ -1821,13 +1770,13 @@ class WebDriver extends Helper {
|
|
|
1821
1770
|
* {{> moveCursorTo }}
|
|
1822
1771
|
*/
|
|
1823
1772
|
async moveCursorTo(locator, xOffset, yOffset) {
|
|
1824
|
-
const res = await this._locate(withStrictLocator(locator), true)
|
|
1825
|
-
assertElementExists(res, locator)
|
|
1826
|
-
const elem = usingFirstElement(res)
|
|
1773
|
+
const res = await this._locate(withStrictLocator(locator), true);
|
|
1774
|
+
assertElementExists(res, locator);
|
|
1775
|
+
const elem = usingFirstElement(res);
|
|
1827
1776
|
try {
|
|
1828
|
-
await elem.moveTo({ xOffset, yOffset })
|
|
1777
|
+
await elem.moveTo({ xOffset, yOffset });
|
|
1829
1778
|
} catch (e) {
|
|
1830
|
-
debug(e.message)
|
|
1779
|
+
debug(e.message);
|
|
1831
1780
|
}
|
|
1832
1781
|
}
|
|
1833
1782
|
|
|
@@ -1836,63 +1785,54 @@ class WebDriver extends Helper {
|
|
|
1836
1785
|
*
|
|
1837
1786
|
*/
|
|
1838
1787
|
async saveElementScreenshot(locator, fileName) {
|
|
1839
|
-
const outputFile = screenshotOutputFolder(fileName)
|
|
1788
|
+
const outputFile = screenshotOutputFolder(fileName);
|
|
1840
1789
|
|
|
1841
|
-
const res = await this._locate(withStrictLocator(locator), true)
|
|
1842
|
-
assertElementExists(res, locator)
|
|
1843
|
-
const elem = usingFirstElement(res)
|
|
1790
|
+
const res = await this._locate(withStrictLocator(locator), true);
|
|
1791
|
+
assertElementExists(res, locator);
|
|
1792
|
+
const elem = usingFirstElement(res);
|
|
1844
1793
|
|
|
1845
|
-
this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
|
|
1846
|
-
return elem.saveScreenshot(outputFile)
|
|
1794
|
+
this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
|
|
1795
|
+
return elem.saveScreenshot(outputFile);
|
|
1847
1796
|
}
|
|
1848
1797
|
|
|
1849
1798
|
/**
|
|
1850
1799
|
* {{> saveScreenshot }}
|
|
1851
1800
|
*/
|
|
1852
1801
|
async saveScreenshot(fileName, fullPage = false) {
|
|
1853
|
-
|
|
1802
|
+
const outputFile = screenshotOutputFolder(fileName);
|
|
1854
1803
|
|
|
1855
1804
|
if (this.activeSessionName) {
|
|
1856
|
-
const browser = this.sessionWindows[this.activeSessionName]
|
|
1857
|
-
|
|
1858
|
-
for (const sessionName in this.sessionWindows) {
|
|
1859
|
-
const activeSessionPage = this.sessionWindows[sessionName]
|
|
1860
|
-
outputFile = screenshotOutputFolder(`${sessionName}_${fileName}`)
|
|
1805
|
+
const browser = this.sessionWindows[this.activeSessionName];
|
|
1861
1806
|
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
this.debug(`Screenshot of ${sessionName} session has been saved to ${outputFile}`)
|
|
1866
|
-
return browser.saveScreenshot(outputFile)
|
|
1867
|
-
}
|
|
1807
|
+
if (browser) {
|
|
1808
|
+
this.debug(`Screenshot of ${this.activeSessionName} session has been saved to ${outputFile}`);
|
|
1809
|
+
return browser.saveScreenshot(outputFile);
|
|
1868
1810
|
}
|
|
1869
1811
|
}
|
|
1870
1812
|
|
|
1871
1813
|
if (!fullPage) {
|
|
1872
|
-
this.debug(`Screenshot has been saved to ${outputFile}`)
|
|
1873
|
-
return this.browser.saveScreenshot(outputFile)
|
|
1814
|
+
this.debug(`Screenshot has been saved to ${outputFile}`);
|
|
1815
|
+
return this.browser.saveScreenshot(outputFile);
|
|
1874
1816
|
}
|
|
1875
1817
|
|
|
1876
1818
|
/* eslint-disable prefer-arrow-callback, comma-dangle, prefer-const */
|
|
1877
|
-
const originalWindowSize = await this.browser.getWindowSize()
|
|
1819
|
+
const originalWindowSize = await this.browser.getWindowSize();
|
|
1878
1820
|
|
|
1879
|
-
let { width, height } = await this.browser
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
})
|
|
1886
|
-
.then((res) => res)
|
|
1821
|
+
let { width, height } = await this.browser.execute(function () {
|
|
1822
|
+
return {
|
|
1823
|
+
height: document.body.scrollHeight,
|
|
1824
|
+
width: document.body.scrollWidth
|
|
1825
|
+
};
|
|
1826
|
+
}).then(res => res);
|
|
1887
1827
|
|
|
1888
|
-
if (height < 100) height = 500 // errors for very small height
|
|
1828
|
+
if (height < 100) height = 500; // errors for very small height
|
|
1889
1829
|
/* eslint-enable */
|
|
1890
1830
|
|
|
1891
|
-
await this.browser.setWindowSize(width, height)
|
|
1892
|
-
this.debug(`Screenshot has been saved to ${outputFile}, size: ${width}x${height}`)
|
|
1893
|
-
const buffer = await this.browser.saveScreenshot(outputFile)
|
|
1894
|
-
await this.browser.setWindowSize(originalWindowSize.width, originalWindowSize.height)
|
|
1895
|
-
return buffer
|
|
1831
|
+
await this.browser.setWindowSize(width, height);
|
|
1832
|
+
this.debug(`Screenshot has been saved to ${outputFile}, size: ${width}x${height}`);
|
|
1833
|
+
const buffer = await this.browser.saveScreenshot(outputFile);
|
|
1834
|
+
await this.browser.setWindowSize(originalWindowSize.width, originalWindowSize.height);
|
|
1835
|
+
return buffer;
|
|
1896
1836
|
}
|
|
1897
1837
|
|
|
1898
1838
|
/**
|
|
@@ -1900,40 +1840,40 @@ class WebDriver extends Helper {
|
|
|
1900
1840
|
* {{> setCookie }}
|
|
1901
1841
|
*/
|
|
1902
1842
|
async setCookie(cookie) {
|
|
1903
|
-
return this.browser.setCookies(cookie)
|
|
1843
|
+
return this.browser.setCookies(cookie);
|
|
1904
1844
|
}
|
|
1905
1845
|
|
|
1906
1846
|
/**
|
|
1907
1847
|
* {{> clearCookie }}
|
|
1908
1848
|
*/
|
|
1909
1849
|
async clearCookie(cookie) {
|
|
1910
|
-
return this.browser.deleteCookies(cookie)
|
|
1850
|
+
return this.browser.deleteCookies(cookie);
|
|
1911
1851
|
}
|
|
1912
1852
|
|
|
1913
1853
|
/**
|
|
1914
1854
|
* {{> seeCookie }}
|
|
1915
1855
|
*/
|
|
1916
1856
|
async seeCookie(name) {
|
|
1917
|
-
const cookie = await this.browser.getCookies([name])
|
|
1918
|
-
return truth(`cookie ${name}`, 'to be set').assert(cookie)
|
|
1857
|
+
const cookie = await this.browser.getCookies([name]);
|
|
1858
|
+
return truth(`cookie ${name}`, 'to be set').assert(cookie);
|
|
1919
1859
|
}
|
|
1920
1860
|
|
|
1921
1861
|
/**
|
|
1922
1862
|
* {{> dontSeeCookie }}
|
|
1923
1863
|
*/
|
|
1924
1864
|
async dontSeeCookie(name) {
|
|
1925
|
-
const cookie = await this.browser.getCookies([name])
|
|
1926
|
-
return truth(`cookie ${name}`, 'to be set').negate(cookie)
|
|
1865
|
+
const cookie = await this.browser.getCookies([name]);
|
|
1866
|
+
return truth(`cookie ${name}`, 'to be set').negate(cookie);
|
|
1927
1867
|
}
|
|
1928
1868
|
|
|
1929
1869
|
/**
|
|
1930
1870
|
* {{> grabCookie }}
|
|
1931
1871
|
*/
|
|
1932
1872
|
async grabCookie(name) {
|
|
1933
|
-
if (!name) return this.browser.getCookies()
|
|
1934
|
-
const cookie = await this.browser.getCookies([name])
|
|
1935
|
-
this.debugSection('Cookie', JSON.stringify(cookie))
|
|
1936
|
-
return cookie[0]
|
|
1873
|
+
if (!name) return this.browser.getCookies();
|
|
1874
|
+
const cookie = await this.browser.getCookies([name]);
|
|
1875
|
+
this.debugSection('Cookie', JSON.stringify(cookie));
|
|
1876
|
+
return cookie[0];
|
|
1937
1877
|
}
|
|
1938
1878
|
|
|
1939
1879
|
/**
|
|
@@ -1941,33 +1881,30 @@ class WebDriver extends Helper {
|
|
|
1941
1881
|
*/
|
|
1942
1882
|
async waitForCookie(name, sec) {
|
|
1943
1883
|
// by default, we will retry 3 times
|
|
1944
|
-
let retries = 3
|
|
1945
|
-
const waitTimeout = sec || this.options.waitForTimeoutInSeconds
|
|
1884
|
+
let retries = 3;
|
|
1885
|
+
const waitTimeout = sec || this.options.waitForTimeoutInSeconds;
|
|
1946
1886
|
|
|
1947
1887
|
if (sec) {
|
|
1948
|
-
retries = sec
|
|
1888
|
+
retries = sec;
|
|
1949
1889
|
} else {
|
|
1950
|
-
retries = waitTimeout - 1
|
|
1890
|
+
retries = waitTimeout - 1;
|
|
1951
1891
|
}
|
|
1952
1892
|
|
|
1953
|
-
return promiseRetry(
|
|
1954
|
-
async (
|
|
1955
|
-
const
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
}
|
|
1893
|
+
return promiseRetry(async (retry, number) => {
|
|
1894
|
+
const _grabCookie = async (name) => {
|
|
1895
|
+
const cookie = await this.browser.getCookies([name]);
|
|
1896
|
+
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
|
|
1897
|
+
};
|
|
1959
1898
|
|
|
1960
|
-
|
|
1961
|
-
|
|
1899
|
+
this.debugSection('Wait for cookie: ', name);
|
|
1900
|
+
if (number > 1) this.debugSection('Retrying... Attempt #', number);
|
|
1962
1901
|
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
{ retries, maxTimeout: 1000 },
|
|
1970
|
-
)
|
|
1902
|
+
try {
|
|
1903
|
+
await _grabCookie(name);
|
|
1904
|
+
} catch (e) {
|
|
1905
|
+
retry(e);
|
|
1906
|
+
}
|
|
1907
|
+
}, { retries, maxTimeout: 1000 });
|
|
1971
1908
|
}
|
|
1972
1909
|
|
|
1973
1910
|
/**
|
|
@@ -1978,9 +1915,9 @@ class WebDriver extends Helper {
|
|
|
1978
1915
|
async acceptPopup() {
|
|
1979
1916
|
return this.browser.getAlertText().then((res) => {
|
|
1980
1917
|
if (res !== null) {
|
|
1981
|
-
return this.browser.acceptAlert()
|
|
1918
|
+
return this.browser.acceptAlert();
|
|
1982
1919
|
}
|
|
1983
|
-
})
|
|
1920
|
+
});
|
|
1984
1921
|
}
|
|
1985
1922
|
|
|
1986
1923
|
/**
|
|
@@ -1990,9 +1927,9 @@ class WebDriver extends Helper {
|
|
|
1990
1927
|
async cancelPopup() {
|
|
1991
1928
|
return this.browser.getAlertText().then((res) => {
|
|
1992
1929
|
if (res !== null) {
|
|
1993
|
-
return this.browser.dismissAlert()
|
|
1930
|
+
return this.browser.dismissAlert();
|
|
1994
1931
|
}
|
|
1995
|
-
})
|
|
1932
|
+
});
|
|
1996
1933
|
}
|
|
1997
1934
|
|
|
1998
1935
|
/**
|
|
@@ -2004,10 +1941,10 @@ class WebDriver extends Helper {
|
|
|
2004
1941
|
async seeInPopup(text) {
|
|
2005
1942
|
return this.browser.getAlertText().then((res) => {
|
|
2006
1943
|
if (res === null) {
|
|
2007
|
-
throw new Error('Popup is not opened')
|
|
1944
|
+
throw new Error('Popup is not opened');
|
|
2008
1945
|
}
|
|
2009
|
-
stringIncludes('text in popup').assert(text, res)
|
|
2010
|
-
})
|
|
1946
|
+
stringIncludes('text in popup').assert(text, res);
|
|
1947
|
+
});
|
|
2011
1948
|
}
|
|
2012
1949
|
|
|
2013
1950
|
/**
|
|
@@ -2015,9 +1952,9 @@ class WebDriver extends Helper {
|
|
|
2015
1952
|
*/
|
|
2016
1953
|
async grabPopupText() {
|
|
2017
1954
|
try {
|
|
2018
|
-
return await this.browser.getAlertText()
|
|
1955
|
+
return await this.browser.getAlertText();
|
|
2019
1956
|
} catch (err) {
|
|
2020
|
-
this.debugSection('Popup', 'Error getting text from popup')
|
|
1957
|
+
this.debugSection('Popup', 'Error getting text from popup');
|
|
2021
1958
|
}
|
|
2022
1959
|
}
|
|
2023
1960
|
|
|
@@ -2025,44 +1962,36 @@ class WebDriver extends Helper {
|
|
|
2025
1962
|
* {{> pressKeyDown }}
|
|
2026
1963
|
*/
|
|
2027
1964
|
async pressKeyDown(key) {
|
|
2028
|
-
key = getNormalizedKey.call(this, key)
|
|
1965
|
+
key = getNormalizedKey.call(this, key);
|
|
2029
1966
|
if (!this.browser.isW3C) {
|
|
2030
|
-
return this.browser.sendKeys([key])
|
|
1967
|
+
return this.browser.sendKeys([key]);
|
|
2031
1968
|
}
|
|
2032
|
-
return this.browser.performActions([
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
},
|
|
2041
|
-
],
|
|
2042
|
-
},
|
|
2043
|
-
])
|
|
1969
|
+
return this.browser.performActions([{
|
|
1970
|
+
type: 'key',
|
|
1971
|
+
id: 'keyboard',
|
|
1972
|
+
actions: [{
|
|
1973
|
+
type: 'keyDown',
|
|
1974
|
+
value: key,
|
|
1975
|
+
}],
|
|
1976
|
+
}]);
|
|
2044
1977
|
}
|
|
2045
1978
|
|
|
2046
1979
|
/**
|
|
2047
1980
|
* {{> pressKeyUp }}
|
|
2048
1981
|
*/
|
|
2049
1982
|
async pressKeyUp(key) {
|
|
2050
|
-
key = getNormalizedKey.call(this, key)
|
|
1983
|
+
key = getNormalizedKey.call(this, key);
|
|
2051
1984
|
if (!this.browser.isW3C) {
|
|
2052
|
-
return this.browser.sendKeys([key])
|
|
1985
|
+
return this.browser.sendKeys([key]);
|
|
2053
1986
|
}
|
|
2054
|
-
return this.browser.performActions([
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
},
|
|
2063
|
-
],
|
|
2064
|
-
},
|
|
2065
|
-
])
|
|
1987
|
+
return this.browser.performActions([{
|
|
1988
|
+
type: 'key',
|
|
1989
|
+
id: 'keyboard',
|
|
1990
|
+
actions: [{
|
|
1991
|
+
type: 'keyUp',
|
|
1992
|
+
value: key,
|
|
1993
|
+
}],
|
|
1994
|
+
}]);
|
|
2066
1995
|
}
|
|
2067
1996
|
|
|
2068
1997
|
/**
|
|
@@ -2071,45 +2000,40 @@ class WebDriver extends Helper {
|
|
|
2071
2000
|
* {{> pressKeyWithKeyNormalization }}
|
|
2072
2001
|
*/
|
|
2073
2002
|
async pressKey(key) {
|
|
2074
|
-
const modifiers = []
|
|
2003
|
+
const modifiers = [];
|
|
2075
2004
|
if (Array.isArray(key)) {
|
|
2076
2005
|
for (let k of key) {
|
|
2077
|
-
k = getNormalizedKey.call(this, k)
|
|
2006
|
+
k = getNormalizedKey.call(this, k);
|
|
2078
2007
|
if (isModifierKey(k)) {
|
|
2079
|
-
modifiers.push(k)
|
|
2008
|
+
modifiers.push(k);
|
|
2080
2009
|
} else {
|
|
2081
|
-
key = k
|
|
2082
|
-
break
|
|
2010
|
+
key = k;
|
|
2011
|
+
break;
|
|
2083
2012
|
}
|
|
2084
2013
|
}
|
|
2085
2014
|
} else {
|
|
2086
|
-
key = getNormalizedKey.call(this, key)
|
|
2015
|
+
key = getNormalizedKey.call(this, key);
|
|
2087
2016
|
}
|
|
2088
2017
|
for (const modifier of modifiers) {
|
|
2089
|
-
await this.pressKeyDown(modifier)
|
|
2018
|
+
await this.pressKeyDown(modifier);
|
|
2090
2019
|
}
|
|
2091
2020
|
if (!this.browser.isW3C) {
|
|
2092
|
-
await this.browser.sendKeys([key])
|
|
2021
|
+
await this.browser.sendKeys([key]);
|
|
2093
2022
|
} else {
|
|
2094
|
-
await this.browser.performActions([
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
value: key,
|
|
2106
|
-
},
|
|
2107
|
-
],
|
|
2108
|
-
},
|
|
2109
|
-
])
|
|
2023
|
+
await this.browser.performActions([{
|
|
2024
|
+
type: 'key',
|
|
2025
|
+
id: 'keyboard',
|
|
2026
|
+
actions: [{
|
|
2027
|
+
type: 'keyDown',
|
|
2028
|
+
value: key,
|
|
2029
|
+
}, {
|
|
2030
|
+
type: 'keyUp',
|
|
2031
|
+
value: key,
|
|
2032
|
+
}],
|
|
2033
|
+
}]);
|
|
2110
2034
|
}
|
|
2111
2035
|
for (const modifier of modifiers) {
|
|
2112
|
-
await this.pressKeyUp(modifier)
|
|
2036
|
+
await this.pressKeyUp(modifier);
|
|
2113
2037
|
}
|
|
2114
2038
|
}
|
|
2115
2039
|
|
|
@@ -2118,17 +2042,17 @@ class WebDriver extends Helper {
|
|
|
2118
2042
|
*/
|
|
2119
2043
|
async type(keys, delay = null) {
|
|
2120
2044
|
if (!Array.isArray(keys)) {
|
|
2121
|
-
keys = keys.toString()
|
|
2122
|
-
keys = keys.split('')
|
|
2045
|
+
keys = keys.toString();
|
|
2046
|
+
keys = keys.split('');
|
|
2123
2047
|
}
|
|
2124
2048
|
if (delay) {
|
|
2125
2049
|
for (const key of keys) {
|
|
2126
|
-
await this.browser.keys(key)
|
|
2127
|
-
await this.wait(delay / 1000)
|
|
2050
|
+
await this.browser.keys(key);
|
|
2051
|
+
await this.wait(delay / 1000);
|
|
2128
2052
|
}
|
|
2129
|
-
return
|
|
2053
|
+
return;
|
|
2130
2054
|
}
|
|
2131
|
-
await this.browser.keys(keys)
|
|
2055
|
+
await this.browser.keys(keys);
|
|
2132
2056
|
}
|
|
2133
2057
|
|
|
2134
2058
|
/**
|
|
@@ -2137,27 +2061,27 @@ class WebDriver extends Helper {
|
|
|
2137
2061
|
* {{> resizeWindow }}
|
|
2138
2062
|
*/
|
|
2139
2063
|
async resizeWindow(width, height) {
|
|
2140
|
-
return this.browser.setWindowSize(width, height)
|
|
2064
|
+
return this.browser.setWindowSize(width, height);
|
|
2141
2065
|
}
|
|
2142
2066
|
|
|
2143
2067
|
async _resizeBrowserWindow(browser, width, height) {
|
|
2144
2068
|
if (width === 'maximize') {
|
|
2145
|
-
const size = await browser.maximizeWindow()
|
|
2146
|
-
this.debugSection('Window Size', size)
|
|
2147
|
-
return
|
|
2069
|
+
const size = await browser.maximizeWindow();
|
|
2070
|
+
this.debugSection('Window Size', size);
|
|
2071
|
+
return;
|
|
2148
2072
|
}
|
|
2149
2073
|
if (browser.isW3C) {
|
|
2150
|
-
return browser.setWindowRect(null, null, parseInt(width, 10), parseInt(height, 10))
|
|
2074
|
+
return browser.setWindowRect(null, null, parseInt(width, 10), parseInt(height, 10));
|
|
2151
2075
|
}
|
|
2152
|
-
return browser.setWindowSize(parseInt(width, 10), parseInt(height, 10))
|
|
2076
|
+
return browser.setWindowSize(parseInt(width, 10), parseInt(height, 10));
|
|
2153
2077
|
}
|
|
2154
2078
|
|
|
2155
2079
|
async _resizeWindowIfNeeded(browser, windowSize) {
|
|
2156
2080
|
if (this.isWeb && windowSize === 'maximize') {
|
|
2157
|
-
await this._resizeBrowserWindow(browser, 'maximize')
|
|
2081
|
+
await this._resizeBrowserWindow(browser, 'maximize');
|
|
2158
2082
|
} else if (this.isWeb && windowSize && windowSize.indexOf('x') > 0) {
|
|
2159
|
-
const dimensions = windowSize.split('x')
|
|
2160
|
-
await this._resizeBrowserWindow(browser, dimensions[0], dimensions[1])
|
|
2083
|
+
const dimensions = windowSize.split('x');
|
|
2084
|
+
await this._resizeBrowserWindow(browser, dimensions[0], dimensions[1]);
|
|
2161
2085
|
}
|
|
2162
2086
|
}
|
|
2163
2087
|
|
|
@@ -2166,11 +2090,11 @@ class WebDriver extends Helper {
|
|
|
2166
2090
|
*
|
|
2167
2091
|
*/
|
|
2168
2092
|
async focus(locator) {
|
|
2169
|
-
const els = await this._locate(locator)
|
|
2170
|
-
assertElementExists(els, locator, 'Element to focus')
|
|
2171
|
-
const el = usingFirstElement(els)
|
|
2093
|
+
const els = await this._locate(locator);
|
|
2094
|
+
assertElementExists(els, locator, 'Element to focus');
|
|
2095
|
+
const el = usingFirstElement(els);
|
|
2172
2096
|
|
|
2173
|
-
await focusElement(el, this.browser)
|
|
2097
|
+
await focusElement(el, this.browser);
|
|
2174
2098
|
}
|
|
2175
2099
|
|
|
2176
2100
|
/**
|
|
@@ -2178,11 +2102,11 @@ class WebDriver extends Helper {
|
|
|
2178
2102
|
*
|
|
2179
2103
|
*/
|
|
2180
2104
|
async blur(locator) {
|
|
2181
|
-
const els = await this._locate(locator)
|
|
2182
|
-
assertElementExists(els, locator, 'Element to blur')
|
|
2183
|
-
const el = usingFirstElement(els)
|
|
2105
|
+
const els = await this._locate(locator);
|
|
2106
|
+
assertElementExists(els, locator, 'Element to blur');
|
|
2107
|
+
const el = usingFirstElement(els);
|
|
2184
2108
|
|
|
2185
|
-
await blurElement(el, this.browser)
|
|
2109
|
+
await blurElement(el, this.browser);
|
|
2186
2110
|
}
|
|
2187
2111
|
|
|
2188
2112
|
/**
|
|
@@ -2190,73 +2114,64 @@ class WebDriver extends Helper {
|
|
|
2190
2114
|
* {{> dragAndDrop }}
|
|
2191
2115
|
*/
|
|
2192
2116
|
async dragAndDrop(srcElement, destElement) {
|
|
2193
|
-
let sourceEl = await this._locate(srcElement)
|
|
2194
|
-
assertElementExists(sourceEl, srcElement)
|
|
2195
|
-
sourceEl = usingFirstElement(sourceEl)
|
|
2117
|
+
let sourceEl = await this._locate(srcElement);
|
|
2118
|
+
assertElementExists(sourceEl, srcElement);
|
|
2119
|
+
sourceEl = usingFirstElement(sourceEl);
|
|
2196
2120
|
|
|
2197
|
-
let destEl = await this._locate(destElement)
|
|
2198
|
-
assertElementExists(destEl, destElement)
|
|
2199
|
-
destEl = usingFirstElement(destEl)
|
|
2121
|
+
let destEl = await this._locate(destElement);
|
|
2122
|
+
assertElementExists(destEl, destElement);
|
|
2123
|
+
destEl = usingFirstElement(destEl);
|
|
2200
2124
|
|
|
2201
|
-
return sourceEl.dragAndDrop(destEl)
|
|
2125
|
+
return sourceEl.dragAndDrop(destEl);
|
|
2202
2126
|
}
|
|
2203
2127
|
|
|
2204
2128
|
/**
|
|
2205
2129
|
* {{> dragSlider }}
|
|
2206
2130
|
*/
|
|
2207
2131
|
async dragSlider(locator, offsetX = 0) {
|
|
2208
|
-
const browser = this.browser
|
|
2209
|
-
await this.moveCursorTo(locator)
|
|
2132
|
+
const browser = this.browser;
|
|
2133
|
+
await this.moveCursorTo(locator);
|
|
2210
2134
|
|
|
2211
2135
|
// for chrome
|
|
2212
2136
|
if (browser.isW3C) {
|
|
2213
|
-
const xOffset = await this.grabElementBoundingRect(locator, 'x')
|
|
2214
|
-
const yOffset = await this.grabElementBoundingRect(locator, 'y')
|
|
2215
|
-
|
|
2216
|
-
return browser.performActions([
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
{ type: 'pointerUp', button: 0 },
|
|
2238
|
-
],
|
|
2239
|
-
},
|
|
2240
|
-
])
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
await browser.buttonDown(0)
|
|
2244
|
-
await browser.moveToElement(null, offsetX, 0)
|
|
2245
|
-
await browser.buttonUp(0)
|
|
2137
|
+
const xOffset = await this.grabElementBoundingRect(locator, 'x');
|
|
2138
|
+
const yOffset = await this.grabElementBoundingRect(locator, 'y');
|
|
2139
|
+
|
|
2140
|
+
return browser.performActions([{
|
|
2141
|
+
type: 'pointer',
|
|
2142
|
+
id: 'pointer1',
|
|
2143
|
+
parameters: { pointerType: 'mouse' },
|
|
2144
|
+
actions: [
|
|
2145
|
+
{
|
|
2146
|
+
type: 'pointerMove', origin: 'pointer', duration: 1000, x: xOffset, y: yOffset,
|
|
2147
|
+
},
|
|
2148
|
+
{ type: 'pointerDown', button: 0 },
|
|
2149
|
+
{
|
|
2150
|
+
type: 'pointerMove', origin: 'pointer', duration: 1000, x: offsetX, y: 0,
|
|
2151
|
+
},
|
|
2152
|
+
{ type: 'pointerUp', button: 0 },
|
|
2153
|
+
],
|
|
2154
|
+
},
|
|
2155
|
+
]);
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
await browser.buttonDown(0);
|
|
2159
|
+
await browser.moveToElement(null, offsetX, 0);
|
|
2160
|
+
await browser.buttonUp(0);
|
|
2246
2161
|
}
|
|
2247
2162
|
|
|
2248
2163
|
/**
|
|
2249
2164
|
* {{> grabAllWindowHandles }}
|
|
2250
2165
|
*/
|
|
2251
2166
|
async grabAllWindowHandles() {
|
|
2252
|
-
return this.browser.getWindowHandles()
|
|
2167
|
+
return this.browser.getWindowHandles();
|
|
2253
2168
|
}
|
|
2254
2169
|
|
|
2255
2170
|
/**
|
|
2256
2171
|
* {{> grabCurrentWindowHandle }}
|
|
2257
2172
|
*/
|
|
2258
2173
|
async grabCurrentWindowHandle() {
|
|
2259
|
-
return this.browser.getWindowHandle()
|
|
2174
|
+
return this.browser.getWindowHandle();
|
|
2260
2175
|
}
|
|
2261
2176
|
|
|
2262
2177
|
/**
|
|
@@ -2274,140 +2189,125 @@ class WebDriver extends Helper {
|
|
|
2274
2189
|
* @param {string} window name of window handle.
|
|
2275
2190
|
*/
|
|
2276
2191
|
async switchToWindow(window) {
|
|
2277
|
-
await this.browser.switchToWindow(window)
|
|
2192
|
+
await this.browser.switchToWindow(window);
|
|
2278
2193
|
}
|
|
2279
2194
|
|
|
2280
2195
|
/**
|
|
2281
2196
|
* {{> closeOtherTabs }}
|
|
2282
2197
|
*/
|
|
2283
2198
|
async closeOtherTabs() {
|
|
2284
|
-
const handles = await this.browser.getWindowHandles()
|
|
2285
|
-
const currentHandle = await this.browser.getWindowHandle()
|
|
2286
|
-
const otherHandles = handles.filter(
|
|
2199
|
+
const handles = await this.browser.getWindowHandles();
|
|
2200
|
+
const currentHandle = await this.browser.getWindowHandle();
|
|
2201
|
+
const otherHandles = handles.filter(handle => handle !== currentHandle);
|
|
2287
2202
|
|
|
2288
2203
|
await forEachAsync(otherHandles, async (handle) => {
|
|
2289
|
-
await this.browser.switchToWindow(handle)
|
|
2290
|
-
await this.browser.closeWindow()
|
|
2291
|
-
})
|
|
2292
|
-
await this.browser.switchToWindow(currentHandle)
|
|
2204
|
+
await this.browser.switchToWindow(handle);
|
|
2205
|
+
await this.browser.closeWindow();
|
|
2206
|
+
});
|
|
2207
|
+
await this.browser.switchToWindow(currentHandle);
|
|
2293
2208
|
}
|
|
2294
2209
|
|
|
2295
2210
|
/**
|
|
2296
2211
|
* {{> wait }}
|
|
2297
2212
|
*/
|
|
2298
2213
|
async wait(sec) {
|
|
2299
|
-
return new Promise(
|
|
2300
|
-
setTimeout(resolve, sec * 1000)
|
|
2301
|
-
})
|
|
2214
|
+
return new Promise(resolve => {
|
|
2215
|
+
setTimeout(resolve, sec * 1000);
|
|
2216
|
+
});
|
|
2302
2217
|
}
|
|
2303
2218
|
|
|
2304
2219
|
/**
|
|
2305
2220
|
* {{> waitForEnabled }}
|
|
2306
2221
|
*/
|
|
2307
2222
|
async waitForEnabled(locator, sec = null) {
|
|
2308
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2223
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2309
2224
|
|
|
2310
|
-
return this.browser.waitUntil(
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
{
|
|
2323
|
-
|
|
2324
|
-
timeoutMsg: `element (${new Locator(locator)}) still not enabled after ${aSec} sec`,
|
|
2325
|
-
},
|
|
2326
|
-
)
|
|
2225
|
+
return this.browser.waitUntil(async () => {
|
|
2226
|
+
const res = await this._res(locator);
|
|
2227
|
+
if (!res || res.length === 0) {
|
|
2228
|
+
return false;
|
|
2229
|
+
}
|
|
2230
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementEnabled(getElementId(el)));
|
|
2231
|
+
if (Array.isArray(selected)) {
|
|
2232
|
+
return selected.filter(val => val === true).length > 0;
|
|
2233
|
+
}
|
|
2234
|
+
return selected;
|
|
2235
|
+
}, {
|
|
2236
|
+
timeout: aSec * 1000,
|
|
2237
|
+
timeoutMsg: `element (${new Locator(locator)}) still not enabled after ${aSec} sec`,
|
|
2238
|
+
});
|
|
2327
2239
|
}
|
|
2328
2240
|
|
|
2329
2241
|
/**
|
|
2330
2242
|
* {{> waitForElement }}
|
|
2331
2243
|
*/
|
|
2332
2244
|
async waitForElement(locator, sec = null) {
|
|
2333
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2245
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2334
2246
|
|
|
2335
|
-
return this.browser.waitUntil(
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
},
|
|
2340
|
-
{
|
|
2341
|
-
timeout: aSec * 1000,
|
|
2342
|
-
timeoutMsg: `element (${new Locator(locator)}) still not present on page after ${aSec} sec`,
|
|
2343
|
-
},
|
|
2344
|
-
)
|
|
2247
|
+
return this.browser.waitUntil(async () => {
|
|
2248
|
+
const res = await this._res(locator);
|
|
2249
|
+
return res && res.length;
|
|
2250
|
+
}, { timeout: aSec * 1000, timeoutMsg: `element (${(new Locator(locator))}) still not present on page after ${aSec} sec` });
|
|
2345
2251
|
}
|
|
2346
2252
|
|
|
2347
2253
|
/**
|
|
2348
2254
|
* {{> waitForClickable }}
|
|
2349
2255
|
*/
|
|
2350
2256
|
async waitForClickable(locator, waitTimeout) {
|
|
2351
|
-
waitTimeout = waitTimeout || this.options.waitForTimeoutInSeconds
|
|
2352
|
-
let res = await this._locate(locator)
|
|
2353
|
-
res = usingFirstElement(res)
|
|
2354
|
-
assertElementExists(res, locator)
|
|
2257
|
+
waitTimeout = waitTimeout || this.options.waitForTimeoutInSeconds;
|
|
2258
|
+
let res = await this._locate(locator);
|
|
2259
|
+
res = usingFirstElement(res);
|
|
2260
|
+
assertElementExists(res, locator);
|
|
2355
2261
|
|
|
2356
2262
|
return res.waitForClickable({
|
|
2357
2263
|
timeout: waitTimeout * 1000,
|
|
2358
2264
|
timeoutMsg: `element ${res.selector} still not clickable after ${waitTimeout} sec`,
|
|
2359
|
-
})
|
|
2265
|
+
});
|
|
2360
2266
|
}
|
|
2361
2267
|
|
|
2362
2268
|
/**
|
|
2363
2269
|
* {{> waitInUrl }}
|
|
2364
2270
|
*/
|
|
2365
2271
|
async waitInUrl(urlPart, sec = null) {
|
|
2366
|
-
const client = this.browser
|
|
2367
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2368
|
-
let currUrl = ''
|
|
2272
|
+
const client = this.browser;
|
|
2273
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2274
|
+
let currUrl = '';
|
|
2369
2275
|
|
|
2370
2276
|
return client
|
|
2371
|
-
.waitUntil(
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
},
|
|
2378
|
-
{ timeout: aSec * 1000 },
|
|
2379
|
-
)
|
|
2380
|
-
.catch((e) => {
|
|
2277
|
+
.waitUntil(function () {
|
|
2278
|
+
return this.getUrl().then((res) => {
|
|
2279
|
+
currUrl = decodeUrl(res);
|
|
2280
|
+
return currUrl.indexOf(urlPart) > -1;
|
|
2281
|
+
});
|
|
2282
|
+
}, { timeout: aSec * 1000 }).catch((e) => {
|
|
2381
2283
|
if (e.message.indexOf('timeout')) {
|
|
2382
|
-
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
|
|
2284
|
+
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
|
|
2383
2285
|
}
|
|
2384
|
-
throw e
|
|
2385
|
-
})
|
|
2286
|
+
throw e;
|
|
2287
|
+
});
|
|
2386
2288
|
}
|
|
2387
2289
|
|
|
2388
2290
|
/**
|
|
2389
2291
|
* {{> waitUrlEquals }}
|
|
2390
2292
|
*/
|
|
2391
2293
|
async waitUrlEquals(urlPart, sec = null) {
|
|
2392
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2393
|
-
const baseUrl = this.options.url
|
|
2294
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2295
|
+
const baseUrl = this.options.url;
|
|
2394
2296
|
if (urlPart.indexOf('http') < 0) {
|
|
2395
|
-
urlPart = baseUrl + urlPart
|
|
2396
|
-
}
|
|
2397
|
-
let currUrl = ''
|
|
2398
|
-
return this.browser
|
|
2399
|
-
.
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
throw e
|
|
2410
|
-
})
|
|
2297
|
+
urlPart = baseUrl + urlPart;
|
|
2298
|
+
}
|
|
2299
|
+
let currUrl = '';
|
|
2300
|
+
return this.browser.waitUntil(function () {
|
|
2301
|
+
return this.getUrl().then((res) => {
|
|
2302
|
+
currUrl = decodeUrl(res);
|
|
2303
|
+
return currUrl === urlPart;
|
|
2304
|
+
});
|
|
2305
|
+
}, aSec * 1000).catch((e) => {
|
|
2306
|
+
if (e.message.indexOf('timeout')) {
|
|
2307
|
+
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
|
|
2308
|
+
}
|
|
2309
|
+
throw e;
|
|
2310
|
+
});
|
|
2411
2311
|
}
|
|
2412
2312
|
|
|
2413
2313
|
/**
|
|
@@ -2415,48 +2315,42 @@ class WebDriver extends Helper {
|
|
|
2415
2315
|
*
|
|
2416
2316
|
*/
|
|
2417
2317
|
async waitForText(text, sec = null, context = null) {
|
|
2418
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2419
|
-
const _context = context || this.root
|
|
2420
|
-
|
|
2421
|
-
return this.browser.waitUntil(
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
{
|
|
2432
|
-
|
|
2433
|
-
timeoutMsg: `element (${_context}) is not in DOM or there is no element(${_context}) with text "${text}" after ${aSec} sec`,
|
|
2434
|
-
},
|
|
2435
|
-
)
|
|
2318
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2319
|
+
const _context = context || this.root;
|
|
2320
|
+
|
|
2321
|
+
return this.browser.waitUntil(async () => {
|
|
2322
|
+
const res = await this.$$(withStrictLocator.call(this, _context));
|
|
2323
|
+
if (!res || res.length === 0) return false;
|
|
2324
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
|
|
2325
|
+
if (Array.isArray(selected)) {
|
|
2326
|
+
return selected.filter(part => part.indexOf(text) >= 0).length > 0;
|
|
2327
|
+
}
|
|
2328
|
+
return selected.indexOf(text) >= 0;
|
|
2329
|
+
}, {
|
|
2330
|
+
timeout: aSec * 1000,
|
|
2331
|
+
timeoutMsg: `element (${_context}) is not in DOM or there is no element(${_context}) with text "${text}" after ${aSec} sec`,
|
|
2332
|
+
});
|
|
2436
2333
|
}
|
|
2437
2334
|
|
|
2438
2335
|
/**
|
|
2439
2336
|
* {{> waitForValue }}
|
|
2440
2337
|
*/
|
|
2441
2338
|
async waitForValue(field, value, sec = null) {
|
|
2442
|
-
const client = this.browser
|
|
2443
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2444
|
-
|
|
2445
|
-
return client.waitUntil(
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
{
|
|
2456
|
-
|
|
2457
|
-
timeoutMsg: `element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`,
|
|
2458
|
-
},
|
|
2459
|
-
)
|
|
2339
|
+
const client = this.browser;
|
|
2340
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2341
|
+
|
|
2342
|
+
return client.waitUntil(async () => {
|
|
2343
|
+
const res = await findFields.call(this, field);
|
|
2344
|
+
if (!res || res.length === 0) return false;
|
|
2345
|
+
const selected = await forEachAsync(res, async el => el.getValue());
|
|
2346
|
+
if (Array.isArray(selected)) {
|
|
2347
|
+
return selected.filter(part => part.indexOf(value) >= 0).length > 0;
|
|
2348
|
+
}
|
|
2349
|
+
return selected.indexOf(value) >= 0;
|
|
2350
|
+
}, {
|
|
2351
|
+
timeout: aSec * 1000,
|
|
2352
|
+
timeoutMsg: `element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`,
|
|
2353
|
+
});
|
|
2460
2354
|
}
|
|
2461
2355
|
|
|
2462
2356
|
/**
|
|
@@ -2464,241 +2358,214 @@ class WebDriver extends Helper {
|
|
|
2464
2358
|
*
|
|
2465
2359
|
*/
|
|
2466
2360
|
async waitForVisible(locator, sec = null) {
|
|
2467
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2468
|
-
|
|
2469
|
-
return this.browser.waitUntil(
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
},
|
|
2479
|
-
{
|
|
2480
|
-
timeout: aSec * 1000,
|
|
2481
|
-
timeoutMsg: `element (${new Locator(locator)}) still not visible after ${aSec} sec`,
|
|
2482
|
-
},
|
|
2483
|
-
)
|
|
2361
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2362
|
+
|
|
2363
|
+
return this.browser.waitUntil(async () => {
|
|
2364
|
+
const res = await this._res(locator);
|
|
2365
|
+
if (!res || res.length === 0) return false;
|
|
2366
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2367
|
+
if (Array.isArray(selected)) {
|
|
2368
|
+
return selected.filter(val => val === true).length > 0;
|
|
2369
|
+
}
|
|
2370
|
+
return selected;
|
|
2371
|
+
}, { timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still not visible after ${aSec} sec` });
|
|
2484
2372
|
}
|
|
2485
2373
|
|
|
2486
2374
|
/**
|
|
2487
2375
|
* {{> waitNumberOfVisibleElements }}
|
|
2488
2376
|
*/
|
|
2489
2377
|
async waitNumberOfVisibleElements(locator, num, sec = null) {
|
|
2490
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2378
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2491
2379
|
|
|
2492
|
-
return this.browser.waitUntil(
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
let selected = await forEachAsync(res, async (el) => el.isDisplayed())
|
|
2380
|
+
return this.browser.waitUntil(async () => {
|
|
2381
|
+
const res = await this._res(locator);
|
|
2382
|
+
if (!res || res.length === 0) return false;
|
|
2383
|
+
let selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2497
2384
|
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
{
|
|
2503
|
-
timeout: aSec * 1000,
|
|
2504
|
-
timeoutMsg: `The number of elements (${new Locator(locator)}) is not ${num} after ${aSec} sec`,
|
|
2505
|
-
},
|
|
2506
|
-
)
|
|
2385
|
+
if (!Array.isArray(selected)) selected = [selected];
|
|
2386
|
+
selected = selected.filter(val => val === true);
|
|
2387
|
+
return selected.length === num;
|
|
2388
|
+
}, { timeout: aSec * 1000, timeoutMsg: `The number of elements (${new Locator(locator)}) is not ${num} after ${aSec} sec` });
|
|
2507
2389
|
}
|
|
2508
2390
|
|
|
2509
2391
|
/**
|
|
2510
2392
|
* {{> waitForInvisible }}
|
|
2511
2393
|
*/
|
|
2512
2394
|
async waitForInvisible(locator, sec = null) {
|
|
2513
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2514
|
-
|
|
2515
|
-
return this.browser.waitUntil(
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
},
|
|
2522
|
-
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still visible after ${aSec} sec` },
|
|
2523
|
-
)
|
|
2395
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2396
|
+
|
|
2397
|
+
return this.browser.waitUntil(async () => {
|
|
2398
|
+
const res = await this._res(locator);
|
|
2399
|
+
if (!res || res.length === 0) return true;
|
|
2400
|
+
const selected = await forEachAsync(res, async el => el.isDisplayed());
|
|
2401
|
+
return !selected.length;
|
|
2402
|
+
}, { timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still visible after ${aSec} sec` });
|
|
2524
2403
|
}
|
|
2525
2404
|
|
|
2526
2405
|
/**
|
|
2527
2406
|
* {{> waitToHide }}
|
|
2528
2407
|
*/
|
|
2529
2408
|
async waitToHide(locator, sec = null) {
|
|
2530
|
-
return this.waitForInvisible(locator, sec)
|
|
2409
|
+
return this.waitForInvisible(locator, sec);
|
|
2531
2410
|
}
|
|
2532
2411
|
|
|
2533
2412
|
/**
|
|
2534
2413
|
* {{> waitForDetached }}
|
|
2535
2414
|
*/
|
|
2536
2415
|
async waitForDetached(locator, sec = null) {
|
|
2537
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2416
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2538
2417
|
|
|
2539
|
-
return this.browser.waitUntil(
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
},
|
|
2547
|
-
{ timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still on page after ${aSec} sec` },
|
|
2548
|
-
)
|
|
2418
|
+
return this.browser.waitUntil(async () => {
|
|
2419
|
+
const res = await this._res(locator);
|
|
2420
|
+
if (!res || res.length === 0) {
|
|
2421
|
+
return true;
|
|
2422
|
+
}
|
|
2423
|
+
return false;
|
|
2424
|
+
}, { timeout: aSec * 1000, timeoutMsg: `element (${new Locator(locator)}) still on page after ${aSec} sec` });
|
|
2549
2425
|
}
|
|
2550
2426
|
|
|
2551
2427
|
/**
|
|
2552
2428
|
* {{> waitForFunction }}
|
|
2553
2429
|
*/
|
|
2554
2430
|
async waitForFunction(fn, argsOrSec = null, sec = null) {
|
|
2555
|
-
let args = []
|
|
2431
|
+
let args = [];
|
|
2556
2432
|
if (argsOrSec) {
|
|
2557
2433
|
if (Array.isArray(argsOrSec)) {
|
|
2558
|
-
args = argsOrSec
|
|
2434
|
+
args = argsOrSec;
|
|
2559
2435
|
} else if (typeof argsOrSec === 'number') {
|
|
2560
|
-
sec = argsOrSec
|
|
2436
|
+
sec = argsOrSec;
|
|
2561
2437
|
}
|
|
2562
2438
|
}
|
|
2563
2439
|
|
|
2564
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2440
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2565
2441
|
|
|
2566
|
-
return this.browser.waitUntil(async () => this.browser.execute(fn, ...args), {
|
|
2567
|
-
timeout: aSec * 1000,
|
|
2568
|
-
timeoutMsg: '',
|
|
2569
|
-
})
|
|
2442
|
+
return this.browser.waitUntil(async () => this.browser.execute(fn, ...args), { timeout: aSec * 1000, timeoutMsg: '' });
|
|
2570
2443
|
}
|
|
2571
2444
|
|
|
2572
2445
|
/**
|
|
2573
2446
|
* {{> waitForNumberOfTabs }}
|
|
2574
2447
|
*/
|
|
2575
2448
|
async waitForNumberOfTabs(expectedTabs, sec) {
|
|
2576
|
-
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeoutInSeconds
|
|
2577
|
-
let currentTabs
|
|
2578
|
-
let count = 0
|
|
2449
|
+
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeoutInSeconds;
|
|
2450
|
+
let currentTabs;
|
|
2451
|
+
let count = 0;
|
|
2579
2452
|
|
|
2580
2453
|
do {
|
|
2581
|
-
currentTabs = await this.grabNumberOfOpenTabs()
|
|
2582
|
-
await this.wait(1)
|
|
2583
|
-
count += 1000
|
|
2584
|
-
if (currentTabs >= expectedTabs) return
|
|
2585
|
-
} while (count <= waitTimeout)
|
|
2454
|
+
currentTabs = await this.grabNumberOfOpenTabs();
|
|
2455
|
+
await this.wait(1);
|
|
2456
|
+
count += 1000;
|
|
2457
|
+
if (currentTabs >= expectedTabs) return;
|
|
2458
|
+
} while (count <= waitTimeout);
|
|
2586
2459
|
|
|
2587
|
-
throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`)
|
|
2460
|
+
throw new Error(`Expected ${expectedTabs} tabs are not met after ${waitTimeout / 1000} sec.`);
|
|
2588
2461
|
}
|
|
2589
2462
|
|
|
2590
2463
|
/**
|
|
2591
2464
|
* {{> switchTo }}
|
|
2592
2465
|
*/
|
|
2593
2466
|
async switchTo(locator) {
|
|
2594
|
-
this.browser.isInsideFrame = true
|
|
2467
|
+
this.browser.isInsideFrame = true;
|
|
2595
2468
|
if (Number.isInteger(locator)) {
|
|
2596
2469
|
if (this.options.automationProtocol) {
|
|
2597
|
-
return this.browser.switchToFrame(locator + 1)
|
|
2470
|
+
return this.browser.switchToFrame(locator + 1);
|
|
2598
2471
|
}
|
|
2599
|
-
return this.browser.switchToFrame(locator)
|
|
2472
|
+
return this.browser.switchToFrame(locator);
|
|
2600
2473
|
}
|
|
2601
2474
|
if (!locator) {
|
|
2602
|
-
return this.browser.switchToFrame(null)
|
|
2475
|
+
return this.browser.switchToFrame(null);
|
|
2603
2476
|
}
|
|
2604
2477
|
|
|
2605
|
-
let res = await this._locate(locator, true)
|
|
2606
|
-
assertElementExists(res, locator)
|
|
2607
|
-
res = usingFirstElement(res)
|
|
2608
|
-
return this.browser.switchToFrame(res)
|
|
2478
|
+
let res = await this._locate(locator, true);
|
|
2479
|
+
assertElementExists(res, locator);
|
|
2480
|
+
res = usingFirstElement(res);
|
|
2481
|
+
return this.browser.switchToFrame(res);
|
|
2609
2482
|
}
|
|
2610
2483
|
|
|
2611
2484
|
/**
|
|
2612
2485
|
* {{> switchToNextTab }}
|
|
2613
2486
|
*/
|
|
2614
2487
|
async switchToNextTab(num = 1, sec = null) {
|
|
2615
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2616
|
-
let target
|
|
2617
|
-
const current = await this.browser.getWindowHandle()
|
|
2618
|
-
|
|
2619
|
-
await this.browser.waitUntil(
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
{ timeout: aSec * 1000, timeoutMsg: `There is no ability to switch to next tab with offset ${num}` },
|
|
2629
|
-
)
|
|
2630
|
-
return this.browser.switchToWindow(target)
|
|
2488
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2489
|
+
let target;
|
|
2490
|
+
const current = await this.browser.getWindowHandle();
|
|
2491
|
+
|
|
2492
|
+
await this.browser.waitUntil(async () => {
|
|
2493
|
+
await this.browser.getWindowHandles().then((handles) => {
|
|
2494
|
+
if (handles.indexOf(current) + num + 1 <= handles.length) {
|
|
2495
|
+
target = handles[handles.indexOf(current) + num];
|
|
2496
|
+
}
|
|
2497
|
+
});
|
|
2498
|
+
return target;
|
|
2499
|
+
}, { timeout: aSec * 1000, timeoutMsg: `There is no ability to switch to next tab with offset ${num}` });
|
|
2500
|
+
return this.browser.switchToWindow(target);
|
|
2631
2501
|
}
|
|
2632
2502
|
|
|
2633
2503
|
/**
|
|
2634
2504
|
* {{> switchToPreviousTab }}
|
|
2635
2505
|
*/
|
|
2636
2506
|
async switchToPreviousTab(num = 1, sec = null) {
|
|
2637
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
2638
|
-
const current = await this.browser.getWindowHandle()
|
|
2639
|
-
let target
|
|
2640
|
-
|
|
2641
|
-
await this.browser.waitUntil(
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
{ timeout: aSec * 1000, timeoutMsg: `There is no ability to switch to previous tab with offset ${num}` },
|
|
2651
|
-
)
|
|
2652
|
-
return this.browser.switchToWindow(target)
|
|
2507
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
2508
|
+
const current = await this.browser.getWindowHandle();
|
|
2509
|
+
let target;
|
|
2510
|
+
|
|
2511
|
+
await this.browser.waitUntil(async () => {
|
|
2512
|
+
await this.browser.getWindowHandles().then((handles) => {
|
|
2513
|
+
if (handles.indexOf(current) - num > -1) {
|
|
2514
|
+
target = handles[handles.indexOf(current) - num];
|
|
2515
|
+
}
|
|
2516
|
+
});
|
|
2517
|
+
return target;
|
|
2518
|
+
}, { timeout: aSec * 1000, timeoutMsg: `There is no ability to switch to previous tab with offset ${num}` });
|
|
2519
|
+
return this.browser.switchToWindow(target);
|
|
2653
2520
|
}
|
|
2654
2521
|
|
|
2655
2522
|
/**
|
|
2656
2523
|
* {{> closeCurrentTab }}
|
|
2657
2524
|
*/
|
|
2658
2525
|
async closeCurrentTab() {
|
|
2659
|
-
await this.browser.closeWindow()
|
|
2660
|
-
const handles = await this.browser.getWindowHandles()
|
|
2661
|
-
if (handles[0]) await this.browser.switchToWindow(handles[0])
|
|
2526
|
+
await this.browser.closeWindow();
|
|
2527
|
+
const handles = await this.browser.getWindowHandles();
|
|
2528
|
+
if (handles[0]) await this.browser.switchToWindow(handles[0]);
|
|
2662
2529
|
}
|
|
2663
2530
|
|
|
2664
2531
|
/**
|
|
2665
2532
|
* {{> openNewTab }}
|
|
2666
2533
|
*/
|
|
2667
2534
|
async openNewTab(url = 'about:blank', windowName = null) {
|
|
2668
|
-
const client = this.browser
|
|
2669
|
-
const crypto = require('crypto')
|
|
2535
|
+
const client = this.browser;
|
|
2536
|
+
const crypto = require('crypto');
|
|
2670
2537
|
if (windowName == null) {
|
|
2671
|
-
windowName = crypto.randomBytes(32).toString('hex')
|
|
2538
|
+
windowName = crypto.randomBytes(32).toString('hex');
|
|
2672
2539
|
}
|
|
2673
|
-
return client.newWindow(url, windowName)
|
|
2540
|
+
return client.newWindow(url, windowName);
|
|
2674
2541
|
}
|
|
2675
2542
|
|
|
2676
2543
|
/**
|
|
2677
2544
|
* {{> grabNumberOfOpenTabs }}
|
|
2678
2545
|
*/
|
|
2679
2546
|
async grabNumberOfOpenTabs() {
|
|
2680
|
-
const pages = await this.browser.getWindowHandles()
|
|
2681
|
-
this.debugSection('Tabs', `Total ${pages.length}`)
|
|
2682
|
-
return pages.length
|
|
2547
|
+
const pages = await this.browser.getWindowHandles();
|
|
2548
|
+
this.debugSection('Tabs', `Total ${pages.length}`);
|
|
2549
|
+
return pages.length;
|
|
2683
2550
|
}
|
|
2684
2551
|
|
|
2685
2552
|
/**
|
|
2686
2553
|
* {{> refreshPage }}
|
|
2687
2554
|
*/
|
|
2688
2555
|
async refreshPage() {
|
|
2689
|
-
const client = this.browser
|
|
2690
|
-
return client.refresh()
|
|
2556
|
+
const client = this.browser;
|
|
2557
|
+
return client.refresh();
|
|
2691
2558
|
}
|
|
2692
2559
|
|
|
2693
2560
|
/**
|
|
2694
2561
|
* {{> scrollPageToTop }}
|
|
2695
2562
|
*/
|
|
2696
2563
|
scrollPageToTop() {
|
|
2697
|
-
const client = this.browser
|
|
2564
|
+
const client = this.browser;
|
|
2698
2565
|
/* eslint-disable prefer-arrow-callback */
|
|
2699
2566
|
return client.execute(function () {
|
|
2700
|
-
window.scrollTo(0, 0)
|
|
2701
|
-
})
|
|
2567
|
+
window.scrollTo(0, 0);
|
|
2568
|
+
});
|
|
2702
2569
|
/* eslint-enable */
|
|
2703
2570
|
}
|
|
2704
2571
|
|
|
@@ -2706,16 +2573,19 @@ class WebDriver extends Helper {
|
|
|
2706
2573
|
* {{> scrollPageToBottom }}
|
|
2707
2574
|
*/
|
|
2708
2575
|
scrollPageToBottom() {
|
|
2709
|
-
const client = this.browser
|
|
2576
|
+
const client = this.browser;
|
|
2710
2577
|
/* eslint-disable prefer-arrow-callback, comma-dangle */
|
|
2711
2578
|
return client.execute(function () {
|
|
2712
|
-
const body = document.body
|
|
2713
|
-
const html = document.documentElement
|
|
2714
|
-
window.scrollTo(
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2579
|
+
const body = document.body;
|
|
2580
|
+
const html = document.documentElement;
|
|
2581
|
+
window.scrollTo(0, Math.max(
|
|
2582
|
+
body.scrollHeight,
|
|
2583
|
+
body.offsetHeight,
|
|
2584
|
+
html.clientHeight,
|
|
2585
|
+
html.scrollHeight,
|
|
2586
|
+
html.offsetHeight
|
|
2587
|
+
));
|
|
2588
|
+
});
|
|
2719
2589
|
/* eslint-enable */
|
|
2720
2590
|
}
|
|
2721
2591
|
|
|
@@ -2727,11 +2597,11 @@ class WebDriver extends Helper {
|
|
|
2727
2597
|
function getScrollPosition() {
|
|
2728
2598
|
return {
|
|
2729
2599
|
x: window.pageXOffset,
|
|
2730
|
-
y: window.pageYOffset
|
|
2731
|
-
}
|
|
2600
|
+
y: window.pageYOffset
|
|
2601
|
+
};
|
|
2732
2602
|
}
|
|
2733
2603
|
/* eslint-enable comma-dangle */
|
|
2734
|
-
return this.executeScript(getScrollPosition)
|
|
2604
|
+
return this.executeScript(getScrollPosition);
|
|
2735
2605
|
}
|
|
2736
2606
|
|
|
2737
2607
|
/**
|
|
@@ -2744,15 +2614,15 @@ class WebDriver extends Helper {
|
|
|
2744
2614
|
if (!this.options.automationProtocol) {
|
|
2745
2615
|
console.log(`setGeoLocation deprecated:
|
|
2746
2616
|
* 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
|
|
2617
|
+
* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`);
|
|
2618
|
+
return;
|
|
2749
2619
|
}
|
|
2750
|
-
this.geoLocation = { latitude, longitude }
|
|
2620
|
+
this.geoLocation = { latitude, longitude };
|
|
2751
2621
|
|
|
2752
2622
|
await this.browser.call(async () => {
|
|
2753
|
-
const pages = await this.puppeteerBrowser.pages()
|
|
2754
|
-
await pages[0].setGeolocation({ latitude, longitude })
|
|
2755
|
-
})
|
|
2623
|
+
const pages = await this.puppeteerBrowser.pages();
|
|
2624
|
+
await pages[0].setGeolocation({ latitude, longitude });
|
|
2625
|
+
});
|
|
2756
2626
|
}
|
|
2757
2627
|
|
|
2758
2628
|
/**
|
|
@@ -2765,27 +2635,27 @@ class WebDriver extends Helper {
|
|
|
2765
2635
|
if (!this.options.automationProtocol) {
|
|
2766
2636
|
console.log(`grabGeoLocation deprecated:
|
|
2767
2637
|
* 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
|
|
2638
|
+
* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`);
|
|
2639
|
+
return;
|
|
2770
2640
|
}
|
|
2771
|
-
if (!this.geoLocation) return 'No GeoLocation is set!'
|
|
2772
|
-
return this.geoLocation
|
|
2641
|
+
if (!this.geoLocation) return 'No GeoLocation is set!';
|
|
2642
|
+
return this.geoLocation;
|
|
2773
2643
|
}
|
|
2774
2644
|
|
|
2775
2645
|
/**
|
|
2776
2646
|
* {{> grabElementBoundingRect }}
|
|
2777
2647
|
*/
|
|
2778
2648
|
async grabElementBoundingRect(locator, prop) {
|
|
2779
|
-
const res = await this._locate(locator, true)
|
|
2780
|
-
assertElementExists(res, locator)
|
|
2781
|
-
const el = usingFirstElement(res)
|
|
2649
|
+
const res = await this._locate(locator, true);
|
|
2650
|
+
assertElementExists(res, locator);
|
|
2651
|
+
const el = usingFirstElement(res);
|
|
2782
2652
|
|
|
2783
2653
|
const rect = {
|
|
2784
2654
|
...(await el.getLocation()),
|
|
2785
2655
|
...(await el.getSize()),
|
|
2786
|
-
}
|
|
2787
|
-
if (prop) return rect[prop]
|
|
2788
|
-
return rect
|
|
2656
|
+
};
|
|
2657
|
+
if (prop) return rect[prop];
|
|
2658
|
+
return rect;
|
|
2789
2659
|
}
|
|
2790
2660
|
|
|
2791
2661
|
/**
|
|
@@ -2794,21 +2664,23 @@ class WebDriver extends Helper {
|
|
|
2794
2664
|
* @param {*} fn
|
|
2795
2665
|
*/
|
|
2796
2666
|
/* eslint-disable */
|
|
2797
|
-
runOnIOS(caps, fn) {
|
|
2667
|
+
runOnIOS(caps, fn) {
|
|
2668
|
+
}
|
|
2798
2669
|
|
|
2799
2670
|
/**
|
|
2800
2671
|
* Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
|
|
2801
2672
|
* @param {*} caps
|
|
2802
2673
|
* @param {*} fn
|
|
2803
2674
|
*/
|
|
2804
|
-
runOnAndroid(caps, fn) {
|
|
2675
|
+
runOnAndroid(caps, fn) {
|
|
2676
|
+
}
|
|
2805
2677
|
/* eslint-enable */
|
|
2806
2678
|
|
|
2807
2679
|
/**
|
|
2808
2680
|
* Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
|
|
2809
2681
|
*/
|
|
2810
2682
|
runInWeb(fn) {
|
|
2811
|
-
return fn()
|
|
2683
|
+
return fn();
|
|
2812
2684
|
}
|
|
2813
2685
|
|
|
2814
2686
|
/**
|
|
@@ -2819,12 +2691,10 @@ class WebDriver extends Helper {
|
|
|
2819
2691
|
*/
|
|
2820
2692
|
flushNetworkTraffics() {
|
|
2821
2693
|
if (!this.options.automationProtocol) {
|
|
2822
|
-
console.log(
|
|
2823
|
-
|
|
2824
|
-
)
|
|
2825
|
-
return
|
|
2694
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2695
|
+
return;
|
|
2826
2696
|
}
|
|
2827
|
-
this.requests = []
|
|
2697
|
+
this.requests = [];
|
|
2828
2698
|
}
|
|
2829
2699
|
|
|
2830
2700
|
/**
|
|
@@ -2835,13 +2705,11 @@ class WebDriver extends Helper {
|
|
|
2835
2705
|
*/
|
|
2836
2706
|
stopRecordingTraffic() {
|
|
2837
2707
|
if (!this.options.automationProtocol) {
|
|
2838
|
-
console.log(
|
|
2839
|
-
|
|
2840
|
-
)
|
|
2841
|
-
return
|
|
2708
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2709
|
+
return;
|
|
2842
2710
|
}
|
|
2843
|
-
this.page.removeAllListeners('request')
|
|
2844
|
-
this.recording = false
|
|
2711
|
+
this.page.removeAllListeners('request');
|
|
2712
|
+
this.recording = false;
|
|
2845
2713
|
}
|
|
2846
2714
|
|
|
2847
2715
|
/**
|
|
@@ -2853,16 +2721,15 @@ class WebDriver extends Helper {
|
|
|
2853
2721
|
*/
|
|
2854
2722
|
async startRecordingTraffic() {
|
|
2855
2723
|
if (!this.options.automationProtocol) {
|
|
2856
|
-
console.log(
|
|
2857
|
-
|
|
2858
|
-
)
|
|
2859
|
-
return
|
|
2724
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2725
|
+
return;
|
|
2860
2726
|
}
|
|
2861
|
-
this.flushNetworkTraffics()
|
|
2862
|
-
this.recording = true
|
|
2863
|
-
this.recordedAtLeastOnce = true
|
|
2727
|
+
this.flushNetworkTraffics();
|
|
2728
|
+
this.recording = true;
|
|
2729
|
+
this.recordedAtLeastOnce = true;
|
|
2864
2730
|
|
|
2865
|
-
await this.
|
|
2731
|
+
this.page = (await this.puppeteerBrowser.pages())[0];
|
|
2732
|
+
await this.page.setRequestInterception(true);
|
|
2866
2733
|
|
|
2867
2734
|
this.page.on('request', (request) => {
|
|
2868
2735
|
const information = {
|
|
@@ -2871,16 +2738,16 @@ class WebDriver extends Helper {
|
|
|
2871
2738
|
requestHeaders: request.headers(),
|
|
2872
2739
|
requestPostData: request.postData(),
|
|
2873
2740
|
response: request.response(),
|
|
2874
|
-
}
|
|
2741
|
+
};
|
|
2875
2742
|
|
|
2876
|
-
this.debugSection('REQUEST: ', JSON.stringify(information))
|
|
2743
|
+
this.debugSection('REQUEST: ', JSON.stringify(information));
|
|
2877
2744
|
|
|
2878
2745
|
if (typeof information.requestPostData === 'object') {
|
|
2879
|
-
information.requestPostData = JSON.parse(information.requestPostData)
|
|
2746
|
+
information.requestPostData = JSON.parse(information.requestPostData);
|
|
2880
2747
|
}
|
|
2881
|
-
request.continue()
|
|
2882
|
-
this.requests.push(information)
|
|
2883
|
-
})
|
|
2748
|
+
request.continue();
|
|
2749
|
+
this.requests.push(information);
|
|
2750
|
+
});
|
|
2884
2751
|
}
|
|
2885
2752
|
|
|
2886
2753
|
/**
|
|
@@ -2891,12 +2758,10 @@ class WebDriver extends Helper {
|
|
|
2891
2758
|
*/
|
|
2892
2759
|
async grabRecordedNetworkTraffics() {
|
|
2893
2760
|
if (!this.options.automationProtocol) {
|
|
2894
|
-
console.log(
|
|
2895
|
-
|
|
2896
|
-
)
|
|
2897
|
-
return
|
|
2761
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2762
|
+
return;
|
|
2898
2763
|
}
|
|
2899
|
-
return grabRecordedNetworkTraffics.call(this)
|
|
2764
|
+
return grabRecordedNetworkTraffics.call(this);
|
|
2900
2765
|
}
|
|
2901
2766
|
|
|
2902
2767
|
/**
|
|
@@ -2905,14 +2770,14 @@ class WebDriver extends Helper {
|
|
|
2905
2770
|
*
|
|
2906
2771
|
* {{> seeTraffic }}
|
|
2907
2772
|
*/
|
|
2908
|
-
async seeTraffic({
|
|
2773
|
+
async seeTraffic({
|
|
2774
|
+
name, url, parameters, requestPostData, timeout = 10,
|
|
2775
|
+
}) {
|
|
2909
2776
|
if (!this.options.automationProtocol) {
|
|
2910
|
-
console.log(
|
|
2911
|
-
|
|
2912
|
-
)
|
|
2913
|
-
return
|
|
2777
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2778
|
+
return;
|
|
2914
2779
|
}
|
|
2915
|
-
await seeTraffic.call(this, ...arguments)
|
|
2780
|
+
await seeTraffic.call(this, ...arguments);
|
|
2916
2781
|
}
|
|
2917
2782
|
|
|
2918
2783
|
/**
|
|
@@ -2924,40 +2789,38 @@ class WebDriver extends Helper {
|
|
|
2924
2789
|
*/
|
|
2925
2790
|
dontSeeTraffic({ name, url }) {
|
|
2926
2791
|
if (!this.options.automationProtocol) {
|
|
2927
|
-
console.log(
|
|
2928
|
-
|
|
2929
|
-
)
|
|
2930
|
-
return
|
|
2792
|
+
console.log('* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration');
|
|
2793
|
+
return;
|
|
2931
2794
|
}
|
|
2932
|
-
dontSeeTraffic.call(this, ...arguments)
|
|
2795
|
+
dontSeeTraffic.call(this, ...arguments);
|
|
2933
2796
|
}
|
|
2934
2797
|
}
|
|
2935
2798
|
|
|
2936
2799
|
async function proceedSee(assertType, text, context, strict = false) {
|
|
2937
|
-
let description
|
|
2800
|
+
let description;
|
|
2938
2801
|
if (!context) {
|
|
2939
2802
|
if (this.context === webRoot) {
|
|
2940
|
-
context = this.context
|
|
2941
|
-
description = 'web page'
|
|
2803
|
+
context = this.context;
|
|
2804
|
+
description = 'web page';
|
|
2942
2805
|
} else {
|
|
2943
|
-
description = `current context ${this.context}
|
|
2944
|
-
context = './/*'
|
|
2806
|
+
description = `current context ${this.context}`;
|
|
2807
|
+
context = './/*';
|
|
2945
2808
|
}
|
|
2946
2809
|
} else {
|
|
2947
|
-
description = `element ${context}
|
|
2810
|
+
description = `element ${context}`;
|
|
2948
2811
|
}
|
|
2949
2812
|
|
|
2950
|
-
const smartWaitEnabled = assertType === 'assert'
|
|
2951
|
-
const res = await this._locate(withStrictLocator(context), smartWaitEnabled)
|
|
2952
|
-
assertElementExists(res, context)
|
|
2953
|
-
const selected = await forEachAsync(res, async
|
|
2813
|
+
const smartWaitEnabled = assertType === 'assert';
|
|
2814
|
+
const res = await this._locate(withStrictLocator(context), smartWaitEnabled);
|
|
2815
|
+
assertElementExists(res, context);
|
|
2816
|
+
const selected = await forEachAsync(res, async el => this.browser.getElementText(getElementId(el)));
|
|
2954
2817
|
if (strict) {
|
|
2955
2818
|
if (Array.isArray(selected) && selected.length !== 0) {
|
|
2956
|
-
return selected.map(
|
|
2819
|
+
return selected.map(elText => equals(description)[assertType](text, elText));
|
|
2957
2820
|
}
|
|
2958
|
-
return equals(description)[assertType](text, selected)
|
|
2821
|
+
return equals(description)[assertType](text, selected);
|
|
2959
2822
|
}
|
|
2960
|
-
return stringIncludes(description)[assertType](text, selected)
|
|
2823
|
+
return stringIncludes(description)[assertType](text, selected);
|
|
2961
2824
|
}
|
|
2962
2825
|
|
|
2963
2826
|
/**
|
|
@@ -2974,19 +2837,21 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
2974
2837
|
* @return {Promise<Array>} - Array of values.
|
|
2975
2838
|
*/
|
|
2976
2839
|
async function forEachAsync(array, callback, options = { expandArrayResults: true }) {
|
|
2977
|
-
const {
|
|
2978
|
-
|
|
2979
|
-
|
|
2840
|
+
const {
|
|
2841
|
+
expandArrayResults = true,
|
|
2842
|
+
} = options;
|
|
2843
|
+
const inputArray = Array.isArray(array) ? array : [array];
|
|
2844
|
+
const values = [];
|
|
2980
2845
|
for (let index = 0; index < inputArray.length; index++) {
|
|
2981
|
-
const res = await callback(inputArray[index], index, inputArray)
|
|
2846
|
+
const res = await callback(inputArray[index], index, inputArray);
|
|
2982
2847
|
|
|
2983
2848
|
if (Array.isArray(res) && expandArrayResults) {
|
|
2984
|
-
res.forEach(
|
|
2849
|
+
res.forEach(val => values.push(val));
|
|
2985
2850
|
} else if (res) {
|
|
2986
|
-
values.push(res)
|
|
2851
|
+
values.push(res);
|
|
2987
2852
|
}
|
|
2988
2853
|
}
|
|
2989
|
-
return values
|
|
2854
|
+
return values;
|
|
2990
2855
|
}
|
|
2991
2856
|
|
|
2992
2857
|
/**
|
|
@@ -3001,380 +2866,374 @@ async function forEachAsync(array, callback, options = { expandArrayResults: tru
|
|
|
3001
2866
|
* @return {Promise<Array>} - Array of values.
|
|
3002
2867
|
*/
|
|
3003
2868
|
async function filterAsync(array, callback) {
|
|
3004
|
-
const inputArray = Array.isArray(array) ? array : [array]
|
|
3005
|
-
const values = []
|
|
2869
|
+
const inputArray = Array.isArray(array) ? array : [array];
|
|
2870
|
+
const values = [];
|
|
3006
2871
|
for (let index = 0; index < inputArray.length; index++) {
|
|
3007
|
-
const res = await callback(inputArray[index], index, inputArray)
|
|
3008
|
-
const value = Array.isArray(res) ? res[0] : res
|
|
2872
|
+
const res = await callback(inputArray[index], index, inputArray);
|
|
2873
|
+
const value = Array.isArray(res) ? res[0] : res;
|
|
3009
2874
|
|
|
3010
2875
|
if (value) {
|
|
3011
|
-
values.push(inputArray[index])
|
|
2876
|
+
values.push(inputArray[index]);
|
|
3012
2877
|
}
|
|
3013
2878
|
}
|
|
3014
|
-
return values
|
|
2879
|
+
return values;
|
|
3015
2880
|
}
|
|
3016
2881
|
|
|
3017
2882
|
async function findClickable(locator, locateFn) {
|
|
3018
|
-
locator = new Locator(locator)
|
|
2883
|
+
locator = new Locator(locator);
|
|
3019
2884
|
|
|
3020
2885
|
if (this._isCustomLocator(locator)) {
|
|
3021
|
-
return locateFn(locator.value)
|
|
2886
|
+
return locateFn(locator.value);
|
|
3022
2887
|
}
|
|
3023
2888
|
|
|
3024
|
-
if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true)
|
|
3025
|
-
if (!locator.isFuzzy()) return locateFn(locator, true)
|
|
2889
|
+
if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true);
|
|
2890
|
+
if (!locator.isFuzzy()) return locateFn(locator, true);
|
|
3026
2891
|
|
|
3027
|
-
let els
|
|
3028
|
-
const literal = xpathLocator.literal(locator.value)
|
|
2892
|
+
let els;
|
|
2893
|
+
const literal = xpathLocator.literal(locator.value);
|
|
3029
2894
|
|
|
3030
|
-
els = await locateFn(Locator.clickable.narrow(literal))
|
|
3031
|
-
if (els.length) return els
|
|
2895
|
+
els = await locateFn(Locator.clickable.narrow(literal));
|
|
2896
|
+
if (els.length) return els;
|
|
3032
2897
|
|
|
3033
|
-
els = await locateFn(Locator.clickable.wide(literal))
|
|
3034
|
-
if (els.length) return els
|
|
2898
|
+
els = await locateFn(Locator.clickable.wide(literal));
|
|
2899
|
+
if (els.length) return els;
|
|
3035
2900
|
|
|
3036
|
-
els = await locateFn(Locator.clickable.self(literal))
|
|
3037
|
-
if (els.length) return els
|
|
2901
|
+
els = await locateFn(Locator.clickable.self(literal));
|
|
2902
|
+
if (els.length) return els;
|
|
3038
2903
|
|
|
3039
|
-
return locateFn(locator.value) // by css or xpath
|
|
2904
|
+
return locateFn(locator.value); // by css or xpath
|
|
3040
2905
|
}
|
|
3041
2906
|
|
|
3042
2907
|
async function findFields(locator) {
|
|
3043
|
-
locator = new Locator(locator)
|
|
2908
|
+
locator = new Locator(locator);
|
|
3044
2909
|
|
|
3045
2910
|
if (this._isCustomLocator(locator)) {
|
|
3046
|
-
return this._locate(locator)
|
|
2911
|
+
return this._locate(locator);
|
|
3047
2912
|
}
|
|
3048
2913
|
|
|
3049
|
-
if (locator.isAccessibilityId() && !this.isWeb) return this._locate(locator, true)
|
|
3050
|
-
if (!locator.isFuzzy()) return this._locate(locator, true)
|
|
2914
|
+
if (locator.isAccessibilityId() && !this.isWeb) return this._locate(locator, true);
|
|
2915
|
+
if (!locator.isFuzzy()) return this._locate(locator, true);
|
|
3051
2916
|
|
|
3052
|
-
const literal = xpathLocator.literal(locator.value)
|
|
3053
|
-
let els = await this._locate(Locator.field.labelEquals(literal))
|
|
3054
|
-
if (els.length) return els
|
|
2917
|
+
const literal = xpathLocator.literal(locator.value);
|
|
2918
|
+
let els = await this._locate(Locator.field.labelEquals(literal));
|
|
2919
|
+
if (els.length) return els;
|
|
3055
2920
|
|
|
3056
|
-
els = await this._locate(Locator.field.labelContains(literal))
|
|
3057
|
-
if (els.length) return els
|
|
2921
|
+
els = await this._locate(Locator.field.labelContains(literal));
|
|
2922
|
+
if (els.length) return els;
|
|
3058
2923
|
|
|
3059
|
-
els = await this._locate(Locator.field.byName(literal))
|
|
3060
|
-
if (els.length) return els
|
|
3061
|
-
return this._locate(locator.value) // by css or xpath
|
|
2924
|
+
els = await this._locate(Locator.field.byName(literal));
|
|
2925
|
+
if (els.length) return els;
|
|
2926
|
+
return this._locate(locator.value); // by css or xpath
|
|
3062
2927
|
}
|
|
3063
2928
|
|
|
3064
2929
|
async function proceedSeeField(assertType, field, value) {
|
|
3065
|
-
const res = await findFields.call(this, field)
|
|
3066
|
-
assertElementExists(res, field, 'Field')
|
|
3067
|
-
const elem = usingFirstElement(res)
|
|
3068
|
-
const elemId = getElementId(elem)
|
|
2930
|
+
const res = await findFields.call(this, field);
|
|
2931
|
+
assertElementExists(res, field, 'Field');
|
|
2932
|
+
const elem = usingFirstElement(res);
|
|
2933
|
+
const elemId = getElementId(elem);
|
|
3069
2934
|
|
|
3070
2935
|
const proceedMultiple = async (fields) => {
|
|
3071
|
-
const fieldResults = toArray(
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
}),
|
|
3076
|
-
)
|
|
2936
|
+
const fieldResults = toArray(await forEachAsync(fields, async (el) => {
|
|
2937
|
+
const elementId = getElementId(el);
|
|
2938
|
+
return this.browser.isW3C ? el.getValue() : this.browser.getElementAttribute(elementId, 'value');
|
|
2939
|
+
}));
|
|
3077
2940
|
|
|
3078
2941
|
if (typeof value === 'boolean') {
|
|
3079
|
-
equals(`no. of items matching > 0: ${field}`)[assertType](value, !!fieldResults.length)
|
|
2942
|
+
equals(`no. of items matching > 0: ${field}`)[assertType](value, !!fieldResults.length);
|
|
3080
2943
|
} else {
|
|
3081
2944
|
// Assert that results were found so the forEach assert does not silently pass
|
|
3082
|
-
equals(`no. of items matching > 0: ${field}`)[assertType](true, !!fieldResults.length)
|
|
3083
|
-
fieldResults.forEach(
|
|
2945
|
+
equals(`no. of items matching > 0: ${field}`)[assertType](true, !!fieldResults.length);
|
|
2946
|
+
fieldResults.forEach(val => stringIncludes(`fields by ${field}`)[assertType](value, val));
|
|
3084
2947
|
}
|
|
3085
|
-
}
|
|
2948
|
+
};
|
|
3086
2949
|
|
|
3087
|
-
const proceedSingle = (
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
})
|
|
2950
|
+
const proceedSingle = el => el.getValue().then((res) => {
|
|
2951
|
+
if (res === null) {
|
|
2952
|
+
throw new Error(`Element ${el.selector} has no value attribute`);
|
|
2953
|
+
}
|
|
2954
|
+
stringIncludes(`fields by ${field}`)[assertType](value, res);
|
|
2955
|
+
});
|
|
3094
2956
|
|
|
3095
|
-
const filterBySelected = async (elements
|
|
3096
|
-
filterAsync(elements, async (el) => this.browser.isElementSelected(getElementId(el)))
|
|
2957
|
+
const filterBySelected = async elements => filterAsync(elements, async el => this.browser.isElementSelected(getElementId(el)));
|
|
3097
2958
|
|
|
3098
2959
|
const filterSelectedByValue = async (elements, value) => {
|
|
3099
2960
|
return filterAsync(elements, async (el) => {
|
|
3100
|
-
const elementId = getElementId(el)
|
|
3101
|
-
const currentValue = this.browser.isW3C
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
const tag = await elem.getTagName()
|
|
2961
|
+
const elementId = getElementId(el);
|
|
2962
|
+
const currentValue = this.browser.isW3C ? await el.getValue() : await this.browser.getElementAttribute(elementId, 'value');
|
|
2963
|
+
const isSelected = await this.browser.isElementSelected(elementId);
|
|
2964
|
+
return currentValue === value && isSelected;
|
|
2965
|
+
});
|
|
2966
|
+
};
|
|
2967
|
+
|
|
2968
|
+
const tag = await elem.getTagName();
|
|
3110
2969
|
if (tag === 'select') {
|
|
3111
|
-
const subOptions = await this.browser.findElementsFromElement(elemId, 'css', 'option')
|
|
2970
|
+
const subOptions = await this.browser.findElementsFromElement(elemId, 'css', 'option');
|
|
3112
2971
|
|
|
3113
2972
|
if (value === '') {
|
|
3114
2973
|
// Don't filter by value
|
|
3115
|
-
const selectedOptions = await filterBySelected(subOptions)
|
|
3116
|
-
return proceedMultiple(selectedOptions)
|
|
2974
|
+
const selectedOptions = await filterBySelected(subOptions);
|
|
2975
|
+
return proceedMultiple(selectedOptions);
|
|
3117
2976
|
}
|
|
3118
2977
|
|
|
3119
|
-
const options = await filterSelectedByValue(subOptions, value)
|
|
3120
|
-
return proceedMultiple(options)
|
|
2978
|
+
const options = await filterSelectedByValue(subOptions, value);
|
|
2979
|
+
return proceedMultiple(options);
|
|
3121
2980
|
}
|
|
3122
2981
|
|
|
3123
2982
|
if (tag === 'input') {
|
|
3124
|
-
const fieldType = await elem.getAttribute('type')
|
|
2983
|
+
const fieldType = await elem.getAttribute('type');
|
|
3125
2984
|
|
|
3126
2985
|
if (fieldType === 'checkbox' || fieldType === 'radio') {
|
|
3127
2986
|
if (typeof value === 'boolean') {
|
|
3128
2987
|
// Support boolean values
|
|
3129
|
-
const options = await filterBySelected(res)
|
|
3130
|
-
return proceedMultiple(options)
|
|
2988
|
+
const options = await filterBySelected(res);
|
|
2989
|
+
return proceedMultiple(options);
|
|
3131
2990
|
}
|
|
3132
2991
|
|
|
3133
|
-
const options = await filterSelectedByValue(res, value)
|
|
3134
|
-
return proceedMultiple(options)
|
|
2992
|
+
const options = await filterSelectedByValue(res, value);
|
|
2993
|
+
return proceedMultiple(options);
|
|
3135
2994
|
}
|
|
3136
|
-
return proceedSingle(elem)
|
|
2995
|
+
return proceedSingle(elem);
|
|
3137
2996
|
}
|
|
3138
|
-
return proceedSingle(elem)
|
|
2997
|
+
return proceedSingle(elem);
|
|
3139
2998
|
}
|
|
3140
2999
|
|
|
3141
3000
|
function toArray(item) {
|
|
3142
3001
|
if (!Array.isArray(item)) {
|
|
3143
|
-
return [item]
|
|
3002
|
+
return [item];
|
|
3144
3003
|
}
|
|
3145
|
-
return item
|
|
3004
|
+
return item;
|
|
3146
3005
|
}
|
|
3147
3006
|
|
|
3148
3007
|
async function proceedSeeCheckbox(assertType, field) {
|
|
3149
|
-
const res = await findFields.call(this, field)
|
|
3150
|
-
assertElementExists(res, field, 'Field')
|
|
3008
|
+
const res = await findFields.call(this, field);
|
|
3009
|
+
assertElementExists(res, field, 'Field');
|
|
3151
3010
|
|
|
3152
|
-
const selected = await forEachAsync(res, async
|
|
3153
|
-
return truth(`checkable field "${field}"`, 'to be checked')[assertType](selected)
|
|
3011
|
+
const selected = await forEachAsync(res, async el => this.browser.isElementSelected(getElementId(el)));
|
|
3012
|
+
return truth(`checkable field "${field}"`, 'to be checked')[assertType](selected);
|
|
3154
3013
|
}
|
|
3155
3014
|
|
|
3156
3015
|
async function findCheckable(locator, locateFn) {
|
|
3157
|
-
let els
|
|
3158
|
-
locator = new Locator(locator)
|
|
3016
|
+
let els;
|
|
3017
|
+
locator = new Locator(locator);
|
|
3159
3018
|
|
|
3160
3019
|
if (this._isCustomLocator(locator)) {
|
|
3161
|
-
return locateFn(locator.value)
|
|
3020
|
+
return locateFn(locator.value);
|
|
3162
3021
|
}
|
|
3163
3022
|
|
|
3164
|
-
if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true)
|
|
3165
|
-
if (!locator.isFuzzy()) return locateFn(locator, true)
|
|
3023
|
+
if (locator.isAccessibilityId() && !this.isWeb) return locateFn(locator, true);
|
|
3024
|
+
if (!locator.isFuzzy()) return locateFn(locator, true);
|
|
3166
3025
|
|
|
3167
|
-
const literal = xpathLocator.literal(locator.value)
|
|
3168
|
-
els = await locateFn(Locator.checkable.byText(literal))
|
|
3169
|
-
if (els.length) return els
|
|
3170
|
-
els = await locateFn(Locator.checkable.byName(literal))
|
|
3171
|
-
if (els.length) return els
|
|
3026
|
+
const literal = xpathLocator.literal(locator.value);
|
|
3027
|
+
els = await locateFn(Locator.checkable.byText(literal));
|
|
3028
|
+
if (els.length) return els;
|
|
3029
|
+
els = await locateFn(Locator.checkable.byName(literal));
|
|
3030
|
+
if (els.length) return els;
|
|
3172
3031
|
|
|
3173
|
-
return locateFn(locator.value) // by css or xpath
|
|
3032
|
+
return locateFn(locator.value); // by css or xpath
|
|
3174
3033
|
}
|
|
3175
3034
|
|
|
3176
3035
|
function withStrictLocator(locator) {
|
|
3177
|
-
locator = new Locator(locator)
|
|
3178
|
-
return locator.simplify()
|
|
3036
|
+
locator = new Locator(locator);
|
|
3037
|
+
return locator.simplify();
|
|
3179
3038
|
}
|
|
3180
3039
|
|
|
3181
3040
|
function isFrameLocator(locator) {
|
|
3182
|
-
locator = new Locator(locator)
|
|
3183
|
-
if (locator.isFrame()) return locator.value
|
|
3184
|
-
return false
|
|
3041
|
+
locator = new Locator(locator);
|
|
3042
|
+
if (locator.isFrame()) return locator.value;
|
|
3043
|
+
return false;
|
|
3185
3044
|
}
|
|
3186
3045
|
|
|
3187
3046
|
function assertElementExists(res, locator, prefix, suffix) {
|
|
3188
3047
|
if (!res || res.length === 0) {
|
|
3189
|
-
throw new ElementNotFound(locator, prefix, suffix)
|
|
3048
|
+
throw new ElementNotFound(locator, prefix, suffix);
|
|
3190
3049
|
}
|
|
3191
3050
|
}
|
|
3192
3051
|
|
|
3193
3052
|
function usingFirstElement(els) {
|
|
3194
|
-
if (els.length > 1) debug(`[Elements] Using first element out of ${els.length}`)
|
|
3195
|
-
return els[0]
|
|
3053
|
+
if (els.length > 1) debug(`[Elements] Using first element out of ${els.length}`);
|
|
3054
|
+
return els[0];
|
|
3196
3055
|
}
|
|
3197
3056
|
|
|
3198
3057
|
function getElementId(el) {
|
|
3199
3058
|
// W3C WebDriver web element identifier
|
|
3200
3059
|
// https://w3c.github.io/webdriver/#dfn-web-element-identifier
|
|
3201
3060
|
if (el['element-6066-11e4-a52e-4f735466cecf']) {
|
|
3202
|
-
return el['element-6066-11e4-a52e-4f735466cecf']
|
|
3061
|
+
return el['element-6066-11e4-a52e-4f735466cecf'];
|
|
3203
3062
|
}
|
|
3204
3063
|
// (deprecated) JsonWireProtocol identifier
|
|
3205
3064
|
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#webelement-json-object
|
|
3206
3065
|
if (el.ELEMENT) {
|
|
3207
|
-
return el.ELEMENT
|
|
3066
|
+
return el.ELEMENT;
|
|
3208
3067
|
}
|
|
3209
3068
|
|
|
3210
|
-
return null
|
|
3069
|
+
return null;
|
|
3211
3070
|
}
|
|
3212
3071
|
|
|
3213
3072
|
// List of known key values to unicode code points
|
|
3214
3073
|
// https://www.w3.org/TR/webdriver/#keyboard-actions
|
|
3215
3074
|
const keyUnicodeMap = {
|
|
3216
3075
|
/* eslint-disable quote-props */
|
|
3217
|
-
Unidentified: '\uE000',
|
|
3218
|
-
Cancel: '\uE001',
|
|
3219
|
-
Clear: '\uE005',
|
|
3220
|
-
Help: '\uE002',
|
|
3221
|
-
Pause: '\uE00B',
|
|
3222
|
-
Backspace: '\uE003',
|
|
3223
|
-
Return: '\uE006',
|
|
3224
|
-
Enter: '\uE007',
|
|
3225
|
-
Escape: '\uE00C',
|
|
3226
|
-
Alt: '\uE00A',
|
|
3227
|
-
AltLeft: '\uE00A',
|
|
3228
|
-
AltRight: '\uE052',
|
|
3229
|
-
Control: '\uE009',
|
|
3230
|
-
ControlLeft: '\uE009',
|
|
3231
|
-
ControlRight: '\uE051',
|
|
3232
|
-
Meta: '\uE03D',
|
|
3233
|
-
MetaLeft: '\uE03D',
|
|
3234
|
-
MetaRight: '\uE053',
|
|
3235
|
-
Shift: '\uE008',
|
|
3236
|
-
ShiftLeft: '\uE008',
|
|
3237
|
-
ShiftRight: '\uE050',
|
|
3238
|
-
Space: '\uE00D',
|
|
3076
|
+
'Unidentified': '\uE000',
|
|
3077
|
+
'Cancel': '\uE001',
|
|
3078
|
+
'Clear': '\uE005',
|
|
3079
|
+
'Help': '\uE002',
|
|
3080
|
+
'Pause': '\uE00B',
|
|
3081
|
+
'Backspace': '\uE003',
|
|
3082
|
+
'Return': '\uE006',
|
|
3083
|
+
'Enter': '\uE007',
|
|
3084
|
+
'Escape': '\uE00C',
|
|
3085
|
+
'Alt': '\uE00A',
|
|
3086
|
+
'AltLeft': '\uE00A',
|
|
3087
|
+
'AltRight': '\uE052',
|
|
3088
|
+
'Control': '\uE009',
|
|
3089
|
+
'ControlLeft': '\uE009',
|
|
3090
|
+
'ControlRight': '\uE051',
|
|
3091
|
+
'Meta': '\uE03D',
|
|
3092
|
+
'MetaLeft': '\uE03D',
|
|
3093
|
+
'MetaRight': '\uE053',
|
|
3094
|
+
'Shift': '\uE008',
|
|
3095
|
+
'ShiftLeft': '\uE008',
|
|
3096
|
+
'ShiftRight': '\uE050',
|
|
3097
|
+
'Space': '\uE00D',
|
|
3239
3098
|
' ': '\uE00D',
|
|
3240
|
-
Tab: '\uE004',
|
|
3241
|
-
Insert: '\uE016',
|
|
3242
|
-
Delete: '\uE017',
|
|
3243
|
-
End: '\uE010',
|
|
3244
|
-
Home: '\uE011',
|
|
3245
|
-
PageUp: '\uE00E',
|
|
3246
|
-
PageDown: '\uE00F',
|
|
3247
|
-
ArrowDown: '\uE015',
|
|
3248
|
-
ArrowLeft: '\uE012',
|
|
3249
|
-
ArrowRight: '\uE014',
|
|
3250
|
-
ArrowUp: '\uE013',
|
|
3251
|
-
F1: '\uE031',
|
|
3252
|
-
F2: '\uE032',
|
|
3253
|
-
F3: '\uE033',
|
|
3254
|
-
F4: '\uE034',
|
|
3255
|
-
F5: '\uE035',
|
|
3256
|
-
F6: '\uE036',
|
|
3257
|
-
F7: '\uE037',
|
|
3258
|
-
F8: '\uE038',
|
|
3259
|
-
F9: '\uE039',
|
|
3260
|
-
F10: '\uE03A',
|
|
3261
|
-
F11: '\uE03B',
|
|
3262
|
-
F12: '\uE03C',
|
|
3263
|
-
Numpad0: '\uE01A',
|
|
3264
|
-
Numpad1: '\uE01B',
|
|
3265
|
-
Numpad2: '\uE01C',
|
|
3266
|
-
Numpad3: '\uE01D',
|
|
3267
|
-
Numpad4: '\uE01E',
|
|
3268
|
-
Numpad5: '\uE01F',
|
|
3269
|
-
Numpad6: '\uE020',
|
|
3270
|
-
Numpad7: '\uE021',
|
|
3271
|
-
Numpad8: '\uE022',
|
|
3272
|
-
Numpad9: '\uE023',
|
|
3273
|
-
NumpadMultiply: '\uE024',
|
|
3274
|
-
NumpadAdd: '\uE025',
|
|
3275
|
-
NumpadSubtract: '\uE027',
|
|
3276
|
-
NumpadDecimal: '\uE028',
|
|
3277
|
-
NumpadDivide: '\uE029',
|
|
3278
|
-
NumpadEnter: '\uE007',
|
|
3279
|
-
NumpadInsert: '\uE05C', // 'Numpad0' alternate (when NumLock off)
|
|
3280
|
-
NumpadDelete: '\uE05D', // 'NumpadDecimal' alternate (when NumLock off)
|
|
3281
|
-
NumpadEnd: '\uE056', // 'Numpad1' alternate (when NumLock off)
|
|
3282
|
-
NumpadHome: '\uE057', // 'Numpad7' alternate (when NumLock off)
|
|
3283
|
-
NumpadPageDown: '\uE055', // 'Numpad3' alternate (when NumLock off)
|
|
3284
|
-
NumpadPageUp: '\uE054', // 'Numpad9' alternate (when NumLock off)
|
|
3285
|
-
NumpadArrowDown: '\uE05B', // 'Numpad2' alternate (when NumLock off)
|
|
3286
|
-
NumpadArrowLeft: '\uE058', // 'Numpad4' alternate (when NumLock off)
|
|
3287
|
-
NumpadArrowRight: '\uE05A', // 'Numpad6' alternate (when NumLock off)
|
|
3288
|
-
NumpadArrowUp: '\uE059', // 'Numpad8' alternate (when NumLock off)
|
|
3289
|
-
Comma: '\uE026', // ',' alias
|
|
3290
|
-
Digit0: '0', // '0' alias
|
|
3291
|
-
Digit1: '1', // '1' alias
|
|
3292
|
-
Digit2: '2', // '2' alias
|
|
3293
|
-
Digit3: '3', // '3' alias
|
|
3294
|
-
Digit4: '4', // '4' alias
|
|
3295
|
-
Digit5: '5', // '5' alias
|
|
3296
|
-
Digit6: '6', // '6' alias
|
|
3297
|
-
Digit7: '7', // '7' alias
|
|
3298
|
-
Digit8: '8', // '8' alias
|
|
3299
|
-
Digit9: '9', // '9' alias
|
|
3300
|
-
Equal: '\uE019', // '=' alias
|
|
3301
|
-
KeyA: 'a', // 'a' alias
|
|
3302
|
-
KeyB: 'b', // 'b' alias
|
|
3303
|
-
KeyC: 'c', // 'c' alias
|
|
3304
|
-
KeyD: 'd', // 'd' alias
|
|
3305
|
-
KeyE: 'e', // 'e' alias
|
|
3306
|
-
KeyF: 'f', // 'f' alias
|
|
3307
|
-
KeyG: 'g', // 'g' alias
|
|
3308
|
-
KeyH: 'h', // 'h' alias
|
|
3309
|
-
KeyI: 'i', // 'i' alias
|
|
3310
|
-
KeyJ: 'j', // 'j' alias
|
|
3311
|
-
KeyK: 'k', // 'k' alias
|
|
3312
|
-
KeyL: 'l', // 'l' alias
|
|
3313
|
-
KeyM: 'm', // 'm' alias
|
|
3314
|
-
KeyN: 'n', // 'n' alias
|
|
3315
|
-
KeyO: 'o', // 'o' alias
|
|
3316
|
-
KeyP: 'p', // 'p' alias
|
|
3317
|
-
KeyQ: 'q', // 'q' alias
|
|
3318
|
-
KeyR: 'r', // 'r' alias
|
|
3319
|
-
KeyS: 's', // 's' alias
|
|
3320
|
-
KeyT: 't', // 't' alias
|
|
3321
|
-
KeyU: 'u', // 'u' alias
|
|
3322
|
-
KeyV: 'v', // 'v' alias
|
|
3323
|
-
KeyW: 'w', // 'w' alias
|
|
3324
|
-
KeyX: 'x', // 'x' alias
|
|
3325
|
-
KeyY: 'y', // 'y' alias
|
|
3326
|
-
KeyZ: 'z', // 'z' alias
|
|
3327
|
-
Period: '.', // '.' alias
|
|
3328
|
-
Semicolon: '\uE018', // ';' alias
|
|
3329
|
-
Slash: '/', // '/' alias
|
|
3330
|
-
ZenkakuHankaku: '\uE040',
|
|
3099
|
+
'Tab': '\uE004',
|
|
3100
|
+
'Insert': '\uE016',
|
|
3101
|
+
'Delete': '\uE017',
|
|
3102
|
+
'End': '\uE010',
|
|
3103
|
+
'Home': '\uE011',
|
|
3104
|
+
'PageUp': '\uE00E',
|
|
3105
|
+
'PageDown': '\uE00F',
|
|
3106
|
+
'ArrowDown': '\uE015',
|
|
3107
|
+
'ArrowLeft': '\uE012',
|
|
3108
|
+
'ArrowRight': '\uE014',
|
|
3109
|
+
'ArrowUp': '\uE013',
|
|
3110
|
+
'F1': '\uE031',
|
|
3111
|
+
'F2': '\uE032',
|
|
3112
|
+
'F3': '\uE033',
|
|
3113
|
+
'F4': '\uE034',
|
|
3114
|
+
'F5': '\uE035',
|
|
3115
|
+
'F6': '\uE036',
|
|
3116
|
+
'F7': '\uE037',
|
|
3117
|
+
'F8': '\uE038',
|
|
3118
|
+
'F9': '\uE039',
|
|
3119
|
+
'F10': '\uE03A',
|
|
3120
|
+
'F11': '\uE03B',
|
|
3121
|
+
'F12': '\uE03C',
|
|
3122
|
+
'Numpad0': '\uE01A',
|
|
3123
|
+
'Numpad1': '\uE01B',
|
|
3124
|
+
'Numpad2': '\uE01C',
|
|
3125
|
+
'Numpad3': '\uE01D',
|
|
3126
|
+
'Numpad4': '\uE01E',
|
|
3127
|
+
'Numpad5': '\uE01F',
|
|
3128
|
+
'Numpad6': '\uE020',
|
|
3129
|
+
'Numpad7': '\uE021',
|
|
3130
|
+
'Numpad8': '\uE022',
|
|
3131
|
+
'Numpad9': '\uE023',
|
|
3132
|
+
'NumpadMultiply': '\uE024',
|
|
3133
|
+
'NumpadAdd': '\uE025',
|
|
3134
|
+
'NumpadSubtract': '\uE027',
|
|
3135
|
+
'NumpadDecimal': '\uE028',
|
|
3136
|
+
'NumpadDivide': '\uE029',
|
|
3137
|
+
'NumpadEnter': '\uE007',
|
|
3138
|
+
'NumpadInsert': '\uE05C', // 'Numpad0' alternate (when NumLock off)
|
|
3139
|
+
'NumpadDelete': '\uE05D', // 'NumpadDecimal' alternate (when NumLock off)
|
|
3140
|
+
'NumpadEnd': '\uE056', // 'Numpad1' alternate (when NumLock off)
|
|
3141
|
+
'NumpadHome': '\uE057', // 'Numpad7' alternate (when NumLock off)
|
|
3142
|
+
'NumpadPageDown': '\uE055', // 'Numpad3' alternate (when NumLock off)
|
|
3143
|
+
'NumpadPageUp': '\uE054', // 'Numpad9' alternate (when NumLock off)
|
|
3144
|
+
'NumpadArrowDown': '\uE05B', // 'Numpad2' alternate (when NumLock off)
|
|
3145
|
+
'NumpadArrowLeft': '\uE058', // 'Numpad4' alternate (when NumLock off)
|
|
3146
|
+
'NumpadArrowRight': '\uE05A', // 'Numpad6' alternate (when NumLock off)
|
|
3147
|
+
'NumpadArrowUp': '\uE059', // 'Numpad8' alternate (when NumLock off)
|
|
3148
|
+
'Comma': '\uE026', // ',' alias
|
|
3149
|
+
'Digit0': '0', // '0' alias
|
|
3150
|
+
'Digit1': '1', // '1' alias
|
|
3151
|
+
'Digit2': '2', // '2' alias
|
|
3152
|
+
'Digit3': '3', // '3' alias
|
|
3153
|
+
'Digit4': '4', // '4' alias
|
|
3154
|
+
'Digit5': '5', // '5' alias
|
|
3155
|
+
'Digit6': '6', // '6' alias
|
|
3156
|
+
'Digit7': '7', // '7' alias
|
|
3157
|
+
'Digit8': '8', // '8' alias
|
|
3158
|
+
'Digit9': '9', // '9' alias
|
|
3159
|
+
'Equal': '\uE019', // '=' alias
|
|
3160
|
+
'KeyA': 'a', // 'a' alias
|
|
3161
|
+
'KeyB': 'b', // 'b' alias
|
|
3162
|
+
'KeyC': 'c', // 'c' alias
|
|
3163
|
+
'KeyD': 'd', // 'd' alias
|
|
3164
|
+
'KeyE': 'e', // 'e' alias
|
|
3165
|
+
'KeyF': 'f', // 'f' alias
|
|
3166
|
+
'KeyG': 'g', // 'g' alias
|
|
3167
|
+
'KeyH': 'h', // 'h' alias
|
|
3168
|
+
'KeyI': 'i', // 'i' alias
|
|
3169
|
+
'KeyJ': 'j', // 'j' alias
|
|
3170
|
+
'KeyK': 'k', // 'k' alias
|
|
3171
|
+
'KeyL': 'l', // 'l' alias
|
|
3172
|
+
'KeyM': 'm', // 'm' alias
|
|
3173
|
+
'KeyN': 'n', // 'n' alias
|
|
3174
|
+
'KeyO': 'o', // 'o' alias
|
|
3175
|
+
'KeyP': 'p', // 'p' alias
|
|
3176
|
+
'KeyQ': 'q', // 'q' alias
|
|
3177
|
+
'KeyR': 'r', // 'r' alias
|
|
3178
|
+
'KeyS': 's', // 's' alias
|
|
3179
|
+
'KeyT': 't', // 't' alias
|
|
3180
|
+
'KeyU': 'u', // 'u' alias
|
|
3181
|
+
'KeyV': 'v', // 'v' alias
|
|
3182
|
+
'KeyW': 'w', // 'w' alias
|
|
3183
|
+
'KeyX': 'x', // 'x' alias
|
|
3184
|
+
'KeyY': 'y', // 'y' alias
|
|
3185
|
+
'KeyZ': 'z', // 'z' alias
|
|
3186
|
+
'Period': '.', // '.' alias
|
|
3187
|
+
'Semicolon': '\uE018', // ';' alias
|
|
3188
|
+
'Slash': '/', // '/' alias
|
|
3189
|
+
'ZenkakuHankaku': '\uE040',
|
|
3331
3190
|
/* eslint-enable quote-props */
|
|
3332
|
-
}
|
|
3191
|
+
};
|
|
3333
3192
|
|
|
3334
3193
|
function convertKeyToRawKey(key) {
|
|
3335
3194
|
if (Object.prototype.hasOwnProperty.call(keyUnicodeMap, key)) {
|
|
3336
|
-
return keyUnicodeMap[key]
|
|
3195
|
+
return keyUnicodeMap[key];
|
|
3337
3196
|
}
|
|
3338
3197
|
// Key is raw key when no representative unicode code point for value
|
|
3339
|
-
return key
|
|
3198
|
+
return key;
|
|
3340
3199
|
}
|
|
3341
3200
|
|
|
3342
3201
|
function getNormalizedKey(key) {
|
|
3343
|
-
let normalizedKey = getNormalizedKeyAttributeValue(key)
|
|
3202
|
+
let normalizedKey = getNormalizedKeyAttributeValue(key);
|
|
3344
3203
|
// Always use "left" modifier keys for non-W3C sessions,
|
|
3345
3204
|
// as JsonWireProtocol does not support "right" modifier keys
|
|
3346
3205
|
if (!this.browser.isW3C) {
|
|
3347
|
-
normalizedKey = normalizedKey.replace(/^(Alt|Control|Meta|Shift)Right$/, '$1')
|
|
3206
|
+
normalizedKey = normalizedKey.replace(/^(Alt|Control|Meta|Shift)Right$/, '$1');
|
|
3348
3207
|
}
|
|
3349
3208
|
if (key !== normalizedKey) {
|
|
3350
|
-
this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`)
|
|
3209
|
+
this.debugSection('Input', `Mapping key '${key}' to '${normalizedKey}'`);
|
|
3351
3210
|
}
|
|
3352
|
-
return convertKeyToRawKey(normalizedKey)
|
|
3211
|
+
return convertKeyToRawKey(normalizedKey);
|
|
3353
3212
|
}
|
|
3354
3213
|
|
|
3355
|
-
const unicodeModifierKeys = modifierKeys.map(
|
|
3214
|
+
const unicodeModifierKeys = modifierKeys.map(k => convertKeyToRawKey(k));
|
|
3356
3215
|
function isModifierKey(key) {
|
|
3357
|
-
return unicodeModifierKeys.includes(key)
|
|
3216
|
+
return unicodeModifierKeys.includes(key);
|
|
3358
3217
|
}
|
|
3359
3218
|
|
|
3360
3219
|
function highlightActiveElement(element) {
|
|
3361
3220
|
if (this.options.highlightElement && global.debugMode) {
|
|
3362
|
-
highlightElement(element, this.browser)
|
|
3221
|
+
highlightElement(element, this.browser);
|
|
3363
3222
|
}
|
|
3364
3223
|
}
|
|
3365
3224
|
|
|
3366
3225
|
function prepareLocateFn(context) {
|
|
3367
|
-
if (!context) return this._locate.bind(this)
|
|
3226
|
+
if (!context) return this._locate.bind(this);
|
|
3368
3227
|
return (l) => {
|
|
3369
|
-
l = new Locator(l, 'css')
|
|
3228
|
+
l = new Locator(l, 'css');
|
|
3370
3229
|
return this._locate(context, true).then(async (res) => {
|
|
3371
|
-
assertElementExists(res, context, 'Context element')
|
|
3230
|
+
assertElementExists(res, context, 'Context element');
|
|
3372
3231
|
if (l.react) {
|
|
3373
|
-
return res[0].react$$(l.react, l.props || undefined)
|
|
3232
|
+
return res[0].react$$(l.react, l.props || undefined);
|
|
3374
3233
|
}
|
|
3375
|
-
return res[0].$$(l.simplify())
|
|
3376
|
-
})
|
|
3377
|
-
}
|
|
3234
|
+
return res[0].$$(l.simplify());
|
|
3235
|
+
});
|
|
3236
|
+
};
|
|
3378
3237
|
}
|
|
3379
3238
|
|
|
3380
|
-
|
|
3239
|
+
export default WebDriver;
|