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