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/Protractor.js
CHANGED
|
@@ -1,24 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
let
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import Helper from '@codeceptjs/helper';
|
|
3
|
+
import { includes as stringIncludes } from '../assert/include.js';
|
|
4
|
+
import { urlEquals, equals } from '../assert/equal.js';
|
|
5
|
+
import { empty } from '../assert/empty.js';
|
|
6
|
+
import { truth } from '../assert/truth';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
xpathLocator,
|
|
10
|
+
fileExists,
|
|
11
|
+
convertCssPropertiesToCamelCase,
|
|
12
|
+
screenshotOutputFolder,
|
|
13
|
+
} from '../utils.js';
|
|
14
|
+
|
|
15
|
+
import { isColorProperty, convertColorToRGBA } from '../colorUtils';
|
|
16
|
+
import ElementNotFound from './errors/ElementNotFound.js';
|
|
17
|
+
import ConnectionRefused from './errors/ConnectionRefused.js';
|
|
18
|
+
import Locator from '../locator.js';
|
|
19
|
+
|
|
20
|
+
let EC;
|
|
21
|
+
let Key;
|
|
22
|
+
let Button;
|
|
23
|
+
let ProtractorBy;
|
|
24
|
+
let ProtractorExpectedConditions;
|
|
25
|
+
|
|
26
|
+
let withinStore = {};
|
|
27
|
+
let Runner;
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* Protractor helper is based on [Protractor library](http://www.protractortest.org) and used for testing web applications.
|
|
@@ -112,14 +118,12 @@ let Runner
|
|
|
112
118
|
class Protractor extends Helper {
|
|
113
119
|
constructor(config) {
|
|
114
120
|
// process.env.SELENIUM_PROMISE_MANAGER = false; // eslint-disable-line
|
|
115
|
-
super(config)
|
|
121
|
+
super(config);
|
|
116
122
|
|
|
117
|
-
this.isRunning = false
|
|
118
|
-
this._setConfig(config)
|
|
123
|
+
this.isRunning = false;
|
|
124
|
+
this._setConfig(config);
|
|
119
125
|
|
|
120
|
-
console.log(
|
|
121
|
-
'Protractor helper is deprecated as well as Protractor itself.\nThis helper will be removed in next major release',
|
|
122
|
-
)
|
|
126
|
+
console.log('Protractor helper is deprecated as well as Protractor itself.\nThis helper will be removed in next major release');
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
_validateConfig(config) {
|
|
@@ -138,213 +142,206 @@ class Protractor extends Helper {
|
|
|
138
142
|
capabilities: {},
|
|
139
143
|
angular: true,
|
|
140
144
|
restart: true,
|
|
141
|
-
}
|
|
145
|
+
};
|
|
142
146
|
|
|
143
|
-
config = Object.assign(defaults, config)
|
|
147
|
+
config = Object.assign(defaults, config);
|
|
144
148
|
|
|
145
|
-
if (!config.allScriptsTimeout) config.allScriptsTimeout = config.scriptsTimeout
|
|
146
|
-
if (!config.scriptTimeout) config.scriptTimeout = config.scriptsTimeout
|
|
147
|
-
if (config.proxy) config.capabilities.proxy = config.proxy
|
|
148
|
-
if (config.browser) config.capabilities.browserName = config.browser
|
|
149
|
+
if (!config.allScriptsTimeout) config.allScriptsTimeout = config.scriptsTimeout;
|
|
150
|
+
if (!config.scriptTimeout) config.scriptTimeout = config.scriptsTimeout;
|
|
151
|
+
if (config.proxy) config.capabilities.proxy = config.proxy;
|
|
152
|
+
if (config.browser) config.capabilities.browserName = config.browser;
|
|
149
153
|
|
|
150
|
-
config.waitForTimeoutInSeconds = config.waitForTimeout / 1000 // convert to seconds
|
|
151
|
-
return config
|
|
154
|
+
config.waitForTimeoutInSeconds = config.waitForTimeout / 1000; // convert to seconds
|
|
155
|
+
return config;
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
async _init() {
|
|
155
159
|
process.on('unhandledRejection', (reason) => {
|
|
156
160
|
if (reason.message.indexOf('ECONNREFUSED') > 0) {
|
|
157
|
-
this.browser = null
|
|
161
|
+
this.browser = null;
|
|
158
162
|
}
|
|
159
|
-
})
|
|
163
|
+
});
|
|
160
164
|
|
|
161
|
-
Runner = require('protractor/built/runner').Runner
|
|
162
|
-
ProtractorBy = require('protractor').ProtractorBy
|
|
163
|
-
Key = require('protractor').Key
|
|
164
|
-
Button = require('protractor').Button
|
|
165
|
-
ProtractorExpectedConditions = require('protractor').ProtractorExpectedConditions
|
|
165
|
+
Runner = require('protractor/built/runner').Runner;
|
|
166
|
+
ProtractorBy = require('protractor').ProtractorBy;
|
|
167
|
+
Key = require('protractor').Key;
|
|
168
|
+
Button = require('protractor').Button;
|
|
169
|
+
ProtractorExpectedConditions = require('protractor').ProtractorExpectedConditions;
|
|
166
170
|
|
|
167
|
-
return Promise.resolve()
|
|
171
|
+
return Promise.resolve();
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
static _checkRequirements() {
|
|
171
175
|
try {
|
|
172
|
-
require('protractor')
|
|
173
|
-
require('assert').ok(require('protractor/built/runner').Runner)
|
|
176
|
+
require('protractor');
|
|
177
|
+
require('assert').ok(require('protractor/built/runner').Runner);
|
|
174
178
|
} catch (e) {
|
|
175
|
-
return ['protractor@^5.3.0']
|
|
179
|
+
return ['protractor@^5.3.0'];
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
182
|
|
|
179
183
|
static _config() {
|
|
180
184
|
return [
|
|
181
185
|
{ name: 'url', message: 'Base url of site to be tested', default: 'http://localhost' },
|
|
182
|
-
{
|
|
183
|
-
name: 'driver',
|
|
184
|
-
message: 'Protractor driver (local, direct, session, hosted, sauce, browserstack)',
|
|
185
|
-
default: 'hosted',
|
|
186
|
-
},
|
|
186
|
+
{ name: 'driver', message: 'Protractor driver (local, direct, session, hosted, sauce, browserstack)', default: 'hosted' },
|
|
187
187
|
{ name: 'browser', message: 'Browser in which testing will be performed', default: 'chrome' },
|
|
188
188
|
{ name: 'rootElement', message: 'Root element of AngularJS application', default: 'body' },
|
|
189
189
|
{
|
|
190
|
-
name: 'angular',
|
|
191
|
-
message: 'Enable AngularJS synchronization',
|
|
192
|
-
default: false,
|
|
193
|
-
type: 'confirm',
|
|
190
|
+
name: 'angular', message: 'Enable AngularJS synchronization', default: false, type: 'confirm',
|
|
194
191
|
},
|
|
195
|
-
|
|
192
|
+
|
|
193
|
+
];
|
|
196
194
|
}
|
|
197
195
|
|
|
198
196
|
async _beforeStep() {
|
|
199
197
|
if (!this.insideAngular) {
|
|
200
|
-
return this.amOutsideAngularApp()
|
|
198
|
+
return this.amOutsideAngularApp();
|
|
201
199
|
}
|
|
202
200
|
}
|
|
203
201
|
|
|
204
202
|
async _beforeSuite() {
|
|
205
203
|
if (!this.options.restart && !this.options.manualStart && !this.isRunning) {
|
|
206
|
-
this.debugSection('Session', 'Starting singleton browser session')
|
|
207
|
-
return this._startBrowser()
|
|
204
|
+
this.debugSection('Session', 'Starting singleton browser session');
|
|
205
|
+
return this._startBrowser();
|
|
208
206
|
}
|
|
209
207
|
}
|
|
210
208
|
|
|
211
209
|
async _startBrowser() {
|
|
212
210
|
try {
|
|
213
|
-
const runner = new Runner(this.options)
|
|
214
|
-
this.browser = runner.createBrowser()
|
|
215
|
-
await this.browser.ready
|
|
211
|
+
const runner = new Runner(this.options);
|
|
212
|
+
this.browser = runner.createBrowser();
|
|
213
|
+
await this.browser.ready;
|
|
216
214
|
} catch (err) {
|
|
217
215
|
if (err.toString().indexOf('ECONNREFUSED')) {
|
|
218
|
-
throw new ConnectionRefused(err)
|
|
216
|
+
throw new ConnectionRefused(err);
|
|
219
217
|
}
|
|
220
|
-
throw err
|
|
218
|
+
throw err;
|
|
221
219
|
}
|
|
222
220
|
if (this.options.angular) {
|
|
223
|
-
await this.amInsideAngularApp()
|
|
221
|
+
await this.amInsideAngularApp();
|
|
224
222
|
} else {
|
|
225
|
-
await this.amOutsideAngularApp()
|
|
223
|
+
await this.amOutsideAngularApp();
|
|
226
224
|
}
|
|
227
225
|
|
|
228
|
-
loadGlobals(this.browser)
|
|
226
|
+
loadGlobals(this.browser);
|
|
229
227
|
|
|
230
228
|
if (this.options.windowSize === 'maximize') {
|
|
231
|
-
await this.resizeWindow(this.options.windowSize)
|
|
229
|
+
await this.resizeWindow(this.options.windowSize);
|
|
232
230
|
} else if (this.options.windowSize) {
|
|
233
|
-
const size = this.options.windowSize.split('x')
|
|
234
|
-
await this.resizeWindow(parseInt(size[0], 10), parseInt(size[1], 10))
|
|
231
|
+
const size = this.options.windowSize.split('x');
|
|
232
|
+
await this.resizeWindow(parseInt(size[0], 10), parseInt(size[1], 10));
|
|
235
233
|
}
|
|
236
|
-
this.context = this.options.rootElement
|
|
237
|
-
this.isRunning = true
|
|
238
|
-
return this.browser.ready
|
|
234
|
+
this.context = this.options.rootElement;
|
|
235
|
+
this.isRunning = true;
|
|
236
|
+
return this.browser.ready;
|
|
239
237
|
}
|
|
240
238
|
|
|
241
239
|
async _before() {
|
|
242
|
-
if (this.options.restart && !this.options.manualStart) return this._startBrowser()
|
|
243
|
-
if (!this.isRunning && !this.options.manualStart) return this._startBrowser()
|
|
240
|
+
if (this.options.restart && !this.options.manualStart) return this._startBrowser();
|
|
241
|
+
if (!this.isRunning && !this.options.manualStart) return this._startBrowser();
|
|
244
242
|
}
|
|
245
243
|
|
|
246
244
|
async _after() {
|
|
247
|
-
if (!this.browser) return
|
|
248
|
-
if (!this.isRunning) return
|
|
245
|
+
if (!this.browser) return;
|
|
246
|
+
if (!this.isRunning) return;
|
|
249
247
|
if (this.options.restart) {
|
|
250
|
-
this.isRunning = false
|
|
251
|
-
return this.browser.quit()
|
|
248
|
+
this.isRunning = false;
|
|
249
|
+
return this.browser.quit();
|
|
252
250
|
}
|
|
253
|
-
if (this.options.keepBrowserState) return
|
|
251
|
+
if (this.options.keepBrowserState) return;
|
|
254
252
|
|
|
255
|
-
const dialog = await this.grabPopupText()
|
|
253
|
+
const dialog = await this.grabPopupText();
|
|
256
254
|
if (dialog) {
|
|
257
|
-
await this.cancelPopup()
|
|
255
|
+
await this.cancelPopup();
|
|
258
256
|
}
|
|
259
257
|
if (!this.options.keepCookies) {
|
|
260
|
-
await this.browser.manage().deleteAllCookies()
|
|
258
|
+
await this.browser.manage().deleteAllCookies();
|
|
261
259
|
}
|
|
262
|
-
let url
|
|
260
|
+
let url;
|
|
263
261
|
try {
|
|
264
|
-
url = await this.browser.getCurrentUrl()
|
|
262
|
+
url = await this.browser.getCurrentUrl();
|
|
265
263
|
} catch (err) {
|
|
266
264
|
// Ignore, as above will throw if no webpage has been loaded
|
|
267
265
|
}
|
|
268
266
|
if (url && !/data:,/i.test(url)) {
|
|
269
|
-
await this.browser.executeScript('localStorage.clear();')
|
|
267
|
+
await this.browser.executeScript('localStorage.clear();');
|
|
270
268
|
}
|
|
271
|
-
return this.closeOtherTabs()
|
|
269
|
+
return this.closeOtherTabs();
|
|
272
270
|
}
|
|
273
271
|
|
|
274
272
|
async _failed() {
|
|
275
|
-
await this._withinEnd()
|
|
273
|
+
await this._withinEnd();
|
|
276
274
|
}
|
|
277
275
|
|
|
278
276
|
async _finishTest() {
|
|
279
|
-
if (!this.options.restart && this.isRunning) return this.browser.quit()
|
|
277
|
+
if (!this.options.restart && this.isRunning) return this.browser.quit();
|
|
280
278
|
}
|
|
281
279
|
|
|
282
280
|
async _withinBegin(locator) {
|
|
283
|
-
withinStore.elFn = this.browser.findElement
|
|
284
|
-
withinStore.elsFn = this.browser.findElements
|
|
281
|
+
withinStore.elFn = this.browser.findElement;
|
|
282
|
+
withinStore.elsFn = this.browser.findElements;
|
|
285
283
|
|
|
286
|
-
const frame = isFrameLocator(locator)
|
|
284
|
+
const frame = isFrameLocator(locator);
|
|
287
285
|
|
|
288
286
|
if (frame) {
|
|
289
287
|
if (Array.isArray(frame)) {
|
|
290
|
-
withinStore.frame = frame.join('>')
|
|
291
|
-
return this.switchTo(null)
|
|
292
|
-
frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve())
|
|
293
|
-
)
|
|
288
|
+
withinStore.frame = frame.join('>');
|
|
289
|
+
return this.switchTo(null)
|
|
290
|
+
.then(() => frame.reduce((p, frameLocator) => p.then(() => this.switchTo(frameLocator)), Promise.resolve()));
|
|
294
291
|
}
|
|
295
|
-
withinStore.frame = frame
|
|
296
|
-
return this.switchTo(locator)
|
|
292
|
+
withinStore.frame = frame;
|
|
293
|
+
return this.switchTo(locator);
|
|
297
294
|
}
|
|
298
295
|
|
|
299
|
-
this.context = locator
|
|
300
|
-
const context = await global.element(guessLocator(locator) || global.by.css(locator))
|
|
301
|
-
if (!context) throw new ElementNotFound(locator)
|
|
296
|
+
this.context = locator;
|
|
297
|
+
const context = await global.element(guessLocator(locator) || global.by.css(locator));
|
|
298
|
+
if (!context) throw new ElementNotFound(locator);
|
|
302
299
|
|
|
303
|
-
this.browser.findElement =
|
|
304
|
-
this.browser.findElements =
|
|
305
|
-
return context
|
|
300
|
+
this.browser.findElement = l => (l ? context.element(l).getWebElement() : context.getWebElement());
|
|
301
|
+
this.browser.findElements = l => context.all(l).getWebElements();
|
|
302
|
+
return context;
|
|
306
303
|
}
|
|
307
304
|
|
|
308
305
|
async _withinEnd() {
|
|
309
|
-
if (!isWithin()) return
|
|
306
|
+
if (!isWithin()) return;
|
|
310
307
|
if (withinStore.frame) {
|
|
311
|
-
withinStore = {}
|
|
312
|
-
return this.switchTo(null)
|
|
308
|
+
withinStore = {};
|
|
309
|
+
return this.switchTo(null);
|
|
313
310
|
}
|
|
314
|
-
this.browser.findElement = withinStore.elFn
|
|
315
|
-
this.browser.findElements = withinStore.elsFn
|
|
316
|
-
withinStore = {}
|
|
317
|
-
this.context = this.options.rootElement
|
|
311
|
+
this.browser.findElement = withinStore.elFn;
|
|
312
|
+
this.browser.findElements = withinStore.elsFn;
|
|
313
|
+
withinStore = {};
|
|
314
|
+
this.context = this.options.rootElement;
|
|
318
315
|
}
|
|
319
316
|
|
|
320
317
|
_session() {
|
|
321
|
-
const defaultSession = this.browser
|
|
318
|
+
const defaultSession = this.browser;
|
|
322
319
|
return {
|
|
323
320
|
start: async (opts) => {
|
|
324
|
-
opts = this._validateConfig(Object.assign(this.options, opts))
|
|
325
|
-
this.debugSection('New Browser', JSON.stringify(opts))
|
|
326
|
-
const runner = new Runner(opts)
|
|
327
|
-
const res = await this.browser.executeScript('return [window.outerWidth, window.outerHeight]')
|
|
328
|
-
const browser = runner.createBrowser(null, this.browser)
|
|
329
|
-
await browser.ready
|
|
330
|
-
await browser.waitForAngularEnabled(this.insideAngular)
|
|
331
|
-
await browser.manage().window().setSize(parseInt(res[0], 10), parseInt(res[1], 10))
|
|
332
|
-
return browser.ready
|
|
321
|
+
opts = this._validateConfig(Object.assign(this.options, opts));
|
|
322
|
+
this.debugSection('New Browser', JSON.stringify(opts));
|
|
323
|
+
const runner = new Runner(opts);
|
|
324
|
+
const res = await this.browser.executeScript('return [window.outerWidth, window.outerHeight]');
|
|
325
|
+
const browser = runner.createBrowser(null, this.browser);
|
|
326
|
+
await browser.ready;
|
|
327
|
+
await browser.waitForAngularEnabled(this.insideAngular);
|
|
328
|
+
await browser.manage().window().setSize(parseInt(res[0], 10), parseInt(res[1], 10));
|
|
329
|
+
return browser.ready;
|
|
333
330
|
},
|
|
334
331
|
stop: async (browser) => {
|
|
335
|
-
return browser.close()
|
|
332
|
+
return browser.close();
|
|
336
333
|
},
|
|
337
334
|
loadVars: async (browser) => {
|
|
338
|
-
if (isWithin()) throw new Error(
|
|
339
|
-
this.browser = browser
|
|
340
|
-
loadGlobals(this.browser)
|
|
335
|
+
if (isWithin()) throw new Error('Can\'t start session inside within block');
|
|
336
|
+
this.browser = browser;
|
|
337
|
+
loadGlobals(this.browser);
|
|
341
338
|
},
|
|
342
339
|
restoreVars: async () => {
|
|
343
|
-
if (isWithin()) await this._withinEnd()
|
|
344
|
-
this.browser = defaultSession
|
|
345
|
-
loadGlobals(this.browser)
|
|
340
|
+
if (isWithin()) await this._withinEnd();
|
|
341
|
+
this.browser = defaultSession;
|
|
342
|
+
loadGlobals(this.browser);
|
|
346
343
|
},
|
|
347
|
-
}
|
|
344
|
+
};
|
|
348
345
|
}
|
|
349
346
|
|
|
350
347
|
/**
|
|
@@ -365,7 +362,7 @@ class Protractor extends Helper {
|
|
|
365
362
|
* @param {function} fn async functuion that executed with Protractor helper as argument
|
|
366
363
|
*/
|
|
367
364
|
useProtractorTo(description, fn) {
|
|
368
|
-
return this._useTo(...arguments)
|
|
365
|
+
return this._useTo(...arguments);
|
|
369
366
|
}
|
|
370
367
|
|
|
371
368
|
/**
|
|
@@ -373,9 +370,9 @@ class Protractor extends Helper {
|
|
|
373
370
|
* start using WebDriver instead of Protractor in this session
|
|
374
371
|
*/
|
|
375
372
|
async amOutsideAngularApp() {
|
|
376
|
-
if (!this.browser) return
|
|
377
|
-
await this.browser.waitForAngularEnabled(false)
|
|
378
|
-
return Promise.resolve(
|
|
373
|
+
if (!this.browser) return;
|
|
374
|
+
await this.browser.waitForAngularEnabled(false);
|
|
375
|
+
return Promise.resolve(this.insideAngular = false);
|
|
379
376
|
}
|
|
380
377
|
|
|
381
378
|
/**
|
|
@@ -383,8 +380,8 @@ class Protractor extends Helper {
|
|
|
383
380
|
* Should be used after "amOutsideAngularApp"
|
|
384
381
|
*/
|
|
385
382
|
async amInsideAngularApp() {
|
|
386
|
-
await this.browser.waitForAngularEnabled(true)
|
|
387
|
-
return Promise.resolve(
|
|
383
|
+
await this.browser.waitForAngularEnabled(true);
|
|
384
|
+
return Promise.resolve(this.insideAngular = true);
|
|
388
385
|
}
|
|
389
386
|
|
|
390
387
|
/**
|
|
@@ -402,15 +399,15 @@ class Protractor extends Helper {
|
|
|
402
399
|
*
|
|
403
400
|
*/
|
|
404
401
|
async _locate(locator, smartWait = false) {
|
|
405
|
-
return this._smartWait(() => this.browser.findElements(guessLocator(locator) || global.by.css(locator)), smartWait)
|
|
402
|
+
return this._smartWait(() => this.browser.findElements(guessLocator(locator) || global.by.css(locator)), smartWait);
|
|
406
403
|
}
|
|
407
404
|
|
|
408
405
|
async _smartWait(fn, enabled = true) {
|
|
409
|
-
if (!this.options.smartWait || !enabled) return fn()
|
|
410
|
-
await this.browser.manage().timeouts().implicitlyWait(this.options.smartWait)
|
|
411
|
-
const res = await fn()
|
|
412
|
-
await this.browser.manage().timeouts().implicitlyWait(0)
|
|
413
|
-
return res
|
|
406
|
+
if (!this.options.smartWait || !enabled) return fn();
|
|
407
|
+
await this.browser.manage().timeouts().implicitlyWait(this.options.smartWait);
|
|
408
|
+
const res = await fn();
|
|
409
|
+
await this.browser.manage().timeouts().implicitlyWait(0);
|
|
410
|
+
return res;
|
|
414
411
|
}
|
|
415
412
|
|
|
416
413
|
/**
|
|
@@ -421,7 +418,7 @@ class Protractor extends Helper {
|
|
|
421
418
|
* ```
|
|
422
419
|
*/
|
|
423
420
|
async _locateCheckable(locator) {
|
|
424
|
-
return findCheckable.call(this, this.browser, locator)
|
|
421
|
+
return findCheckable.call(this, this.browser, locator);
|
|
425
422
|
}
|
|
426
423
|
|
|
427
424
|
/**
|
|
@@ -432,7 +429,7 @@ class Protractor extends Helper {
|
|
|
432
429
|
* ```
|
|
433
430
|
*/
|
|
434
431
|
async _locateClickable(locator) {
|
|
435
|
-
return findClickable.call(this, this.browser, locator)
|
|
432
|
+
return findClickable.call(this, this.browser, locator);
|
|
436
433
|
}
|
|
437
434
|
|
|
438
435
|
/**
|
|
@@ -443,47 +440,47 @@ class Protractor extends Helper {
|
|
|
443
440
|
* ```
|
|
444
441
|
*/
|
|
445
442
|
async _locateFields(locator) {
|
|
446
|
-
return findFields.call(this, this.browser, locator)
|
|
443
|
+
return findFields.call(this, this.browser, locator);
|
|
447
444
|
}
|
|
448
445
|
|
|
449
446
|
/**
|
|
450
447
|
* {{> amOnPage }}
|
|
451
448
|
*/
|
|
452
449
|
async amOnPage(url) {
|
|
453
|
-
if (
|
|
454
|
-
url = this.options.url + url
|
|
450
|
+
if (!(/^\w+\:\/\//.test(url))) {
|
|
451
|
+
url = this.options.url + url;
|
|
455
452
|
}
|
|
456
|
-
const res = await this.browser.get(url)
|
|
457
|
-
this.debug(`Visited ${url}`)
|
|
458
|
-
return res
|
|
453
|
+
const res = await this.browser.get(url);
|
|
454
|
+
this.debug(`Visited ${url}`);
|
|
455
|
+
return res;
|
|
459
456
|
}
|
|
460
457
|
|
|
461
458
|
/**
|
|
462
459
|
* {{> click }}
|
|
463
460
|
*/
|
|
464
461
|
async click(locator, context = null) {
|
|
465
|
-
let matcher = this.browser
|
|
462
|
+
let matcher = this.browser;
|
|
466
463
|
if (context) {
|
|
467
|
-
const els = await this._locate(context, true)
|
|
468
|
-
assertElementExists(els, context)
|
|
469
|
-
matcher = els[0]
|
|
464
|
+
const els = await this._locate(context, true);
|
|
465
|
+
assertElementExists(els, context);
|
|
466
|
+
matcher = els[0];
|
|
470
467
|
}
|
|
471
|
-
const el = await findClickable.call(this, matcher, locator)
|
|
472
|
-
return el.click()
|
|
468
|
+
const el = await findClickable.call(this, matcher, locator);
|
|
469
|
+
return el.click();
|
|
473
470
|
}
|
|
474
471
|
|
|
475
472
|
/**
|
|
476
473
|
* {{> doubleClick }}
|
|
477
474
|
*/
|
|
478
475
|
async doubleClick(locator, context = null) {
|
|
479
|
-
let matcher = this.browser
|
|
476
|
+
let matcher = this.browser;
|
|
480
477
|
if (context) {
|
|
481
|
-
const els = await this._locate(context, true)
|
|
482
|
-
assertElementExists(els, context)
|
|
483
|
-
matcher = els[0]
|
|
478
|
+
const els = await this._locate(context, true);
|
|
479
|
+
assertElementExists(els, context);
|
|
480
|
+
matcher = els[0];
|
|
484
481
|
}
|
|
485
|
-
const el = await findClickable.call(this, matcher, locator)
|
|
486
|
-
return this.browser.actions().doubleClick(el).perform()
|
|
482
|
+
const el = await findClickable.call(this, matcher, locator);
|
|
483
|
+
return this.browser.actions().doubleClick(el).perform();
|
|
487
484
|
}
|
|
488
485
|
|
|
489
486
|
/**
|
|
@@ -494,98 +491,98 @@ class Protractor extends Helper {
|
|
|
494
491
|
* just press button if no selector is given
|
|
495
492
|
*/
|
|
496
493
|
if (locator === undefined) {
|
|
497
|
-
return this.browser.actions().click(Button.RIGHT).perform()
|
|
494
|
+
return this.browser.actions().click(Button.RIGHT).perform();
|
|
498
495
|
}
|
|
499
|
-
let matcher = this.browser
|
|
496
|
+
let matcher = this.browser;
|
|
500
497
|
if (context) {
|
|
501
|
-
const els = await this._locate(context, true)
|
|
502
|
-
assertElementExists(els, context)
|
|
503
|
-
matcher = els[0]
|
|
498
|
+
const els = await this._locate(context, true);
|
|
499
|
+
assertElementExists(els, context);
|
|
500
|
+
matcher = els[0];
|
|
504
501
|
}
|
|
505
|
-
const el = await findClickable.call(this, matcher, locator)
|
|
502
|
+
const el = await findClickable.call(this, matcher, locator);
|
|
506
503
|
|
|
507
|
-
await this.browser.actions().mouseMove(el).perform()
|
|
508
|
-
return this.browser.actions().click(Button.RIGHT).perform()
|
|
504
|
+
await this.browser.actions().mouseMove(el).perform();
|
|
505
|
+
return this.browser.actions().click(Button.RIGHT).perform();
|
|
509
506
|
}
|
|
510
507
|
|
|
511
508
|
/**
|
|
512
509
|
* {{> moveCursorTo }}
|
|
513
510
|
*/
|
|
514
511
|
async moveCursorTo(locator, offsetX = null, offsetY = null) {
|
|
515
|
-
let offset = null
|
|
512
|
+
let offset = null;
|
|
516
513
|
if (offsetX !== null || offsetY !== null) {
|
|
517
|
-
offset = { x: offsetX, y: offsetY }
|
|
514
|
+
offset = { x: offsetX, y: offsetY };
|
|
518
515
|
}
|
|
519
|
-
const els = await this._locate(locator, true)
|
|
520
|
-
assertElementExists(els, locator)
|
|
521
|
-
return this.browser.actions().mouseMove(els[0], offset).perform()
|
|
516
|
+
const els = await this._locate(locator, true);
|
|
517
|
+
assertElementExists(els, locator);
|
|
518
|
+
return this.browser.actions().mouseMove(els[0], offset).perform();
|
|
522
519
|
}
|
|
523
520
|
|
|
524
521
|
/**
|
|
525
522
|
* {{> see }}
|
|
526
523
|
*/
|
|
527
524
|
async see(text, context = null) {
|
|
528
|
-
return proceedSee.call(this, 'assert', text, context)
|
|
525
|
+
return proceedSee.call(this, 'assert', text, context);
|
|
529
526
|
}
|
|
530
527
|
|
|
531
528
|
/**
|
|
532
529
|
* {{> seeTextEquals }}
|
|
533
530
|
*/
|
|
534
531
|
async seeTextEquals(text, context = null) {
|
|
535
|
-
return proceedSee.call(this, 'assert', text, context, true)
|
|
532
|
+
return proceedSee.call(this, 'assert', text, context, true);
|
|
536
533
|
}
|
|
537
534
|
|
|
538
535
|
/**
|
|
539
536
|
* {{> dontSee }}
|
|
540
537
|
*/
|
|
541
538
|
dontSee(text, context = null) {
|
|
542
|
-
return proceedSee.call(this, 'negate', text, context)
|
|
539
|
+
return proceedSee.call(this, 'negate', text, context);
|
|
543
540
|
}
|
|
544
541
|
|
|
545
542
|
/**
|
|
546
543
|
* {{> grabBrowserLogs }}
|
|
547
544
|
*/
|
|
548
545
|
async grabBrowserLogs() {
|
|
549
|
-
return this.browser.manage().logs().get('browser')
|
|
546
|
+
return this.browser.manage().logs().get('browser');
|
|
550
547
|
}
|
|
551
548
|
|
|
552
549
|
/**
|
|
553
550
|
* {{> grabCurrentUrl }}
|
|
554
551
|
*/
|
|
555
552
|
async grabCurrentUrl() {
|
|
556
|
-
return this.browser.getCurrentUrl()
|
|
553
|
+
return this.browser.getCurrentUrl();
|
|
557
554
|
}
|
|
558
555
|
|
|
559
556
|
/**
|
|
560
557
|
* {{> selectOption }}
|
|
561
558
|
*/
|
|
562
559
|
async selectOption(select, option) {
|
|
563
|
-
const fields = await findFields(this.browser, select)
|
|
564
|
-
assertElementExists(fields, select, 'Selectable field')
|
|
560
|
+
const fields = await findFields(this.browser, select);
|
|
561
|
+
assertElementExists(fields, select, 'Selectable field');
|
|
565
562
|
if (!Array.isArray(option)) {
|
|
566
|
-
option = [option]
|
|
563
|
+
option = [option];
|
|
567
564
|
}
|
|
568
|
-
const field = fields[0]
|
|
569
|
-
const promises = []
|
|
565
|
+
const field = fields[0];
|
|
566
|
+
const promises = [];
|
|
570
567
|
for (const key in option) {
|
|
571
|
-
const opt = xpathLocator.literal(option[key])
|
|
572
|
-
let els = await field.findElements(global.by.xpath(Locator.select.byVisibleText(opt)))
|
|
568
|
+
const opt = xpathLocator.literal(option[key]);
|
|
569
|
+
let els = await field.findElements(global.by.xpath(Locator.select.byVisibleText(opt)));
|
|
573
570
|
if (!els.length) {
|
|
574
|
-
els = await field.findElements(global.by.xpath(Locator.select.byValue(opt)))
|
|
571
|
+
els = await field.findElements(global.by.xpath(Locator.select.byValue(opt)));
|
|
575
572
|
}
|
|
576
|
-
els.forEach(
|
|
573
|
+
els.forEach(el => promises.push(el.click()));
|
|
577
574
|
}
|
|
578
575
|
|
|
579
|
-
return Promise.all(promises)
|
|
576
|
+
return Promise.all(promises);
|
|
580
577
|
}
|
|
581
578
|
|
|
582
579
|
/**
|
|
583
580
|
* {{> fillField }}
|
|
584
581
|
*/
|
|
585
582
|
async fillField(field, value) {
|
|
586
|
-
const els = await findFields(this.browser, field)
|
|
587
|
-
await els[0].clear()
|
|
588
|
-
return els[0].sendKeys(value.toString())
|
|
583
|
+
const els = await findFields(this.browser, field);
|
|
584
|
+
await els[0].clear();
|
|
585
|
+
return els[0].sendKeys(value.toString());
|
|
589
586
|
}
|
|
590
587
|
|
|
591
588
|
/**
|
|
@@ -593,269 +590,266 @@ class Protractor extends Helper {
|
|
|
593
590
|
* {{ keys }}
|
|
594
591
|
*/
|
|
595
592
|
async pressKey(key) {
|
|
596
|
-
let modifier
|
|
597
|
-
if (Array.isArray(key) && ~['Control', 'Command', 'Shift', 'Alt'].indexOf(key[0])) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
key = key[1]
|
|
593
|
+
let modifier;
|
|
594
|
+
if (Array.isArray(key) && ~['Control', 'Command', 'Shift', 'Alt'].indexOf(key[0])) { // eslint-disable-line no-bitwise
|
|
595
|
+
modifier = Key[key[0].toUpperCase()];
|
|
596
|
+
key = key[1];
|
|
601
597
|
}
|
|
602
598
|
|
|
603
599
|
// guess special key in Selenium Webdriver list
|
|
604
600
|
if (Key[key.toUpperCase()]) {
|
|
605
|
-
key = Key[key.toUpperCase()]
|
|
601
|
+
key = Key[key.toUpperCase()];
|
|
606
602
|
}
|
|
607
603
|
|
|
608
|
-
const action = this.browser.actions()
|
|
609
|
-
if (modifier) action.keyDown(modifier)
|
|
610
|
-
action.sendKeys(key)
|
|
611
|
-
if (modifier) action.keyUp(modifier)
|
|
612
|
-
return action.perform()
|
|
604
|
+
const action = this.browser.actions();
|
|
605
|
+
if (modifier) action.keyDown(modifier);
|
|
606
|
+
action.sendKeys(key);
|
|
607
|
+
if (modifier) action.keyUp(modifier);
|
|
608
|
+
return action.perform();
|
|
613
609
|
}
|
|
614
610
|
|
|
615
611
|
/**
|
|
616
612
|
* {{> attachFile }}
|
|
617
613
|
*/
|
|
618
614
|
async attachFile(locator, pathToFile) {
|
|
619
|
-
const file = path.join(global.codecept_dir, pathToFile)
|
|
615
|
+
const file = path.join(global.codecept_dir, pathToFile);
|
|
620
616
|
if (!fileExists(file)) {
|
|
621
|
-
throw new Error(`File at ${file} can not be found on local system`)
|
|
617
|
+
throw new Error(`File at ${file} can not be found on local system`);
|
|
622
618
|
}
|
|
623
|
-
const els = await findFields(this.browser, locator)
|
|
624
|
-
assertElementExists(els, locator, 'Field')
|
|
619
|
+
const els = await findFields(this.browser, locator);
|
|
620
|
+
assertElementExists(els, locator, 'Field');
|
|
625
621
|
if (this.options.browser !== 'phantomjs') {
|
|
626
|
-
const remote = require('selenium-webdriver/remote')
|
|
627
|
-
this.browser.setFileDetector(new remote.FileDetector())
|
|
622
|
+
const remote = require('selenium-webdriver/remote');
|
|
623
|
+
this.browser.setFileDetector(new remote.FileDetector());
|
|
628
624
|
}
|
|
629
|
-
return els[0].sendKeys(file)
|
|
625
|
+
return els[0].sendKeys(file);
|
|
630
626
|
}
|
|
631
627
|
|
|
632
628
|
/**
|
|
633
629
|
* {{> seeInField }}
|
|
634
630
|
*/
|
|
635
631
|
async seeInField(field, value) {
|
|
636
|
-
const _value = typeof value === 'boolean' ? value : value.toString()
|
|
637
|
-
return proceedSeeInField.call(this, 'assert', field, _value)
|
|
632
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
633
|
+
return proceedSeeInField.call(this, 'assert', field, _value);
|
|
638
634
|
}
|
|
639
635
|
|
|
640
636
|
/**
|
|
641
637
|
* {{> dontSeeInField }}
|
|
642
638
|
*/
|
|
643
639
|
async dontSeeInField(field, value) {
|
|
644
|
-
const _value = typeof value === 'boolean' ? value : value.toString()
|
|
645
|
-
return proceedSeeInField.call(this, 'negate', field, _value)
|
|
640
|
+
const _value = (typeof value === 'boolean') ? value : value.toString();
|
|
641
|
+
return proceedSeeInField.call(this, 'negate', field, _value);
|
|
646
642
|
}
|
|
647
643
|
|
|
648
644
|
/**
|
|
649
645
|
* {{> appendField }}
|
|
650
646
|
*/
|
|
651
647
|
async appendField(field, value) {
|
|
652
|
-
const els = await findFields(this.browser, field)
|
|
653
|
-
assertElementExists(els, field, 'Field')
|
|
654
|
-
return els[0].sendKeys(value.toString())
|
|
648
|
+
const els = await findFields(this.browser, field);
|
|
649
|
+
assertElementExists(els, field, 'Field');
|
|
650
|
+
return els[0].sendKeys(value.toString());
|
|
655
651
|
}
|
|
656
652
|
|
|
657
653
|
/**
|
|
658
654
|
* {{> clearField }}
|
|
659
655
|
*/
|
|
660
656
|
async clearField(field) {
|
|
661
|
-
const els = await findFields(this.browser, field)
|
|
662
|
-
assertElementExists(els, field, 'Field')
|
|
663
|
-
return els[0].clear()
|
|
657
|
+
const els = await findFields(this.browser, field);
|
|
658
|
+
assertElementExists(els, field, 'Field');
|
|
659
|
+
return els[0].clear();
|
|
664
660
|
}
|
|
665
661
|
|
|
666
662
|
/**
|
|
667
663
|
* {{> checkOption }}
|
|
668
664
|
*/
|
|
669
665
|
async checkOption(field, context = null) {
|
|
670
|
-
let matcher = this.browser
|
|
666
|
+
let matcher = this.browser;
|
|
671
667
|
if (context) {
|
|
672
|
-
const els = await this._locate(context, true)
|
|
673
|
-
assertElementExists(els, context)
|
|
674
|
-
matcher = els[0]
|
|
668
|
+
const els = await this._locate(context, true);
|
|
669
|
+
assertElementExists(els, context);
|
|
670
|
+
matcher = els[0];
|
|
675
671
|
}
|
|
676
|
-
const els = await findCheckable(matcher, field)
|
|
677
|
-
assertElementExists(els, field, 'Checkbox or radio')
|
|
678
|
-
const isSelected = await els[0].isSelected()
|
|
679
|
-
if (!isSelected) return els[0].click()
|
|
672
|
+
const els = await findCheckable(matcher, field);
|
|
673
|
+
assertElementExists(els, field, 'Checkbox or radio');
|
|
674
|
+
const isSelected = await els[0].isSelected();
|
|
675
|
+
if (!isSelected) return els[0].click();
|
|
680
676
|
}
|
|
681
677
|
|
|
682
678
|
/**
|
|
683
679
|
* {{> uncheckOption }}
|
|
684
680
|
*/
|
|
685
681
|
async uncheckOption(field, context = null) {
|
|
686
|
-
let matcher = this.browser
|
|
682
|
+
let matcher = this.browser;
|
|
687
683
|
if (context) {
|
|
688
|
-
const els = await this._locate(context, true)
|
|
689
|
-
assertElementExists(els, context)
|
|
690
|
-
matcher = els[0]
|
|
684
|
+
const els = await this._locate(context, true);
|
|
685
|
+
assertElementExists(els, context);
|
|
686
|
+
matcher = els[0];
|
|
691
687
|
}
|
|
692
|
-
const els = await findCheckable(matcher, field)
|
|
693
|
-
assertElementExists(els, field, 'Checkbox or radio')
|
|
694
|
-
const isSelected = await els[0].isSelected()
|
|
695
|
-
if (isSelected) return els[0].click()
|
|
688
|
+
const els = await findCheckable(matcher, field);
|
|
689
|
+
assertElementExists(els, field, 'Checkbox or radio');
|
|
690
|
+
const isSelected = await els[0].isSelected();
|
|
691
|
+
if (isSelected) return els[0].click();
|
|
696
692
|
}
|
|
697
693
|
|
|
698
694
|
/**
|
|
699
695
|
* {{> seeCheckboxIsChecked }}
|
|
700
696
|
*/
|
|
701
697
|
async seeCheckboxIsChecked(field) {
|
|
702
|
-
return proceedIsChecked.call(this, 'assert', field)
|
|
698
|
+
return proceedIsChecked.call(this, 'assert', field);
|
|
703
699
|
}
|
|
704
700
|
|
|
705
701
|
/**
|
|
706
702
|
* {{> dontSeeCheckboxIsChecked }}
|
|
707
703
|
*/
|
|
708
704
|
async dontSeeCheckboxIsChecked(field) {
|
|
709
|
-
return proceedIsChecked.call(this, 'negate', field)
|
|
705
|
+
return proceedIsChecked.call(this, 'negate', field);
|
|
710
706
|
}
|
|
711
707
|
|
|
712
708
|
/**
|
|
713
709
|
* {{> grabTextFromAll }}
|
|
714
710
|
*/
|
|
715
711
|
async grabTextFromAll(locator) {
|
|
716
|
-
const els = await this._locate(locator)
|
|
717
|
-
const texts = []
|
|
712
|
+
const els = await this._locate(locator);
|
|
713
|
+
const texts = [];
|
|
718
714
|
for (const el of els) {
|
|
719
|
-
texts.push(await el.getText())
|
|
715
|
+
texts.push(await el.getText());
|
|
720
716
|
}
|
|
721
|
-
return texts
|
|
717
|
+
return texts;
|
|
722
718
|
}
|
|
723
719
|
|
|
724
720
|
/**
|
|
725
721
|
* {{> grabTextFrom }}
|
|
726
722
|
*/
|
|
727
723
|
async grabTextFrom(locator) {
|
|
728
|
-
const texts = await this.grabTextFromAll(locator)
|
|
729
|
-
assertElementExists(texts, locator)
|
|
724
|
+
const texts = await this.grabTextFromAll(locator);
|
|
725
|
+
assertElementExists(texts, locator);
|
|
730
726
|
if (texts.length > 1) {
|
|
731
|
-
this.debugSection('GrabText', `Using first element out of ${texts.length}`)
|
|
727
|
+
this.debugSection('GrabText', `Using first element out of ${texts.length}`);
|
|
732
728
|
}
|
|
733
729
|
|
|
734
|
-
return texts[0]
|
|
730
|
+
return texts[0];
|
|
735
731
|
}
|
|
736
732
|
|
|
737
733
|
/**
|
|
738
734
|
* {{> grabHTMLFromAll }}
|
|
739
735
|
*/
|
|
740
736
|
async grabHTMLFromAll(locator) {
|
|
741
|
-
const els = await this._locate(locator)
|
|
737
|
+
const els = await this._locate(locator);
|
|
742
738
|
|
|
743
|
-
const html = await Promise.all(
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}),
|
|
747
|
-
)
|
|
739
|
+
const html = await Promise.all(els.map((el) => {
|
|
740
|
+
return this.browser.executeScript('return arguments[0].innerHTML;', el);
|
|
741
|
+
}));
|
|
748
742
|
|
|
749
|
-
return html
|
|
743
|
+
return html;
|
|
750
744
|
}
|
|
751
745
|
|
|
752
746
|
/**
|
|
753
747
|
* {{> grabHTMLFrom }}
|
|
754
748
|
*/
|
|
755
749
|
async grabHTMLFrom(locator) {
|
|
756
|
-
const html = await this.grabHTMLFromAll(locator)
|
|
757
|
-
assertElementExists(html, locator)
|
|
750
|
+
const html = await this.grabHTMLFromAll(locator);
|
|
751
|
+
assertElementExists(html, locator);
|
|
758
752
|
if (html.length > 1) {
|
|
759
|
-
this.debugSection('GrabHTMl', `Using first element out of ${html.length}`)
|
|
753
|
+
this.debugSection('GrabHTMl', `Using first element out of ${html.length}`);
|
|
760
754
|
}
|
|
761
755
|
|
|
762
|
-
return html[0]
|
|
756
|
+
return html[0];
|
|
763
757
|
}
|
|
764
758
|
|
|
765
759
|
/**
|
|
766
760
|
* {{> grabValueFromAll }}
|
|
767
761
|
*/
|
|
768
762
|
async grabValueFromAll(locator) {
|
|
769
|
-
const els = await findFields(this.browser, locator)
|
|
770
|
-
const values = await Promise.all(els.map(
|
|
763
|
+
const els = await findFields(this.browser, locator);
|
|
764
|
+
const values = await Promise.all(els.map(el => el.getAttribute('value')));
|
|
771
765
|
|
|
772
|
-
return values
|
|
766
|
+
return values;
|
|
773
767
|
}
|
|
774
768
|
|
|
775
769
|
/**
|
|
776
770
|
* {{> grabValueFrom }}
|
|
777
771
|
*/
|
|
778
772
|
async grabValueFrom(locator) {
|
|
779
|
-
const values = await this.grabValueFromAll(locator)
|
|
780
|
-
assertElementExists(values, locator, 'Field')
|
|
773
|
+
const values = await this.grabValueFromAll(locator);
|
|
774
|
+
assertElementExists(values, locator, 'Field');
|
|
781
775
|
if (values.length > 1) {
|
|
782
|
-
this.debugSection('GrabValue', `Using first element out of ${values.length}`)
|
|
776
|
+
this.debugSection('GrabValue', `Using first element out of ${values.length}`);
|
|
783
777
|
}
|
|
784
778
|
|
|
785
|
-
return values[0]
|
|
779
|
+
return values[0];
|
|
786
780
|
}
|
|
787
781
|
|
|
788
782
|
/**
|
|
789
783
|
* {{> grabCssPropertyFromAll }}
|
|
790
784
|
*/
|
|
791
785
|
async grabCssPropertyFromAll(locator, cssProperty) {
|
|
792
|
-
const els = await this._locate(locator, true)
|
|
793
|
-
const values = await Promise.all(els.map(
|
|
786
|
+
const els = await this._locate(locator, true);
|
|
787
|
+
const values = await Promise.all(els.map(el => el.getCssValue(cssProperty)));
|
|
794
788
|
|
|
795
|
-
return values
|
|
789
|
+
return values;
|
|
796
790
|
}
|
|
797
791
|
|
|
798
792
|
/**
|
|
799
793
|
* {{> grabCssPropertyFrom }}
|
|
800
794
|
*/
|
|
801
795
|
async grabCssPropertyFrom(locator, cssProperty) {
|
|
802
|
-
const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty)
|
|
803
|
-
assertElementExists(cssValues, locator)
|
|
796
|
+
const cssValues = await this.grabCssPropertyFromAll(locator, cssProperty);
|
|
797
|
+
assertElementExists(cssValues, locator);
|
|
804
798
|
|
|
805
799
|
if (cssValues.length > 1) {
|
|
806
|
-
this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`)
|
|
800
|
+
this.debugSection('GrabCSS', `Using first element out of ${cssValues.length}`);
|
|
807
801
|
}
|
|
808
802
|
|
|
809
|
-
return cssValues[0]
|
|
803
|
+
return cssValues[0];
|
|
810
804
|
}
|
|
811
805
|
|
|
812
806
|
/**
|
|
813
807
|
* {{> grabAttributeFromAll }}
|
|
814
808
|
*/
|
|
815
809
|
async grabAttributeFromAll(locator, attr) {
|
|
816
|
-
const els = await this._locate(locator)
|
|
817
|
-
const array = []
|
|
810
|
+
const els = await this._locate(locator);
|
|
811
|
+
const array = [];
|
|
818
812
|
|
|
819
813
|
for (let index = 0; index < els.length; index++) {
|
|
820
|
-
const el = els[index]
|
|
821
|
-
array.push(await el.getAttribute(attr))
|
|
814
|
+
const el = els[index];
|
|
815
|
+
array.push(await el.getAttribute(attr));
|
|
822
816
|
}
|
|
823
|
-
return array
|
|
817
|
+
return array;
|
|
824
818
|
}
|
|
825
819
|
|
|
826
820
|
/**
|
|
827
821
|
* {{> grabAttributeFrom }}
|
|
828
822
|
*/
|
|
829
823
|
async grabAttributeFrom(locator, attr) {
|
|
830
|
-
const attrs = await this.grabAttributeFromAll(locator, attr)
|
|
831
|
-
assertElementExists(attrs, locator)
|
|
824
|
+
const attrs = await this.grabAttributeFromAll(locator, attr);
|
|
825
|
+
assertElementExists(attrs, locator);
|
|
832
826
|
if (attrs.length > 1) {
|
|
833
|
-
this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
|
|
827
|
+
this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
|
|
834
828
|
}
|
|
835
829
|
|
|
836
|
-
return attrs[0]
|
|
830
|
+
return attrs[0];
|
|
837
831
|
}
|
|
838
832
|
|
|
839
833
|
/**
|
|
840
834
|
* {{> seeInTitle }}
|
|
841
835
|
*/
|
|
842
836
|
async seeInTitle(text) {
|
|
843
|
-
return this.browser.getTitle().then(
|
|
837
|
+
return this.browser.getTitle().then(title => stringIncludes('web page title').assert(text, title));
|
|
844
838
|
}
|
|
845
839
|
|
|
846
840
|
/**
|
|
847
841
|
* {{> seeTitleEquals }}
|
|
848
842
|
*/
|
|
849
843
|
async seeTitleEquals(text) {
|
|
850
|
-
const title = await this.browser.getTitle()
|
|
851
|
-
return equals('web page title').assert(title, text)
|
|
844
|
+
const title = await this.browser.getTitle();
|
|
845
|
+
return equals('web page title').assert(title, text);
|
|
852
846
|
}
|
|
853
847
|
|
|
854
848
|
/**
|
|
855
849
|
* {{> dontSeeInTitle }}
|
|
856
850
|
*/
|
|
857
851
|
async dontSeeInTitle(text) {
|
|
858
|
-
return this.browser.getTitle().then(
|
|
852
|
+
return this.browser.getTitle().then(title => stringIncludes('web page title').negate(text, title));
|
|
859
853
|
}
|
|
860
854
|
|
|
861
855
|
/**
|
|
@@ -863,202 +857,188 @@ class Protractor extends Helper {
|
|
|
863
857
|
*/
|
|
864
858
|
async grabTitle() {
|
|
865
859
|
return this.browser.getTitle().then((title) => {
|
|
866
|
-
this.debugSection('Title', title)
|
|
867
|
-
return title
|
|
868
|
-
})
|
|
860
|
+
this.debugSection('Title', title);
|
|
861
|
+
return title;
|
|
862
|
+
});
|
|
869
863
|
}
|
|
870
864
|
|
|
871
865
|
/**
|
|
872
866
|
* {{> seeElement }}
|
|
873
867
|
*/
|
|
874
868
|
async seeElement(locator) {
|
|
875
|
-
let els = await this._locate(locator, true)
|
|
876
|
-
els = await Promise.all(els.map(
|
|
877
|
-
return empty('elements').negate(els.filter(
|
|
869
|
+
let els = await this._locate(locator, true);
|
|
870
|
+
els = await Promise.all(els.map(el => el.isDisplayed()));
|
|
871
|
+
return empty('elements').negate(els.filter(v => v).fill('ELEMENT'));
|
|
878
872
|
}
|
|
879
873
|
|
|
880
874
|
/**
|
|
881
875
|
* {{> dontSeeElement }}
|
|
882
876
|
*/
|
|
883
877
|
async dontSeeElement(locator) {
|
|
884
|
-
let els = await this._locate(locator, false)
|
|
885
|
-
els = await Promise.all(els.map(
|
|
886
|
-
return empty('elements').assert(els.filter(
|
|
878
|
+
let els = await this._locate(locator, false);
|
|
879
|
+
els = await Promise.all(els.map(el => el.isDisplayed()));
|
|
880
|
+
return empty('elements').assert(els.filter(v => v).fill('ELEMENT'));
|
|
887
881
|
}
|
|
888
882
|
|
|
889
883
|
/**
|
|
890
884
|
* {{> seeElementInDOM }}
|
|
891
885
|
*/
|
|
892
886
|
async seeElementInDOM(locator) {
|
|
893
|
-
return this.browser
|
|
894
|
-
.findElements(guessLocator(locator) || global.by.css(locator))
|
|
895
|
-
.then((els) => empty('elements').negate(els.fill('ELEMENT')))
|
|
887
|
+
return this.browser.findElements(guessLocator(locator) || global.by.css(locator)).then(els => empty('elements').negate(els.fill('ELEMENT')));
|
|
896
888
|
}
|
|
897
889
|
|
|
898
890
|
/**
|
|
899
891
|
* {{> dontSeeElementInDOM }}
|
|
900
892
|
*/
|
|
901
893
|
async dontSeeElementInDOM(locator) {
|
|
902
|
-
return this.browser
|
|
903
|
-
.findElements(guessLocator(locator) || global.by.css(locator))
|
|
904
|
-
.then((els) => empty('elements').assert(els.fill('ELEMENT')))
|
|
894
|
+
return this.browser.findElements(guessLocator(locator) || global.by.css(locator)).then(els => empty('elements').assert(els.fill('ELEMENT')));
|
|
905
895
|
}
|
|
906
896
|
|
|
907
897
|
/**
|
|
908
898
|
* {{> seeInSource }}
|
|
909
899
|
*/
|
|
910
900
|
async seeInSource(text) {
|
|
911
|
-
return this.browser.getPageSource().then(
|
|
901
|
+
return this.browser.getPageSource().then(source => stringIncludes('HTML source of a page').assert(text, source));
|
|
912
902
|
}
|
|
913
903
|
|
|
914
904
|
/**
|
|
915
905
|
* {{> grabSource }}
|
|
916
906
|
*/
|
|
917
907
|
async grabSource() {
|
|
918
|
-
return this.browser.getPageSource()
|
|
908
|
+
return this.browser.getPageSource();
|
|
919
909
|
}
|
|
920
910
|
|
|
921
911
|
/**
|
|
922
912
|
* {{> dontSeeInSource }}
|
|
923
913
|
*/
|
|
924
914
|
async dontSeeInSource(text) {
|
|
925
|
-
return this.browser.getPageSource().then(
|
|
915
|
+
return this.browser.getPageSource().then(source => stringIncludes('HTML source of a page').negate(text, source));
|
|
926
916
|
}
|
|
927
917
|
|
|
928
918
|
/**
|
|
929
919
|
* {{> seeNumberOfElements }}
|
|
930
920
|
*/
|
|
931
921
|
async seeNumberOfElements(locator, num) {
|
|
932
|
-
const elements = await this._locate(locator)
|
|
933
|
-
return equals(
|
|
934
|
-
`expected number of elements (${new Locator(locator)}) is ${num}, but found ${elements.length}`,
|
|
935
|
-
).assert(elements.length, num)
|
|
922
|
+
const elements = await this._locate(locator);
|
|
923
|
+
return equals(`expected number of elements (${(new Locator(locator))}) is ${num}, but found ${elements.length}`).assert(elements.length, num);
|
|
936
924
|
}
|
|
937
925
|
|
|
938
926
|
/**
|
|
939
927
|
* {{> seeNumberOfVisibleElements }}
|
|
940
928
|
*/
|
|
941
929
|
async seeNumberOfVisibleElements(locator, num) {
|
|
942
|
-
const res = await this.grabNumberOfVisibleElements(locator)
|
|
943
|
-
return equals(`expected number of visible elements (${new Locator(locator)}) is ${num}, but found ${res}`).assert(
|
|
944
|
-
res,
|
|
945
|
-
num,
|
|
946
|
-
)
|
|
930
|
+
const res = await this.grabNumberOfVisibleElements(locator);
|
|
931
|
+
return equals(`expected number of visible elements (${(new Locator(locator))}) is ${num}, but found ${res}`).assert(res, num);
|
|
947
932
|
}
|
|
948
933
|
|
|
949
934
|
/**
|
|
950
935
|
* {{> grabNumberOfVisibleElements }}
|
|
951
936
|
*/
|
|
952
937
|
async grabNumberOfVisibleElements(locator) {
|
|
953
|
-
let els = await this._locate(locator)
|
|
954
|
-
els = await Promise.all(els.map(
|
|
955
|
-
return els.length
|
|
938
|
+
let els = await this._locate(locator);
|
|
939
|
+
els = await Promise.all(els.map(el => el.isDisplayed()));
|
|
940
|
+
return els.length;
|
|
956
941
|
}
|
|
957
942
|
|
|
958
943
|
/**
|
|
959
944
|
* {{> seeCssPropertiesOnElements }}
|
|
960
945
|
*/
|
|
961
946
|
async seeCssPropertiesOnElements(locator, cssProperties) {
|
|
962
|
-
const els = await this._locate(locator)
|
|
963
|
-
assertElementExists(els, locator)
|
|
947
|
+
const els = await this._locate(locator);
|
|
948
|
+
assertElementExists(els, locator);
|
|
964
949
|
|
|
965
|
-
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties)
|
|
950
|
+
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
|
|
966
951
|
|
|
967
|
-
const attributeNames = Object.keys(cssPropertiesCamelCase)
|
|
968
|
-
const expectedValues = attributeNames.map(
|
|
969
|
-
const missingAttributes = []
|
|
952
|
+
const attributeNames = Object.keys(cssPropertiesCamelCase);
|
|
953
|
+
const expectedValues = attributeNames.map(name => cssPropertiesCamelCase[name]);
|
|
954
|
+
const missingAttributes = [];
|
|
970
955
|
|
|
971
956
|
for (const el of els) {
|
|
972
|
-
const attributeValues = await Promise.all(attributeNames.map(
|
|
957
|
+
const attributeValues = await Promise.all(attributeNames.map(attr => el.getCssValue(attr)));
|
|
973
958
|
|
|
974
959
|
const missing = attributeValues.filter((actual, i) => {
|
|
975
|
-
const prop = attributeNames[i]
|
|
976
|
-
let propValue = actual
|
|
960
|
+
const prop = attributeNames[i];
|
|
961
|
+
let propValue = actual;
|
|
977
962
|
if (isColorProperty(prop) && propValue) {
|
|
978
|
-
propValue = convertColorToRGBA(propValue)
|
|
963
|
+
propValue = convertColorToRGBA(propValue);
|
|
979
964
|
}
|
|
980
|
-
return propValue !== expectedValues[i]
|
|
981
|
-
})
|
|
965
|
+
return propValue !== expectedValues[i];
|
|
966
|
+
});
|
|
982
967
|
if (missing.length) {
|
|
983
|
-
missingAttributes.push(...missing)
|
|
968
|
+
missingAttributes.push(...missing);
|
|
984
969
|
}
|
|
985
970
|
}
|
|
986
|
-
return equals(
|
|
987
|
-
`all elements (${new Locator(locator)}) to have CSS property ${JSON.stringify(cssProperties)}`,
|
|
988
|
-
).assert(missingAttributes.length, 0)
|
|
971
|
+
return equals(`all elements (${(new Locator(locator))}) to have CSS property ${JSON.stringify(cssProperties)}`).assert(missingAttributes.length, 0);
|
|
989
972
|
}
|
|
990
973
|
|
|
991
974
|
/**
|
|
992
975
|
* {{> seeAttributesOnElements }}
|
|
993
976
|
*/
|
|
994
977
|
async seeAttributesOnElements(locator, attributes) {
|
|
995
|
-
const els = await this._locate(locator)
|
|
996
|
-
assertElementExists(els, locator)
|
|
978
|
+
const els = await this._locate(locator);
|
|
979
|
+
assertElementExists(els, locator);
|
|
997
980
|
|
|
998
|
-
const attributeNames = Object.keys(attributes)
|
|
999
|
-
const expectedValues = attributeNames.map(
|
|
1000
|
-
const missingAttributes = []
|
|
981
|
+
const attributeNames = Object.keys(attributes);
|
|
982
|
+
const expectedValues = attributeNames.map(name => attributes[name]);
|
|
983
|
+
const missingAttributes = [];
|
|
1001
984
|
|
|
1002
985
|
for (const el of els) {
|
|
1003
|
-
const attributeValues = await Promise.all(attributeNames.map(
|
|
986
|
+
const attributeValues = await Promise.all(attributeNames.map(attr => el.getAttribute(attr)));
|
|
1004
987
|
const missing = attributeValues.filter((actual, i) => {
|
|
1005
988
|
if (expectedValues[i] instanceof RegExp) {
|
|
1006
|
-
return expectedValues[i].test(actual)
|
|
989
|
+
return expectedValues[i].test(actual);
|
|
1007
990
|
}
|
|
1008
|
-
return actual !== expectedValues[i]
|
|
1009
|
-
})
|
|
991
|
+
return actual !== expectedValues[i];
|
|
992
|
+
});
|
|
1010
993
|
if (missing.length) {
|
|
1011
|
-
missingAttributes.push(...missing)
|
|
994
|
+
missingAttributes.push(...missing);
|
|
1012
995
|
}
|
|
1013
996
|
}
|
|
1014
997
|
|
|
1015
|
-
return equals(`all elements (${new Locator(locator)}) to have attributes ${JSON.stringify(attributes)}`).assert(
|
|
1016
|
-
missingAttributes.length,
|
|
1017
|
-
0,
|
|
1018
|
-
)
|
|
998
|
+
return equals(`all elements (${(new Locator(locator))}) to have attributes ${JSON.stringify(attributes)}`).assert(missingAttributes.length, 0);
|
|
1019
999
|
}
|
|
1020
1000
|
|
|
1021
1001
|
/**
|
|
1022
1002
|
* {{> executeScript }}
|
|
1023
1003
|
*/
|
|
1024
1004
|
async executeScript() {
|
|
1025
|
-
return this.browser.executeScript.apply(this.browser, arguments)
|
|
1005
|
+
return this.browser.executeScript.apply(this.browser, arguments);
|
|
1026
1006
|
}
|
|
1027
1007
|
|
|
1028
1008
|
/**
|
|
1029
1009
|
* {{> executeAsyncScript }}
|
|
1030
1010
|
*/
|
|
1031
1011
|
async executeAsyncScript() {
|
|
1032
|
-
this.browser.manage().timeouts().setScriptTimeout(this.options.scriptTimeout)
|
|
1033
|
-
return this.browser.executeAsyncScript.apply(this.browser, arguments)
|
|
1012
|
+
this.browser.manage().timeouts().setScriptTimeout(this.options.scriptTimeout);
|
|
1013
|
+
return this.browser.executeAsyncScript.apply(this.browser, arguments);
|
|
1034
1014
|
}
|
|
1035
1015
|
|
|
1036
1016
|
/**
|
|
1037
1017
|
* {{> seeInCurrentUrl }}
|
|
1038
1018
|
*/
|
|
1039
1019
|
async seeInCurrentUrl(url) {
|
|
1040
|
-
return this.browser.getCurrentUrl().then(
|
|
1020
|
+
return this.browser.getCurrentUrl().then(currentUrl => stringIncludes('url').assert(url, currentUrl));
|
|
1041
1021
|
}
|
|
1042
1022
|
|
|
1043
1023
|
/**
|
|
1044
1024
|
* {{> dontSeeInCurrentUrl }}
|
|
1045
1025
|
*/
|
|
1046
1026
|
async dontSeeInCurrentUrl(url) {
|
|
1047
|
-
return this.browser.getCurrentUrl().then(
|
|
1027
|
+
return this.browser.getCurrentUrl().then(currentUrl => stringIncludes('url').negate(url, currentUrl));
|
|
1048
1028
|
}
|
|
1049
1029
|
|
|
1050
1030
|
/**
|
|
1051
1031
|
* {{> seeCurrentUrlEquals }}
|
|
1052
1032
|
*/
|
|
1053
1033
|
async seeCurrentUrlEquals(url) {
|
|
1054
|
-
return this.browser.getCurrentUrl().then(
|
|
1034
|
+
return this.browser.getCurrentUrl().then(currentUrl => urlEquals(this.options.url).assert(url, currentUrl));
|
|
1055
1035
|
}
|
|
1056
1036
|
|
|
1057
1037
|
/**
|
|
1058
1038
|
* {{> dontSeeCurrentUrlEquals }}
|
|
1059
1039
|
*/
|
|
1060
1040
|
async dontSeeCurrentUrlEquals(url) {
|
|
1061
|
-
return this.browser.getCurrentUrl().then(
|
|
1041
|
+
return this.browser.getCurrentUrl().then(currentUrl => urlEquals(this.options.url).negate(url, currentUrl));
|
|
1062
1042
|
}
|
|
1063
1043
|
|
|
1064
1044
|
/**
|
|
@@ -1066,57 +1046,56 @@ class Protractor extends Helper {
|
|
|
1066
1046
|
*
|
|
1067
1047
|
*/
|
|
1068
1048
|
async saveElementScreenshot(locator, fileName) {
|
|
1069
|
-
const outputFile = screenshotOutputFolder(fileName)
|
|
1049
|
+
const outputFile = screenshotOutputFolder(fileName);
|
|
1070
1050
|
|
|
1071
1051
|
const writeFile = (png, outputFile) => {
|
|
1072
|
-
const fs = require('fs')
|
|
1073
|
-
const stream = fs.createWriteStream(outputFile)
|
|
1074
|
-
stream.write(Buffer.from(png, 'base64'))
|
|
1075
|
-
stream.end()
|
|
1076
|
-
return new Promise(
|
|
1077
|
-
}
|
|
1052
|
+
const fs = require('fs');
|
|
1053
|
+
const stream = fs.createWriteStream(outputFile);
|
|
1054
|
+
stream.write(Buffer.from(png, 'base64'));
|
|
1055
|
+
stream.end();
|
|
1056
|
+
return new Promise(resolve => stream.on('finish', resolve)); // eslint-disable-line no-promise-executor-return
|
|
1057
|
+
};
|
|
1078
1058
|
|
|
1079
|
-
const res = await this._locate(locator)
|
|
1080
|
-
assertElementExists(res, locator)
|
|
1081
|
-
if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`)
|
|
1082
|
-
const elem = res[0]
|
|
1083
|
-
this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
|
|
1084
|
-
const png = await elem.takeScreenshot()
|
|
1085
|
-
return writeFile(png, outputFile)
|
|
1059
|
+
const res = await this._locate(locator);
|
|
1060
|
+
assertElementExists(res, locator);
|
|
1061
|
+
if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
|
|
1062
|
+
const elem = res[0];
|
|
1063
|
+
this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
|
|
1064
|
+
const png = await elem.takeScreenshot();
|
|
1065
|
+
return writeFile(png, outputFile);
|
|
1086
1066
|
}
|
|
1087
1067
|
|
|
1088
1068
|
/**
|
|
1089
1069
|
* {{> saveScreenshot }}
|
|
1090
1070
|
*/
|
|
1091
1071
|
async saveScreenshot(fileName, fullPage = false) {
|
|
1092
|
-
const outputFile = screenshotOutputFolder(fileName)
|
|
1072
|
+
const outputFile = screenshotOutputFolder(fileName);
|
|
1093
1073
|
|
|
1094
1074
|
const writeFile = (png, outputFile) => {
|
|
1095
|
-
const fs = require('fs')
|
|
1096
|
-
const stream = fs.createWriteStream(outputFile)
|
|
1097
|
-
stream.write(Buffer.from(png, 'base64'))
|
|
1098
|
-
stream.end()
|
|
1099
|
-
return new Promise(
|
|
1100
|
-
}
|
|
1075
|
+
const fs = require('fs');
|
|
1076
|
+
const stream = fs.createWriteStream(outputFile);
|
|
1077
|
+
stream.write(Buffer.from(png, 'base64'));
|
|
1078
|
+
stream.end();
|
|
1079
|
+
return new Promise(resolve => stream.on('finish', resolve)); // eslint-disable-line no-promise-executor-return
|
|
1080
|
+
};
|
|
1101
1081
|
|
|
1102
1082
|
if (!fullPage) {
|
|
1103
|
-
this.debug(`Screenshot has been saved to ${outputFile}`)
|
|
1104
|
-
const png = await this.browser.takeScreenshot()
|
|
1105
|
-
return writeFile(png, outputFile)
|
|
1083
|
+
this.debug(`Screenshot has been saved to ${outputFile}`);
|
|
1084
|
+
const png = await this.browser.takeScreenshot();
|
|
1085
|
+
return writeFile(png, outputFile);
|
|
1106
1086
|
}
|
|
1107
1087
|
|
|
1108
|
-
let { width, height } = await this.browser.executeScript(() => ({
|
|
1109
|
-
// eslint-disable-line
|
|
1088
|
+
let { width, height } = await this.browser.executeScript(() => ({ // eslint-disable-line
|
|
1110
1089
|
height: document.body.scrollHeight,
|
|
1111
1090
|
width: document.body.scrollWidth,
|
|
1112
|
-
}))
|
|
1091
|
+
}));
|
|
1113
1092
|
|
|
1114
|
-
if (height < 100) height = 500
|
|
1093
|
+
if (height < 100) height = 500;
|
|
1115
1094
|
|
|
1116
|
-
await this.browser.manage().window().setSize(width, height)
|
|
1117
|
-
this.debug(`Screenshot has been saved to ${outputFile}, size: ${width}x${height}`)
|
|
1118
|
-
const png = await this.browser.takeScreenshot()
|
|
1119
|
-
return writeFile(png, outputFile)
|
|
1095
|
+
await this.browser.manage().window().setSize(width, height);
|
|
1096
|
+
this.debug(`Screenshot has been saved to ${outputFile}, size: ${width}x${height}`);
|
|
1097
|
+
const png = await this.browser.takeScreenshot();
|
|
1098
|
+
return writeFile(png, outputFile);
|
|
1120
1099
|
}
|
|
1121
1100
|
|
|
1122
1101
|
/**
|
|
@@ -1124,29 +1103,23 @@ class Protractor extends Helper {
|
|
|
1124
1103
|
*/
|
|
1125
1104
|
async clearCookie(cookie = null) {
|
|
1126
1105
|
if (!cookie) {
|
|
1127
|
-
return this.browser.manage().deleteAllCookies()
|
|
1106
|
+
return this.browser.manage().deleteAllCookies();
|
|
1128
1107
|
}
|
|
1129
|
-
return this.browser.manage().deleteCookie(cookie)
|
|
1108
|
+
return this.browser.manage().deleteCookie(cookie);
|
|
1130
1109
|
}
|
|
1131
1110
|
|
|
1132
1111
|
/**
|
|
1133
1112
|
* {{> seeCookie }}
|
|
1134
1113
|
*/
|
|
1135
1114
|
async seeCookie(name) {
|
|
1136
|
-
return this.browser
|
|
1137
|
-
.manage()
|
|
1138
|
-
.getCookie(name)
|
|
1139
|
-
.then((res) => truth(`cookie ${name}`, 'to be set').assert(res))
|
|
1115
|
+
return this.browser.manage().getCookie(name).then(res => truth(`cookie ${name}`, 'to be set').assert(res));
|
|
1140
1116
|
}
|
|
1141
1117
|
|
|
1142
1118
|
/**
|
|
1143
1119
|
* {{> dontSeeCookie }}
|
|
1144
1120
|
*/
|
|
1145
1121
|
async dontSeeCookie(name) {
|
|
1146
|
-
return this.browser
|
|
1147
|
-
.manage()
|
|
1148
|
-
.getCookie(name)
|
|
1149
|
-
.then((res) => truth(`cookie ${name}`, 'to be set').negate(res))
|
|
1122
|
+
return this.browser.manage().getCookie(name).then(res => truth(`cookie ${name}`, 'to be set').negate(res));
|
|
1150
1123
|
}
|
|
1151
1124
|
|
|
1152
1125
|
/**
|
|
@@ -1155,8 +1128,8 @@ class Protractor extends Helper {
|
|
|
1155
1128
|
* Returns cookie in JSON [format](https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object).
|
|
1156
1129
|
*/
|
|
1157
1130
|
async grabCookie(name) {
|
|
1158
|
-
if (!name) return this.browser.manage().getCookies()
|
|
1159
|
-
return this.browser.manage().getCookie(name)
|
|
1131
|
+
if (!name) return this.browser.manage().getCookies();
|
|
1132
|
+
return this.browser.manage().getCookie(name);
|
|
1160
1133
|
}
|
|
1161
1134
|
|
|
1162
1135
|
/**
|
|
@@ -1165,26 +1138,26 @@ class Protractor extends Helper {
|
|
|
1165
1138
|
* libraries](http://jster.net/category/windows-modals-popups). Appium: support only web testing
|
|
1166
1139
|
*/
|
|
1167
1140
|
async acceptPopup() {
|
|
1168
|
-
return this.browser.switchTo().alert().accept()
|
|
1141
|
+
return this.browser.switchTo().alert().accept();
|
|
1169
1142
|
}
|
|
1170
1143
|
|
|
1171
1144
|
/**
|
|
1172
1145
|
* Dismisses the active JavaScript popup, as created by window.alert|window.confirm|window.prompt.
|
|
1173
1146
|
*/
|
|
1174
1147
|
async cancelPopup() {
|
|
1175
|
-
return this.browser.switchTo().alert().dismiss()
|
|
1148
|
+
return this.browser.switchTo().alert().dismiss();
|
|
1176
1149
|
}
|
|
1177
1150
|
|
|
1178
1151
|
/**
|
|
1179
1152
|
* {{> seeInPopup }}
|
|
1180
1153
|
*/
|
|
1181
1154
|
async seeInPopup(text) {
|
|
1182
|
-
const popupAlert = await this.browser.switchTo().alert()
|
|
1183
|
-
const res = await popupAlert.getText()
|
|
1155
|
+
const popupAlert = await this.browser.switchTo().alert();
|
|
1156
|
+
const res = await popupAlert.getText();
|
|
1184
1157
|
if (res === null) {
|
|
1185
|
-
throw new Error('Popup is not opened')
|
|
1158
|
+
throw new Error('Popup is not opened');
|
|
1186
1159
|
}
|
|
1187
|
-
stringIncludes('text in popup').assert(text, res)
|
|
1160
|
+
stringIncludes('text in popup').assert(text, res);
|
|
1188
1161
|
}
|
|
1189
1162
|
|
|
1190
1163
|
/**
|
|
@@ -1196,17 +1169,17 @@ class Protractor extends Helper {
|
|
|
1196
1169
|
*/
|
|
1197
1170
|
async grabPopupText() {
|
|
1198
1171
|
try {
|
|
1199
|
-
const dialog = await this.browser.switchTo().alert()
|
|
1172
|
+
const dialog = await this.browser.switchTo().alert();
|
|
1200
1173
|
|
|
1201
1174
|
if (dialog) {
|
|
1202
|
-
return dialog.getText()
|
|
1175
|
+
return dialog.getText();
|
|
1203
1176
|
}
|
|
1204
1177
|
} catch (e) {
|
|
1205
1178
|
if (e.message.match(/no.*?(alert|modal)/i)) {
|
|
1206
1179
|
// Don't throw an error
|
|
1207
|
-
return null
|
|
1180
|
+
return null;
|
|
1208
1181
|
}
|
|
1209
|
-
throw e
|
|
1182
|
+
throw e;
|
|
1210
1183
|
}
|
|
1211
1184
|
}
|
|
1212
1185
|
|
|
@@ -1215,21 +1188,24 @@ class Protractor extends Helper {
|
|
|
1215
1188
|
*/
|
|
1216
1189
|
async resizeWindow(width, height) {
|
|
1217
1190
|
if (width === 'maximize') {
|
|
1218
|
-
const res = await this.browser.executeScript('return [screen.width, screen.height]')
|
|
1219
|
-
return this.browser.manage().window().setSize(parseInt(res[0], 10), parseInt(res[1], 10))
|
|
1191
|
+
const res = await this.browser.executeScript('return [screen.width, screen.height]');
|
|
1192
|
+
return this.browser.manage().window().setSize(parseInt(res[0], 10), parseInt(res[1], 10));
|
|
1220
1193
|
}
|
|
1221
|
-
return this.browser.manage().window().setSize(parseInt(width, 10), parseInt(height, 10))
|
|
1194
|
+
return this.browser.manage().window().setSize(parseInt(width, 10), parseInt(height, 10));
|
|
1222
1195
|
}
|
|
1223
1196
|
|
|
1224
1197
|
/**
|
|
1225
1198
|
* {{> dragAndDrop }}
|
|
1226
1199
|
*/
|
|
1227
1200
|
async dragAndDrop(srcElement, destElement) {
|
|
1228
|
-
const srcEl = await this._locate(srcElement, true)
|
|
1229
|
-
const destEl = await this._locate(destElement, true)
|
|
1230
|
-
assertElementExists(srcEl, srcElement)
|
|
1231
|
-
assertElementExists(destEl, destElement)
|
|
1232
|
-
return this.browser
|
|
1201
|
+
const srcEl = await this._locate(srcElement, true);
|
|
1202
|
+
const destEl = await this._locate(destElement, true);
|
|
1203
|
+
assertElementExists(srcEl, srcElement);
|
|
1204
|
+
assertElementExists(destEl, destElement);
|
|
1205
|
+
return this.browser
|
|
1206
|
+
.actions()
|
|
1207
|
+
.dragAndDrop(srcEl[0], destEl[0])
|
|
1208
|
+
.perform();
|
|
1233
1209
|
}
|
|
1234
1210
|
|
|
1235
1211
|
/**
|
|
@@ -1240,24 +1216,19 @@ class Protractor extends Helper {
|
|
|
1240
1216
|
* ```
|
|
1241
1217
|
*/
|
|
1242
1218
|
async closeOtherTabs() {
|
|
1243
|
-
const client = this.browser
|
|
1219
|
+
const client = this.browser;
|
|
1244
1220
|
|
|
1245
|
-
const handles = await client.getAllWindowHandles()
|
|
1246
|
-
const currentHandle = await client.getWindowHandle()
|
|
1247
|
-
const otherHandles = handles.filter(
|
|
1221
|
+
const handles = await client.getAllWindowHandles();
|
|
1222
|
+
const currentHandle = await client.getWindowHandle();
|
|
1223
|
+
const otherHandles = handles.filter(handle => handle !== currentHandle);
|
|
1248
1224
|
|
|
1249
|
-
if (!otherHandles || !otherHandles.length) return
|
|
1250
|
-
let p = Promise.resolve()
|
|
1225
|
+
if (!otherHandles || !otherHandles.length) return;
|
|
1226
|
+
let p = Promise.resolve();
|
|
1251
1227
|
otherHandles.forEach((handle) => {
|
|
1252
|
-
p = p.then(() =>
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
.then(() => client.close()),
|
|
1257
|
-
)
|
|
1258
|
-
})
|
|
1259
|
-
p = p.then(() => client.switchTo().window(currentHandle))
|
|
1260
|
-
return p
|
|
1228
|
+
p = p.then(() => client.switchTo().window(handle).then(() => client.close()));
|
|
1229
|
+
});
|
|
1230
|
+
p = p.then(() => client.switchTo().window(currentHandle));
|
|
1231
|
+
return p;
|
|
1261
1232
|
}
|
|
1262
1233
|
|
|
1263
1234
|
/**
|
|
@@ -1268,14 +1239,14 @@ class Protractor extends Helper {
|
|
|
1268
1239
|
* ```
|
|
1269
1240
|
*/
|
|
1270
1241
|
async closeCurrentTab() {
|
|
1271
|
-
const client = this.browser
|
|
1242
|
+
const client = this.browser;
|
|
1272
1243
|
|
|
1273
|
-
const currentHandle = await client.getWindowHandle()
|
|
1274
|
-
const nextHandle = await this._getWindowHandle(-1)
|
|
1244
|
+
const currentHandle = await client.getWindowHandle();
|
|
1245
|
+
const nextHandle = await this._getWindowHandle(-1);
|
|
1275
1246
|
|
|
1276
|
-
await client.switchTo().window(currentHandle)
|
|
1277
|
-
await client.close()
|
|
1278
|
-
return client.switchTo().window(nextHandle)
|
|
1247
|
+
await client.switchTo().window(currentHandle);
|
|
1248
|
+
await client.close();
|
|
1249
|
+
return client.switchTo().window(nextHandle);
|
|
1279
1250
|
}
|
|
1280
1251
|
|
|
1281
1252
|
/**
|
|
@@ -1283,12 +1254,12 @@ class Protractor extends Helper {
|
|
|
1283
1254
|
* @param {Number} offset Offset from current handle index. i.e. offset < 0 will go to the previous handle and positive number will go to the next window handle in sequence.
|
|
1284
1255
|
*/
|
|
1285
1256
|
async _getWindowHandle(offset = 0) {
|
|
1286
|
-
const client = this.browser
|
|
1287
|
-
const handles = await client.getAllWindowHandles()
|
|
1288
|
-
const index = handles.indexOf(await client.getWindowHandle())
|
|
1289
|
-
const nextIndex = index + offset
|
|
1257
|
+
const client = this.browser;
|
|
1258
|
+
const handles = await client.getAllWindowHandles();
|
|
1259
|
+
const index = handles.indexOf(await client.getWindowHandle());
|
|
1260
|
+
const nextIndex = index + offset;
|
|
1290
1261
|
|
|
1291
|
-
return handles[nextIndex]
|
|
1262
|
+
return handles[nextIndex];
|
|
1292
1263
|
// return handles[(index + offset) % handles.length];
|
|
1293
1264
|
}
|
|
1294
1265
|
|
|
@@ -1300,10 +1271,10 @@ class Protractor extends Helper {
|
|
|
1300
1271
|
* ```
|
|
1301
1272
|
*/
|
|
1302
1273
|
async openNewTab() {
|
|
1303
|
-
const client = this.browser
|
|
1304
|
-
await this.executeScript('window.open("about:blank")')
|
|
1305
|
-
const handles = await client.getAllWindowHandles()
|
|
1306
|
-
await client.switchTo().window(handles[handles.length - 1])
|
|
1274
|
+
const client = this.browser;
|
|
1275
|
+
await this.executeScript('window.open("about:blank")');
|
|
1276
|
+
const handles = await client.getAllWindowHandles();
|
|
1277
|
+
await client.switchTo().window(handles[handles.length - 1]);
|
|
1307
1278
|
}
|
|
1308
1279
|
|
|
1309
1280
|
/**
|
|
@@ -1315,13 +1286,13 @@ class Protractor extends Helper {
|
|
|
1315
1286
|
* ```
|
|
1316
1287
|
*/
|
|
1317
1288
|
async switchToNextTab(num = 1) {
|
|
1318
|
-
const client = this.browser
|
|
1319
|
-
const newHandle = await this._getWindowHandle(num)
|
|
1289
|
+
const client = this.browser;
|
|
1290
|
+
const newHandle = await this._getWindowHandle(num);
|
|
1320
1291
|
|
|
1321
1292
|
if (!newHandle) {
|
|
1322
|
-
throw new Error(`There is no ability to switch to next tab with offset ${num}`)
|
|
1293
|
+
throw new Error(`There is no ability to switch to next tab with offset ${num}`);
|
|
1323
1294
|
}
|
|
1324
|
-
return client.switchTo().window(newHandle)
|
|
1295
|
+
return client.switchTo().window(newHandle);
|
|
1325
1296
|
}
|
|
1326
1297
|
|
|
1327
1298
|
/**
|
|
@@ -1333,21 +1304,21 @@ class Protractor extends Helper {
|
|
|
1333
1304
|
* ```
|
|
1334
1305
|
*/
|
|
1335
1306
|
async switchToPreviousTab(num = 1) {
|
|
1336
|
-
const client = this.browser
|
|
1337
|
-
const newHandle = await this._getWindowHandle(-1 * num)
|
|
1307
|
+
const client = this.browser;
|
|
1308
|
+
const newHandle = await this._getWindowHandle(-1 * num);
|
|
1338
1309
|
|
|
1339
1310
|
if (!newHandle) {
|
|
1340
|
-
throw new Error(`There is no ability to switch to previous tab with offset ${num}`)
|
|
1311
|
+
throw new Error(`There is no ability to switch to previous tab with offset ${num}`);
|
|
1341
1312
|
}
|
|
1342
|
-
return client.switchTo().window(newHandle)
|
|
1313
|
+
return client.switchTo().window(newHandle);
|
|
1343
1314
|
}
|
|
1344
1315
|
|
|
1345
1316
|
/**
|
|
1346
1317
|
* {{> grabNumberOfOpenTabs }}
|
|
1347
1318
|
*/
|
|
1348
1319
|
async grabNumberOfOpenTabs() {
|
|
1349
|
-
const pages = await this.browser.getAllWindowHandles()
|
|
1350
|
-
return pages.length
|
|
1320
|
+
const pages = await this.browser.getAllWindowHandles();
|
|
1321
|
+
return pages.length;
|
|
1351
1322
|
}
|
|
1352
1323
|
|
|
1353
1324
|
/**
|
|
@@ -1355,51 +1326,51 @@ class Protractor extends Helper {
|
|
|
1355
1326
|
*/
|
|
1356
1327
|
async switchTo(locator) {
|
|
1357
1328
|
if (Number.isInteger(locator)) {
|
|
1358
|
-
return this.browser.switchTo().frame(locator)
|
|
1329
|
+
return this.browser.switchTo().frame(locator);
|
|
1359
1330
|
}
|
|
1360
1331
|
if (!locator) {
|
|
1361
|
-
return this.browser.switchTo().frame(null)
|
|
1332
|
+
return this.browser.switchTo().frame(null);
|
|
1362
1333
|
}
|
|
1363
1334
|
|
|
1364
|
-
const els = await this._locate(withStrictLocator.call(this, locator), true)
|
|
1365
|
-
assertElementExists(els, locator)
|
|
1366
|
-
return this.browser.switchTo().frame(els[0])
|
|
1335
|
+
const els = await this._locate(withStrictLocator.call(this, locator), true);
|
|
1336
|
+
assertElementExists(els, locator);
|
|
1337
|
+
return this.browser.switchTo().frame(els[0]);
|
|
1367
1338
|
}
|
|
1368
1339
|
|
|
1369
1340
|
/**
|
|
1370
1341
|
* {{> wait }}
|
|
1371
1342
|
*/
|
|
1372
1343
|
wait(sec) {
|
|
1373
|
-
return this.browser.sleep(sec * 1000)
|
|
1344
|
+
return this.browser.sleep(sec * 1000);
|
|
1374
1345
|
}
|
|
1375
1346
|
|
|
1376
1347
|
/**
|
|
1377
1348
|
* {{> waitForElement }}
|
|
1378
1349
|
*/
|
|
1379
1350
|
async waitForElement(locator, sec = null) {
|
|
1380
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1381
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1382
|
-
return this.browser.wait(EC.presenceOf(el), aSec * 1000)
|
|
1351
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1352
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1353
|
+
return this.browser.wait(EC.presenceOf(el), aSec * 1000);
|
|
1383
1354
|
}
|
|
1384
1355
|
|
|
1385
1356
|
async waitUntilExists(locator, sec = null) {
|
|
1386
1357
|
console.log(`waitUntilExists deprecated:
|
|
1387
1358
|
* use 'waitForElement' to wait for element to be attached
|
|
1388
|
-
* use 'waitForDetached to wait for element to be removed'`)
|
|
1389
|
-
return this.waitForDetached(locator, sec)
|
|
1359
|
+
* use 'waitForDetached to wait for element to be removed'`);
|
|
1360
|
+
return this.waitForDetached(locator, sec);
|
|
1390
1361
|
}
|
|
1391
1362
|
|
|
1392
1363
|
/**
|
|
1393
1364
|
* {{> waitForDetached }}
|
|
1394
1365
|
*/
|
|
1395
1366
|
async waitForDetached(locator, sec = null) {
|
|
1396
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1397
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1367
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1368
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1398
1369
|
return this.browser.wait(EC.not(EC.presenceOf(el)), aSec * 1000).catch((err) => {
|
|
1399
1370
|
if (err.message && err.message.indexOf('Wait timed out after') > -1) {
|
|
1400
|
-
throw new Error(`element (${JSON.stringify(locator)}) still on page after ${sec} sec`)
|
|
1401
|
-
} else throw err
|
|
1402
|
-
})
|
|
1371
|
+
throw new Error(`element (${JSON.stringify(locator)}) still on page after ${sec} sec`);
|
|
1372
|
+
} else throw err;
|
|
1373
|
+
});
|
|
1403
1374
|
}
|
|
1404
1375
|
|
|
1405
1376
|
/**
|
|
@@ -1410,41 +1381,41 @@ class Protractor extends Helper {
|
|
|
1410
1381
|
* ```
|
|
1411
1382
|
*/
|
|
1412
1383
|
async waitForClickable(locator, sec = null) {
|
|
1413
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1414
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1415
|
-
return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000)
|
|
1384
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1385
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1386
|
+
return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000);
|
|
1416
1387
|
}
|
|
1417
1388
|
|
|
1418
1389
|
/**
|
|
1419
1390
|
* {{> waitForVisible }}
|
|
1420
1391
|
*/
|
|
1421
1392
|
async waitForVisible(locator, sec = null) {
|
|
1422
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1423
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1424
|
-
return this.browser.wait(EC.visibilityOf(el), aSec * 1000)
|
|
1393
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1394
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1395
|
+
return this.browser.wait(EC.visibilityOf(el), aSec * 1000);
|
|
1425
1396
|
}
|
|
1426
1397
|
|
|
1427
1398
|
/**
|
|
1428
1399
|
* {{> waitToHide }}
|
|
1429
1400
|
*/
|
|
1430
1401
|
async waitToHide(locator, sec = null) {
|
|
1431
|
-
return this.waitForInvisible(locator, sec)
|
|
1402
|
+
return this.waitForInvisible(locator, sec);
|
|
1432
1403
|
}
|
|
1433
1404
|
|
|
1434
1405
|
/**
|
|
1435
1406
|
* {{> waitForInvisible }}
|
|
1436
1407
|
*/
|
|
1437
1408
|
async waitForInvisible(locator, sec = null) {
|
|
1438
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1439
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1440
|
-
return this.browser.wait(EC.invisibilityOf(el), aSec * 1000)
|
|
1409
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1410
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1411
|
+
return this.browser.wait(EC.invisibilityOf(el), aSec * 1000);
|
|
1441
1412
|
}
|
|
1442
1413
|
|
|
1443
1414
|
async waitForStalenessOf(locator, sec = null) {
|
|
1444
1415
|
console.log(`waitForStalenessOf deprecated.
|
|
1445
1416
|
* Use waitForDetached to wait for element to be removed from page
|
|
1446
|
-
* Use waitForInvisible to wait for element to be hidden on page`)
|
|
1447
|
-
return this.waitForInvisible(locator, sec)
|
|
1417
|
+
* Use waitForInvisible to wait for element to be hidden on page`);
|
|
1418
|
+
return this.waitForInvisible(locator, sec);
|
|
1448
1419
|
}
|
|
1449
1420
|
|
|
1450
1421
|
/**
|
|
@@ -1453,112 +1424,114 @@ class Protractor extends Helper {
|
|
|
1453
1424
|
async waitNumberOfVisibleElements(locator, num, sec = null) {
|
|
1454
1425
|
function visibilityCountOf(loc, expectedCount) {
|
|
1455
1426
|
return function () {
|
|
1456
|
-
return global.element
|
|
1457
|
-
.
|
|
1458
|
-
.filter((el) => el.isDisplayed())
|
|
1427
|
+
return global.element.all(loc)
|
|
1428
|
+
.filter(el => el.isDisplayed())
|
|
1459
1429
|
.count()
|
|
1460
|
-
.then(
|
|
1461
|
-
}
|
|
1430
|
+
.then(count => count === expectedCount);
|
|
1431
|
+
};
|
|
1462
1432
|
}
|
|
1463
1433
|
|
|
1464
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1465
|
-
const guessLoc = guessLocator(locator) || global.by.css(locator)
|
|
1434
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1435
|
+
const guessLoc = guessLocator(locator) || global.by.css(locator);
|
|
1466
1436
|
|
|
1467
|
-
return this.browser.wait(visibilityCountOf(guessLoc, num), aSec * 1000)
|
|
1468
|
-
|
|
1469
|
-
|
|
1437
|
+
return this.browser.wait(visibilityCountOf(guessLoc, num), aSec * 1000)
|
|
1438
|
+
.catch(() => {
|
|
1439
|
+
throw Error(`The number of elements (${(new Locator(locator))}) is not ${num} after ${aSec} sec`);
|
|
1440
|
+
});
|
|
1470
1441
|
}
|
|
1471
1442
|
|
|
1472
1443
|
/**
|
|
1473
1444
|
* {{> waitForEnabled }}
|
|
1474
1445
|
*/
|
|
1475
1446
|
async waitForEnabled(locator, sec = null) {
|
|
1476
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1477
|
-
const el = global.element(guessLocator(locator) || global.by.css(locator))
|
|
1447
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1448
|
+
const el = global.element(guessLocator(locator) || global.by.css(locator));
|
|
1478
1449
|
|
|
1479
|
-
return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000)
|
|
1480
|
-
|
|
1481
|
-
|
|
1450
|
+
return this.browser.wait(EC.elementToBeClickable(el), aSec * 1000)
|
|
1451
|
+
.catch(() => {
|
|
1452
|
+
throw Error(`element (${(new Locator(locator))}) still not enabled after ${aSec} sec`);
|
|
1453
|
+
});
|
|
1482
1454
|
}
|
|
1483
1455
|
|
|
1484
1456
|
/**
|
|
1485
1457
|
* {{> waitForValue }}
|
|
1486
1458
|
*/
|
|
1487
1459
|
async waitForValue(field, value, sec = null) {
|
|
1488
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1460
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1489
1461
|
|
|
1490
1462
|
const valueToBeInElementValue = (loc) => {
|
|
1491
1463
|
return async () => {
|
|
1492
|
-
const els = await findFields(this.browser, loc)
|
|
1464
|
+
const els = await findFields(this.browser, loc);
|
|
1493
1465
|
|
|
1494
1466
|
if (!els) {
|
|
1495
|
-
return false
|
|
1467
|
+
return false;
|
|
1496
1468
|
}
|
|
1497
|
-
const values = await Promise.all(els.map(
|
|
1498
|
-
return values.filter(
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1469
|
+
const values = await Promise.all(els.map(el => el.getAttribute('value')));
|
|
1470
|
+
return values.filter(part => part.indexOf(value) >= 0).length > 0;
|
|
1471
|
+
};
|
|
1472
|
+
};
|
|
1501
1473
|
|
|
1502
|
-
return this.browser.wait(valueToBeInElementValue(field, value), aSec * 1000)
|
|
1503
|
-
|
|
1504
|
-
`element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec
|
|
1505
|
-
)
|
|
1506
|
-
})
|
|
1474
|
+
return this.browser.wait(valueToBeInElementValue(field, value), aSec * 1000)
|
|
1475
|
+
.catch(() => {
|
|
1476
|
+
throw Error(`element (${field}) is not in DOM or there is no element(${field}) with value "${value}" after ${aSec} sec`);
|
|
1477
|
+
});
|
|
1507
1478
|
}
|
|
1508
1479
|
|
|
1509
1480
|
/**
|
|
1510
1481
|
* {{> waitForFunction }}
|
|
1511
1482
|
*/
|
|
1512
1483
|
async waitForFunction(fn, argsOrSec = null, sec = null) {
|
|
1513
|
-
let args = []
|
|
1484
|
+
let args = [];
|
|
1514
1485
|
if (argsOrSec) {
|
|
1515
1486
|
if (Array.isArray(argsOrSec)) {
|
|
1516
|
-
args = argsOrSec
|
|
1487
|
+
args = argsOrSec;
|
|
1517
1488
|
} else if (typeof argsOrSec === 'number') {
|
|
1518
|
-
sec = argsOrSec
|
|
1489
|
+
sec = argsOrSec;
|
|
1519
1490
|
}
|
|
1520
1491
|
}
|
|
1521
1492
|
|
|
1522
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1523
|
-
return this.browser.wait(() => this.browser.executeScript.call(this.browser, fn, ...args), aSec * 1000)
|
|
1493
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1494
|
+
return this.browser.wait(() => this.browser.executeScript.call(this.browser, fn, ...args), aSec * 1000);
|
|
1524
1495
|
}
|
|
1525
1496
|
|
|
1526
1497
|
/**
|
|
1527
1498
|
* {{> waitInUrl }}
|
|
1528
1499
|
*/
|
|
1529
1500
|
async waitInUrl(urlPart, sec = null) {
|
|
1530
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1531
|
-
const waitTimeout = aSec * 1000
|
|
1532
|
-
|
|
1533
|
-
return this.browser.wait(EC.urlContains(urlPart), waitTimeout)
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1501
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1502
|
+
const waitTimeout = aSec * 1000;
|
|
1503
|
+
|
|
1504
|
+
return this.browser.wait(EC.urlContains(urlPart), waitTimeout)
|
|
1505
|
+
.catch(async (e) => {
|
|
1506
|
+
const currUrl = await this.browser.getCurrentUrl();
|
|
1507
|
+
if (/wait timed out after/i.test(e.message)) {
|
|
1508
|
+
throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
|
|
1509
|
+
} else {
|
|
1510
|
+
throw e;
|
|
1511
|
+
}
|
|
1512
|
+
});
|
|
1541
1513
|
}
|
|
1542
1514
|
|
|
1543
1515
|
/**
|
|
1544
1516
|
* {{> waitUrlEquals }}
|
|
1545
1517
|
*/
|
|
1546
1518
|
async waitUrlEquals(urlPart, sec = null) {
|
|
1547
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1548
|
-
const waitTimeout = aSec * 1000
|
|
1549
|
-
const baseUrl = this.options.url
|
|
1519
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1520
|
+
const waitTimeout = aSec * 1000;
|
|
1521
|
+
const baseUrl = this.options.url;
|
|
1550
1522
|
if (urlPart.indexOf('http') < 0) {
|
|
1551
|
-
urlPart = baseUrl + urlPart
|
|
1523
|
+
urlPart = baseUrl + urlPart;
|
|
1552
1524
|
}
|
|
1553
1525
|
|
|
1554
|
-
return this.browser.wait(EC.urlIs(urlPart), waitTimeout)
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1526
|
+
return this.browser.wait(EC.urlIs(urlPart), waitTimeout)
|
|
1527
|
+
.catch(async (e) => {
|
|
1528
|
+
const currUrl = await this.browser.getCurrentUrl();
|
|
1529
|
+
if (/wait timed out after/i.test(e.message)) {
|
|
1530
|
+
throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
|
|
1531
|
+
} else {
|
|
1532
|
+
throw e;
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1562
1535
|
}
|
|
1563
1536
|
|
|
1564
1537
|
/**
|
|
@@ -1566,11 +1539,11 @@ class Protractor extends Helper {
|
|
|
1566
1539
|
*/
|
|
1567
1540
|
async waitForText(text, sec = null, context = null) {
|
|
1568
1541
|
if (!context) {
|
|
1569
|
-
context = this.context
|
|
1542
|
+
context = this.context;
|
|
1570
1543
|
}
|
|
1571
|
-
const el = global.element(guessLocator(context) || global.by.css(context))
|
|
1572
|
-
const aSec = sec || this.options.waitForTimeoutInSeconds
|
|
1573
|
-
return this.browser.wait(EC.textToBePresentInElement(el, text), aSec * 1000)
|
|
1544
|
+
const el = global.element(guessLocator(context) || global.by.css(context));
|
|
1545
|
+
const aSec = sec || this.options.waitForTimeoutInSeconds;
|
|
1546
|
+
return this.browser.wait(EC.textToBePresentInElement(el, text), aSec * 1000);
|
|
1574
1547
|
}
|
|
1575
1548
|
|
|
1576
1549
|
// ANGULAR SPECIFIC
|
|
@@ -1579,22 +1552,22 @@ class Protractor extends Helper {
|
|
|
1579
1552
|
* Moves to url
|
|
1580
1553
|
*/
|
|
1581
1554
|
moveTo(path) {
|
|
1582
|
-
return this.browser.setLocation(path)
|
|
1555
|
+
return this.browser.setLocation(path);
|
|
1583
1556
|
}
|
|
1584
1557
|
|
|
1585
1558
|
/**
|
|
1586
1559
|
* {{> refreshPage }}
|
|
1587
1560
|
*/
|
|
1588
1561
|
refreshPage() {
|
|
1589
|
-
return this.browser.refresh()
|
|
1562
|
+
return this.browser.refresh();
|
|
1590
1563
|
}
|
|
1591
1564
|
|
|
1592
1565
|
/**
|
|
1593
1566
|
* Reloads page
|
|
1594
1567
|
*/
|
|
1595
1568
|
refresh() {
|
|
1596
|
-
console.log('Deprecated in favor of refreshPage')
|
|
1597
|
-
return this.browser.refresh()
|
|
1569
|
+
console.log('Deprecated in favor of refreshPage');
|
|
1570
|
+
return this.browser.refresh();
|
|
1598
1571
|
}
|
|
1599
1572
|
|
|
1600
1573
|
/**
|
|
@@ -1602,37 +1575,25 @@ class Protractor extends Helper {
|
|
|
1602
1575
|
*/
|
|
1603
1576
|
async scrollTo(locator, offsetX = 0, offsetY = 0) {
|
|
1604
1577
|
if (typeof locator === 'number' && typeof offsetX === 'number') {
|
|
1605
|
-
offsetY = offsetX
|
|
1606
|
-
offsetX = locator
|
|
1607
|
-
locator = null
|
|
1578
|
+
offsetY = offsetX;
|
|
1579
|
+
offsetX = locator;
|
|
1580
|
+
locator = null;
|
|
1608
1581
|
}
|
|
1609
1582
|
|
|
1610
1583
|
if (locator) {
|
|
1611
|
-
const res = await this._locate(locator, true)
|
|
1584
|
+
const res = await this._locate(locator, true);
|
|
1612
1585
|
if (!res || res.length === 0) {
|
|
1613
|
-
return truth(`elements of ${new Locator(locator)}`, 'to be seen').assert(false)
|
|
1586
|
+
return truth(`elements of ${(new Locator(locator))}`, 'to be seen').assert(false);
|
|
1614
1587
|
}
|
|
1615
|
-
const elem = res[0]
|
|
1616
|
-
const location = await elem.getLocation()
|
|
1588
|
+
const elem = res[0];
|
|
1589
|
+
const location = await elem.getLocation();
|
|
1617
1590
|
/* eslint-disable prefer-arrow-callback */
|
|
1618
|
-
return this.executeScript(
|
|
1619
|
-
function (x, y) {
|
|
1620
|
-
return window.scrollTo(x, y)
|
|
1621
|
-
},
|
|
1622
|
-
location.x + offsetX,
|
|
1623
|
-
location.y + offsetY,
|
|
1624
|
-
)
|
|
1591
|
+
return this.executeScript(function (x, y) { return window.scrollTo(x, y); }, location.x + offsetX, location.y + offsetY);
|
|
1625
1592
|
/* eslint-enable */
|
|
1626
1593
|
}
|
|
1627
1594
|
|
|
1628
1595
|
/* eslint-disable prefer-arrow-callback, comma-dangle */
|
|
1629
|
-
return this.executeScript(
|
|
1630
|
-
function (x, y) {
|
|
1631
|
-
return window.scrollTo(x, y)
|
|
1632
|
-
},
|
|
1633
|
-
offsetX,
|
|
1634
|
-
offsetY,
|
|
1635
|
-
)
|
|
1596
|
+
return this.executeScript(function (x, y) { return window.scrollTo(x, y); }, offsetX, offsetY);
|
|
1636
1597
|
/* eslint-enable */
|
|
1637
1598
|
}
|
|
1638
1599
|
|
|
@@ -1640,7 +1601,7 @@ class Protractor extends Helper {
|
|
|
1640
1601
|
* {{> scrollPageToTop }}
|
|
1641
1602
|
*/
|
|
1642
1603
|
async scrollPageToTop() {
|
|
1643
|
-
return this.executeScript('window.scrollTo(0, 0);')
|
|
1604
|
+
return this.executeScript('window.scrollTo(0, 0);');
|
|
1644
1605
|
}
|
|
1645
1606
|
|
|
1646
1607
|
/**
|
|
@@ -1649,13 +1610,16 @@ class Protractor extends Helper {
|
|
|
1649
1610
|
async scrollPageToBottom() {
|
|
1650
1611
|
/* eslint-disable prefer-arrow-callback, comma-dangle */
|
|
1651
1612
|
return this.executeScript(function () {
|
|
1652
|
-
const body = document.body
|
|
1653
|
-
const html = document.documentElement
|
|
1654
|
-
window.scrollTo(
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1613
|
+
const body = document.body;
|
|
1614
|
+
const html = document.documentElement;
|
|
1615
|
+
window.scrollTo(0, Math.max(
|
|
1616
|
+
body.scrollHeight,
|
|
1617
|
+
body.offsetHeight,
|
|
1618
|
+
html.clientHeight,
|
|
1619
|
+
html.scrollHeight,
|
|
1620
|
+
html.offsetHeight
|
|
1621
|
+
));
|
|
1622
|
+
});
|
|
1659
1623
|
/* eslint-enable */
|
|
1660
1624
|
}
|
|
1661
1625
|
|
|
@@ -1667,11 +1631,11 @@ class Protractor extends Helper {
|
|
|
1667
1631
|
function getScrollPosition() {
|
|
1668
1632
|
return {
|
|
1669
1633
|
x: window.pageXOffset,
|
|
1670
|
-
y: window.pageYOffset
|
|
1671
|
-
}
|
|
1634
|
+
y: window.pageYOffset
|
|
1635
|
+
};
|
|
1672
1636
|
}
|
|
1673
1637
|
/* eslint-enable comma-dangle */
|
|
1674
|
-
return this.executeScript(getScrollPosition)
|
|
1638
|
+
return this.executeScript(getScrollPosition);
|
|
1675
1639
|
}
|
|
1676
1640
|
|
|
1677
1641
|
/**
|
|
@@ -1684,7 +1648,7 @@ class Protractor extends Helper {
|
|
|
1684
1648
|
* ```
|
|
1685
1649
|
*/
|
|
1686
1650
|
haveModule(modName, fn) {
|
|
1687
|
-
return this.browser.addMockModule(modName, fn)
|
|
1651
|
+
return this.browser.addMockModule(modName, fn);
|
|
1688
1652
|
}
|
|
1689
1653
|
|
|
1690
1654
|
/**
|
|
@@ -1697,175 +1661,175 @@ class Protractor extends Helper {
|
|
|
1697
1661
|
*/
|
|
1698
1662
|
resetModule(modName) {
|
|
1699
1663
|
if (!modName) {
|
|
1700
|
-
return this.browser.clearMockModules()
|
|
1664
|
+
return this.browser.clearMockModules();
|
|
1701
1665
|
}
|
|
1702
|
-
return this.browser.removeMockModule(modName)
|
|
1666
|
+
return this.browser.removeMockModule(modName);
|
|
1703
1667
|
}
|
|
1704
1668
|
|
|
1705
1669
|
/**
|
|
1706
1670
|
* {{> setCookie }}
|
|
1707
1671
|
*/
|
|
1708
1672
|
setCookie(cookie) {
|
|
1709
|
-
return this.browser.manage().addCookie(cookie)
|
|
1673
|
+
return this.browser.manage().addCookie(cookie);
|
|
1710
1674
|
}
|
|
1711
1675
|
}
|
|
1712
1676
|
|
|
1713
|
-
|
|
1677
|
+
export default Protractor;
|
|
1714
1678
|
|
|
1715
1679
|
async function findCheckable(client, locator) {
|
|
1716
|
-
const matchedLocator = guessLocator(locator)
|
|
1680
|
+
const matchedLocator = guessLocator(locator);
|
|
1717
1681
|
if (matchedLocator) {
|
|
1718
|
-
return client.findElements(matchedLocator)
|
|
1682
|
+
return client.findElements(matchedLocator);
|
|
1719
1683
|
}
|
|
1720
|
-
const literal = xpathLocator.literal(locator)
|
|
1721
|
-
let els = await client.findElements(global.by.xpath(Locator.checkable.byText(literal)))
|
|
1684
|
+
const literal = xpathLocator.literal(locator);
|
|
1685
|
+
let els = await client.findElements(global.by.xpath(Locator.checkable.byText(literal)));
|
|
1722
1686
|
if (els.length) {
|
|
1723
|
-
return els
|
|
1687
|
+
return els;
|
|
1724
1688
|
}
|
|
1725
|
-
els = await client.findElements(global.by.xpath(Locator.checkable.byName(literal)))
|
|
1689
|
+
els = await client.findElements(global.by.xpath(Locator.checkable.byName(literal)));
|
|
1726
1690
|
if (els.length) {
|
|
1727
|
-
return els
|
|
1691
|
+
return els;
|
|
1728
1692
|
}
|
|
1729
|
-
return client.findElements(global.by.css(locator))
|
|
1693
|
+
return client.findElements(global.by.css(locator));
|
|
1730
1694
|
}
|
|
1731
1695
|
|
|
1732
1696
|
function withStrictLocator(locator) {
|
|
1733
|
-
locator = new Locator(locator)
|
|
1734
|
-
if (locator.isAccessibilityId()) return withAccessiblitiyLocator.call(this, locator.value)
|
|
1735
|
-
return locator.simplify()
|
|
1697
|
+
locator = new Locator(locator);
|
|
1698
|
+
if (locator.isAccessibilityId()) return withAccessiblitiyLocator.call(this, locator.value);
|
|
1699
|
+
return locator.simplify();
|
|
1736
1700
|
}
|
|
1737
1701
|
|
|
1738
1702
|
function withAccessiblitiyLocator(locator) {
|
|
1739
1703
|
if (this.isWeb === false) {
|
|
1740
|
-
return `accessibility id:${locator.slice(1)}
|
|
1704
|
+
return `accessibility id:${locator.slice(1)}`;
|
|
1741
1705
|
}
|
|
1742
|
-
return `[aria-label="${locator.slice(1)}"]
|
|
1706
|
+
return `[aria-label="${locator.slice(1)}"]`;
|
|
1743
1707
|
// hook before webdriverio supports native ~ locators in web
|
|
1744
1708
|
}
|
|
1745
1709
|
|
|
1746
1710
|
async function findFields(client, locator) {
|
|
1747
|
-
const matchedLocator = guessLocator(locator)
|
|
1711
|
+
const matchedLocator = guessLocator(locator);
|
|
1748
1712
|
if (matchedLocator) {
|
|
1749
|
-
return client.findElements(matchedLocator)
|
|
1713
|
+
return client.findElements(matchedLocator);
|
|
1750
1714
|
}
|
|
1751
|
-
const literal = xpathLocator.literal(locator)
|
|
1715
|
+
const literal = xpathLocator.literal(locator);
|
|
1752
1716
|
|
|
1753
|
-
let els = await client.findElements(global.by.xpath(Locator.field.labelEquals(literal)))
|
|
1717
|
+
let els = await client.findElements(global.by.xpath(Locator.field.labelEquals(literal)));
|
|
1754
1718
|
if (els.length) {
|
|
1755
|
-
return els
|
|
1719
|
+
return els;
|
|
1756
1720
|
}
|
|
1757
1721
|
|
|
1758
|
-
els = await client.findElements(global.by.xpath(Locator.field.labelContains(literal)))
|
|
1722
|
+
els = await client.findElements(global.by.xpath(Locator.field.labelContains(literal)));
|
|
1759
1723
|
if (els.length) {
|
|
1760
|
-
return els
|
|
1724
|
+
return els;
|
|
1761
1725
|
}
|
|
1762
|
-
els = await client.findElements(global.by.xpath(Locator.field.byName(literal)))
|
|
1726
|
+
els = await client.findElements(global.by.xpath(Locator.field.byName(literal)));
|
|
1763
1727
|
if (els.length) {
|
|
1764
|
-
return els
|
|
1728
|
+
return els;
|
|
1765
1729
|
}
|
|
1766
|
-
return client.findElements(global.by.css(locator))
|
|
1730
|
+
return client.findElements(global.by.css(locator));
|
|
1767
1731
|
}
|
|
1768
1732
|
|
|
1769
1733
|
async function proceedSee(assertType, text, context) {
|
|
1770
|
-
let description
|
|
1771
|
-
let locator
|
|
1734
|
+
let description;
|
|
1735
|
+
let locator;
|
|
1772
1736
|
if (!context) {
|
|
1773
1737
|
if (this.context === this.options.rootElement) {
|
|
1774
|
-
locator = guessLocator(this.context) || global.by.css(this.context)
|
|
1775
|
-
description = 'web application'
|
|
1738
|
+
locator = guessLocator(this.context) || global.by.css(this.context);
|
|
1739
|
+
description = 'web application';
|
|
1776
1740
|
} else {
|
|
1777
1741
|
// inside within block
|
|
1778
|
-
locator = global.by.xpath('.//*')
|
|
1779
|
-
description = `current context ${new Locator(context).toString()}
|
|
1742
|
+
locator = global.by.xpath('.//*');
|
|
1743
|
+
description = `current context ${(new Locator(context)).toString()}`;
|
|
1780
1744
|
}
|
|
1781
1745
|
} else {
|
|
1782
|
-
locator = guessLocator(context) || global.by.css(context)
|
|
1783
|
-
description = `element ${new Locator(context).toString()}
|
|
1784
|
-
}
|
|
1785
|
-
const enableSmartWait = !!this.context && assertType === 'assert'
|
|
1786
|
-
const els = await this._smartWait(() => this.browser.findElements(locator), enableSmartWait)
|
|
1787
|
-
const promises = []
|
|
1788
|
-
let source = ''
|
|
1789
|
-
els.forEach(
|
|
1790
|
-
await Promise.all(promises)
|
|
1791
|
-
return stringIncludes(description)[assertType](text, source)
|
|
1746
|
+
locator = guessLocator(context) || global.by.css(context);
|
|
1747
|
+
description = `element ${(new Locator(context)).toString()}`;
|
|
1748
|
+
}
|
|
1749
|
+
const enableSmartWait = !!this.context && assertType === 'assert';
|
|
1750
|
+
const els = await this._smartWait(() => this.browser.findElements(locator), enableSmartWait);
|
|
1751
|
+
const promises = [];
|
|
1752
|
+
let source = '';
|
|
1753
|
+
els.forEach(el => promises.push(el.getText().then(elText => source += `| ${elText}`)));
|
|
1754
|
+
await Promise.all(promises);
|
|
1755
|
+
return stringIncludes(description)[assertType](text, source);
|
|
1792
1756
|
}
|
|
1793
1757
|
|
|
1794
1758
|
async function proceedSeeInField(assertType, field, value) {
|
|
1795
|
-
const els = await findFields(this.browser, field)
|
|
1796
|
-
assertElementExists(els, field, 'Field')
|
|
1797
|
-
const el = els[0]
|
|
1798
|
-
const tag = await el.getTagName()
|
|
1799
|
-
const fieldVal = await el.getAttribute('value')
|
|
1759
|
+
const els = await findFields(this.browser, field);
|
|
1760
|
+
assertElementExists(els, field, 'Field');
|
|
1761
|
+
const el = els[0];
|
|
1762
|
+
const tag = await el.getTagName();
|
|
1763
|
+
const fieldVal = await el.getAttribute('value');
|
|
1800
1764
|
if (tag === 'select') {
|
|
1801
1765
|
// locate option by values and check them
|
|
1802
|
-
const literal = xpathLocator.literal(fieldVal)
|
|
1803
|
-
const textEl = await el.findElement(global.by.xpath(Locator.select.byValue(literal)))
|
|
1804
|
-
const text = await textEl.getText()
|
|
1805
|
-
return equals(`select option by ${field}`)[assertType](value, text)
|
|
1766
|
+
const literal = xpathLocator.literal(fieldVal);
|
|
1767
|
+
const textEl = await el.findElement(global.by.xpath(Locator.select.byValue(literal)));
|
|
1768
|
+
const text = await textEl.getText();
|
|
1769
|
+
return equals(`select option by ${field}`)[assertType](value, text);
|
|
1806
1770
|
}
|
|
1807
|
-
return stringIncludes(`field by ${field}`)[assertType](value, fieldVal)
|
|
1771
|
+
return stringIncludes(`field by ${field}`)[assertType](value, fieldVal);
|
|
1808
1772
|
}
|
|
1809
1773
|
|
|
1810
1774
|
async function proceedIsChecked(assertType, option) {
|
|
1811
|
-
const els = await findCheckable(this.browser, option)
|
|
1812
|
-
assertElementExists(els, option, 'Option')
|
|
1813
|
-
const elsSelected = []
|
|
1814
|
-
els.forEach(
|
|
1815
|
-
const values = await Promise.all(elsSelected)
|
|
1816
|
-
const selected = values.reduce((prev, cur) => prev || cur)
|
|
1817
|
-
return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
|
|
1775
|
+
const els = await findCheckable(this.browser, option);
|
|
1776
|
+
assertElementExists(els, option, 'Option');
|
|
1777
|
+
const elsSelected = [];
|
|
1778
|
+
els.forEach(el => elsSelected.push(el.isSelected()));
|
|
1779
|
+
const values = await Promise.all(elsSelected);
|
|
1780
|
+
const selected = values.reduce((prev, cur) => prev || cur);
|
|
1781
|
+
return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
|
|
1818
1782
|
}
|
|
1819
1783
|
|
|
1820
1784
|
async function findClickable(matcher, locator) {
|
|
1821
|
-
locator = new Locator(locator)
|
|
1785
|
+
locator = new Locator(locator);
|
|
1822
1786
|
if (!locator.isFuzzy()) {
|
|
1823
|
-
const els = await this._locate(locator, true)
|
|
1824
|
-
assertElementExists(els, locator.value)
|
|
1825
|
-
return els[0]
|
|
1787
|
+
const els = await this._locate(locator, true);
|
|
1788
|
+
assertElementExists(els, locator.value);
|
|
1789
|
+
return els[0];
|
|
1826
1790
|
}
|
|
1827
|
-
const literal = xpathLocator.literal(locator.value)
|
|
1828
|
-
const narrowLocator = Locator.clickable.narrow(literal)
|
|
1829
|
-
let els = await matcher.findElements(global.by.xpath(narrowLocator))
|
|
1791
|
+
const literal = xpathLocator.literal(locator.value);
|
|
1792
|
+
const narrowLocator = Locator.clickable.narrow(literal);
|
|
1793
|
+
let els = await matcher.findElements(global.by.xpath(narrowLocator));
|
|
1830
1794
|
if (els.length) {
|
|
1831
|
-
return els[0]
|
|
1795
|
+
return els[0];
|
|
1832
1796
|
}
|
|
1833
1797
|
|
|
1834
|
-
els = await matcher.findElements(global.by.xpath(Locator.clickable.wide(literal)))
|
|
1798
|
+
els = await matcher.findElements(global.by.xpath(Locator.clickable.wide(literal)));
|
|
1835
1799
|
if (els.length) {
|
|
1836
|
-
return els[0]
|
|
1800
|
+
return els[0];
|
|
1837
1801
|
}
|
|
1838
|
-
return matcher.findElement(global.by.css(locator.value))
|
|
1802
|
+
return matcher.findElement(global.by.css(locator.value));
|
|
1839
1803
|
}
|
|
1840
1804
|
|
|
1841
1805
|
function guessLocator(locator) {
|
|
1842
|
-
const l = new Locator(locator)
|
|
1843
|
-
if (l.isFuzzy()) return false
|
|
1844
|
-
if (l.type) return global.by[l.type](l.value)
|
|
1845
|
-
return false
|
|
1806
|
+
const l = new Locator(locator);
|
|
1807
|
+
if (l.isFuzzy()) return false;
|
|
1808
|
+
if (l.type) return global.by[l.type](l.value);
|
|
1809
|
+
return false;
|
|
1846
1810
|
}
|
|
1847
1811
|
|
|
1848
1812
|
function assertElementExists(res, locator, prefix, suffix) {
|
|
1849
1813
|
if (!res.length) {
|
|
1850
|
-
throw new ElementNotFound(locator, prefix, suffix)
|
|
1814
|
+
throw new ElementNotFound(locator, prefix, suffix);
|
|
1851
1815
|
}
|
|
1852
1816
|
}
|
|
1853
1817
|
|
|
1854
1818
|
function isFrameLocator(locator) {
|
|
1855
|
-
locator = new Locator(locator)
|
|
1856
|
-
if (locator.isFrame()) return locator.value
|
|
1857
|
-
return false
|
|
1819
|
+
locator = new Locator(locator);
|
|
1820
|
+
if (locator.isFrame()) return locator.value;
|
|
1821
|
+
return false;
|
|
1858
1822
|
}
|
|
1859
1823
|
|
|
1860
1824
|
function isWithin() {
|
|
1861
|
-
return Object.keys(withinStore).length !== 0
|
|
1825
|
+
return Object.keys(withinStore).length !== 0;
|
|
1862
1826
|
}
|
|
1863
1827
|
|
|
1864
1828
|
function loadGlobals(browser) {
|
|
1865
|
-
global.browser = browser
|
|
1866
|
-
global.$ = browser
|
|
1867
|
-
global.$$ = browser
|
|
1868
|
-
global.element = browser.element
|
|
1869
|
-
global.by = global.By = new ProtractorBy()
|
|
1870
|
-
global.ExpectedConditions = EC = new ProtractorExpectedConditions(browser)
|
|
1829
|
+
global.browser = browser;
|
|
1830
|
+
global.$ = browser.$;
|
|
1831
|
+
global.$$ = browser.$$;
|
|
1832
|
+
global.element = browser.element;
|
|
1833
|
+
global.by = global.By = new ProtractorBy();
|
|
1834
|
+
global.ExpectedConditions = EC = new ProtractorExpectedConditions(browser);
|
|
1871
1835
|
}
|