webdriverio 4.14.0 → 4.14.4
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/CHANGELOG.md +17 -0
- package/build/lib/commands/deleteCookie.js +1 -1
- package/build/lib/commands/getCookie.js +1 -1
- package/build/lib/commands/leftClick.js +2 -0
- package/build/lib/commands/middleClick.js +2 -0
- package/build/lib/commands/moveToObject.js +4 -37
- package/build/lib/commands/rightClick.js +2 -0
- package/build/lib/commands/setCookie.js +10 -2
- package/build/lib/helpers/detectSeleniumBackend.js +13 -1
- package/build/lib/helpers/findElementStrategy.js +3 -4
- package/build/lib/helpers/findMoveToCoordinates.js +42 -0
- package/build/lib/helpers/handleMouseButtonProtocol.js +34 -1
- package/build/lib/helpers/utilities.js +20 -1
- package/build/lib/helpers/wdio.conf.ejs +6 -0
- package/build/lib/protocol/execute.js +4 -1
- package/build/lib/protocol/moveTo.js +35 -1
- package/build/lib/utils/BaseReporter.js +16 -1
- package/build/lib/utils/ConfigParser.js +41 -19
- package/build/lib/utils/ReporterStats.js +7 -0
- package/build/lib/utils/RequestHandler.js +13 -1
- package/build/lib/webdriverio.js +0 -1
- package/build/package.json +1 -1
- package/docs/guide/getstarted/boilerplate.md +26 -0
- package/docs/guide/testrunner/configurationfile.md +12 -6
- package/docs/guide/testrunner/organizesuite.md +6 -0
- package/lib/commands/deleteCookie.js +1 -1
- package/lib/commands/getCookie.js +1 -1
- package/lib/commands/leftClick.js +2 -0
- package/lib/commands/middleClick.js +2 -0
- package/lib/commands/moveToObject.js +4 -37
- package/lib/commands/rightClick.js +2 -0
- package/lib/commands/setCookie.js +10 -2
- package/lib/protocol/execute.js +5 -2
- package/lib/protocol/moveTo.js +27 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
|
+
## unreleased
|
|
3
|
+
* wdio changes
|
|
4
|
+
* add W3C actions protocol fallback for when moveTo protocol returns an error
|
|
5
|
+
* add W3C actions protocol fallback for when leftClick, middleClick or rightClick command / buttonDown, buttonPress, or buttonUp protocol returns an error
|
|
6
|
+
|
|
7
|
+
## v4.14.2 (2019-01-11)
|
|
8
|
+
* bugfix:
|
|
9
|
+
* fix css-id selector
|
|
10
|
+
* fix a nullref exception on network failures where response had no body
|
|
11
|
+
|
|
12
|
+
## v4.14.1 (2018-11-30)
|
|
13
|
+
* global:
|
|
14
|
+
* add config `region` that allows to specify the SauceLabs datacenter region
|
|
15
|
+
* wdio changes:
|
|
16
|
+
* Allowing to specify a feature file with a scenario line number (#3019)
|
|
17
|
+
* bugfixes:
|
|
18
|
+
* round values for touchMove command (#3039)
|
|
2
19
|
|
|
3
20
|
## v4.14.0 (2018-10-23)
|
|
4
21
|
* global:
|
|
@@ -53,7 +53,7 @@ var deleteCookie = function deleteCookie(name) {
|
|
|
53
53
|
name = null;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
return this.cookie('DELETE', name);
|
|
56
|
+
return this.cookie('DELETE', typeof name === 'string' ? encodeURIComponent(encodeURIComponent(name)) : name);
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
exports.default = deleteCookie;
|
|
@@ -17,6 +17,8 @@ var leftClick = function leftClick(selector, xoffset, yoffset) {
|
|
|
17
17
|
* Apply left click on an element. If selector is not provided, click on the last
|
|
18
18
|
* moved-to location.
|
|
19
19
|
*
|
|
20
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
21
|
+
*
|
|
20
22
|
* @alias browser.leftClick
|
|
21
23
|
* @param {String} selector element to click on
|
|
22
24
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -17,6 +17,8 @@ var middleClick = function middleClick(selector, xoffset, yoffset) {
|
|
|
17
17
|
* Apply middle click on an element. If selector is not provided, click on the last
|
|
18
18
|
* moved-to location.
|
|
19
19
|
*
|
|
20
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
21
|
+
*
|
|
20
22
|
* @alias browser.middleClick
|
|
21
23
|
* @param {String} selector element to click on
|
|
22
24
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -9,41 +9,6 @@ var _ErrorHandler = require('../utils/ErrorHandler');
|
|
|
9
9
|
var moveToObject = function moveToObject(selector, xoffset, yoffset) {
|
|
10
10
|
var _this = this;
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* check for offset params
|
|
14
|
-
*/
|
|
15
|
-
var hasOffsetParams = true;
|
|
16
|
-
if (typeof xoffset !== 'number' && typeof yoffset !== 'number') {
|
|
17
|
-
hasOffsetParams = false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (this.isMobile) {
|
|
21
|
-
return this.element(selector).then(function (res) {
|
|
22
|
-
/**
|
|
23
|
-
* check if element was found and throw error if not
|
|
24
|
-
*/
|
|
25
|
-
if (!res.value) {
|
|
26
|
-
throw new _ErrorHandler.RuntimeError(7);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return _this.elementIdSize(res.value.ELEMENT).then(function (size) {
|
|
30
|
-
return _this.elementIdLocation(res.value.ELEMENT).then(function (location) {
|
|
31
|
-
return { size, location };
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}).then(function (res) {
|
|
35
|
-
var x = res.location.value.x + res.size.value.width / 2;
|
|
36
|
-
var y = res.location.value.y + res.size.value.height / 2;
|
|
37
|
-
|
|
38
|
-
if (hasOffsetParams) {
|
|
39
|
-
x = res.location.value.x + xoffset;
|
|
40
|
-
y = res.location.value.y + yoffset;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return _this.touchMove(x, y);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
12
|
return this.element(selector).then(function (res) {
|
|
48
13
|
/**
|
|
49
14
|
* check if element was found and throw error if not
|
|
@@ -60,14 +25,16 @@ var moveToObject = function moveToObject(selector, xoffset, yoffset) {
|
|
|
60
25
|
* offset, the mouse will be moved to the center of the element. If the element is not
|
|
61
26
|
* visible, it will be scrolled into view.
|
|
62
27
|
*
|
|
28
|
+
* Uses JSONWireframe moveTo protocol with W3C actions protocol fallback.
|
|
29
|
+
* Uses touchMove protocol for mobile.
|
|
30
|
+
*
|
|
63
31
|
* @alias browser.moveToObject
|
|
64
32
|
* @param {String} selector element to move to
|
|
65
33
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
66
34
|
* @param {Number} yoffset Y offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
67
|
-
* @uses protocol/element, protocol/elementIdLocation
|
|
35
|
+
* @uses protocol/element, protocol/elementIdLocation, protocol/elementIdSize
|
|
68
36
|
* @type action
|
|
69
37
|
*
|
|
70
38
|
*/
|
|
71
|
-
|
|
72
39
|
exports.default = moveToObject;
|
|
73
40
|
module.exports = exports['default'];
|
|
@@ -17,6 +17,8 @@ var rightClick = function rightClick(selector, xoffset, yoffset) {
|
|
|
17
17
|
* Apply right click on an element. If selector is not provided, click on the last
|
|
18
18
|
* moved-to location.
|
|
19
19
|
*
|
|
20
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
21
|
+
*
|
|
20
22
|
* @alias browser.rightClick
|
|
21
23
|
* @param {String} selector element to click on
|
|
22
24
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -4,17 +4,25 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
|
|
7
|
+
var _assign = require('babel-runtime/core-js/object/assign');
|
|
8
|
+
|
|
9
|
+
var _assign2 = _interopRequireDefault(_assign);
|
|
10
|
+
|
|
7
11
|
var _ErrorHandler = require('../utils/ErrorHandler');
|
|
8
12
|
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
+
|
|
9
15
|
var setCookie = function setCookie(cookieObj) {
|
|
16
|
+
var name = cookieObj.name;
|
|
10
17
|
/*!
|
|
11
18
|
* parameter check
|
|
12
19
|
*/
|
|
13
|
-
|
|
20
|
+
|
|
21
|
+
if (typeof cookieObj !== 'object' || !name || typeof name !== 'string') {
|
|
14
22
|
throw new _ErrorHandler.CommandError('Please specify a cookie object to set (see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#cookie-json-object for documentation.');
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
return this.cookie('POST', cookieObj);
|
|
25
|
+
return this.cookie('POST', (0, _assign2.default)({}, cookieObj, { name: encodeURIComponent(encodeURIComponent(name)) }));
|
|
18
26
|
}; /**
|
|
19
27
|
*
|
|
20
28
|
* Sets a [cookie](https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#cookie-json-object)
|
|
@@ -6,6 +6,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
var DEFAULT_HOST = '127.0.0.1';
|
|
7
7
|
var DEFAULT_PORT = 4444;
|
|
8
8
|
|
|
9
|
+
var REGION_MAPPING = {
|
|
10
|
+
'eu': 'eu-central-1'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function getSauceEndpoint(region) {
|
|
14
|
+
var dc = region ? (REGION_MAPPING[region] || region) + '.' : '';
|
|
15
|
+
return `${dc}saucelabs.com`;
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
/**
|
|
10
19
|
* helper to detect the Selenium backend according to given capabilities
|
|
11
20
|
*/
|
|
@@ -25,6 +34,7 @@ var detectSeleniumBackend = function detectSeleniumBackend(capabilities) {
|
|
|
25
34
|
*/
|
|
26
35
|
if (!capabilities.user || !capabilities.key) {
|
|
27
36
|
return {
|
|
37
|
+
protocol: 'http',
|
|
28
38
|
host: DEFAULT_HOST,
|
|
29
39
|
port: DEFAULT_PORT
|
|
30
40
|
};
|
|
@@ -36,6 +46,7 @@ var detectSeleniumBackend = function detectSeleniumBackend(capabilities) {
|
|
|
36
46
|
*/
|
|
37
47
|
if (capabilities.key.length === 20) {
|
|
38
48
|
return {
|
|
49
|
+
protocol: 'http',
|
|
39
50
|
host: 'hub.browserstack.com',
|
|
40
51
|
port: 80
|
|
41
52
|
};
|
|
@@ -47,6 +58,7 @@ var detectSeleniumBackend = function detectSeleniumBackend(capabilities) {
|
|
|
47
58
|
*/
|
|
48
59
|
if (capabilities.key.length === 32) {
|
|
49
60
|
return {
|
|
61
|
+
protocol: 'http',
|
|
50
62
|
host: 'hub.testingbot.com',
|
|
51
63
|
port: 80
|
|
52
64
|
};
|
|
@@ -58,7 +70,7 @@ var detectSeleniumBackend = function detectSeleniumBackend(capabilities) {
|
|
|
58
70
|
*/
|
|
59
71
|
return {
|
|
60
72
|
protocol: 'https',
|
|
61
|
-
host:
|
|
73
|
+
host: capabilities.host || `ondemand.${getSauceEndpoint(capabilities.region)}`,
|
|
62
74
|
port: 443
|
|
63
75
|
};
|
|
64
76
|
};
|
|
@@ -48,11 +48,10 @@ var findStrategy = function findStrategy() {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// check value type
|
|
51
|
-
// use
|
|
52
|
-
//
|
|
51
|
+
// use css selector for hash instead of by.id
|
|
52
|
+
// https://github.com/webdriverio/webdriverio/issues/2780
|
|
53
53
|
if (value.search(/^#-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/) > -1) {
|
|
54
|
-
using = '
|
|
55
|
-
value = value.slice(1);
|
|
54
|
+
using = 'css selector';
|
|
56
55
|
|
|
57
56
|
// use xPath strategy if value starts with //
|
|
58
57
|
} else if (value.indexOf('/') === 0 || value.indexOf('(') === 0 || value.indexOf('../') === 0 || value.indexOf('./') === 0 || value.indexOf('*/') === 0) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
/**
|
|
7
|
+
* call must be scoped to the webdriverio client
|
|
8
|
+
*
|
|
9
|
+
* @param {String} element Opaque ID assigned to the element to move to, as described in the WebElement JSON Object.
|
|
10
|
+
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
11
|
+
* @param {Number} yoffset Y offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
12
|
+
* @uses protocol/elementIdLocation, protocol/elementIdSize
|
|
13
|
+
*/
|
|
14
|
+
var findMoveToCoordinates = function findMoveToCoordinates(element, xoffset, yoffset) {
|
|
15
|
+
var _this = this;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* check for offset params
|
|
19
|
+
*/
|
|
20
|
+
xoffset = typeof xoffset === 'number' ? xoffset : 0;
|
|
21
|
+
yoffset = typeof yoffset === 'number' ? yoffset : 0;
|
|
22
|
+
|
|
23
|
+
return this.elementIdSize(element).then(function (size) {
|
|
24
|
+
return _this.elementIdLocation(element).then(function (location) {
|
|
25
|
+
var x = location.value.x + size.value.width / 2;
|
|
26
|
+
var y = location.value.y + size.value.height / 2;
|
|
27
|
+
|
|
28
|
+
if (xoffset > 0 || yoffset > 0) {
|
|
29
|
+
x = location.value.x + xoffset;
|
|
30
|
+
y = location.value.y + yoffset;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
x: Math.round(x),
|
|
35
|
+
y: Math.round(y)
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.default = findMoveToCoordinates;
|
|
42
|
+
module.exports = exports['default'];
|
|
@@ -3,20 +3,53 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
|
|
7
|
+
var _utilities = require('../helpers/utilities');
|
|
8
|
+
|
|
6
9
|
var BUTTON_ENUM = {
|
|
7
10
|
left: 0,
|
|
8
11
|
middle: 1,
|
|
9
12
|
right: 2
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
var REQUEST_PATH_ENUM = {
|
|
16
|
+
down: '/session/:sessionId/buttondown',
|
|
17
|
+
press: '/session/:sessionId/click',
|
|
18
|
+
up: '/session/:sessionId/buttonup'
|
|
10
19
|
|
|
11
20
|
/**
|
|
12
21
|
* call must be scoped to the webdriverio client
|
|
13
22
|
*/
|
|
14
23
|
};var handleMouseButtonProtocol = function handleMouseButtonProtocol(requestPath, button) {
|
|
24
|
+
var _this = this;
|
|
25
|
+
|
|
15
26
|
if (typeof button !== 'number') {
|
|
16
27
|
button = BUTTON_ENUM[button || 'left'];
|
|
17
28
|
}
|
|
18
29
|
|
|
19
|
-
return this.requestHandler.create(requestPath, { button: button })
|
|
30
|
+
return this.requestHandler.create(requestPath, { button: button }).catch(function (err) {
|
|
31
|
+
/**
|
|
32
|
+
* jsonwire command not supported try webdriver endpoint
|
|
33
|
+
*/
|
|
34
|
+
if ((0, _utilities.isUnknownCommand)(err)) {
|
|
35
|
+
var actions = [{ type: 'pointerDown', button: button }, { type: 'pointerUp', button: button }];
|
|
36
|
+
|
|
37
|
+
if (requestPath === REQUEST_PATH_ENUM['down']) {
|
|
38
|
+
actions = [{ type: 'pointerDown', button: button }];
|
|
39
|
+
} else if (requestPath === REQUEST_PATH_ENUM['up']) {
|
|
40
|
+
actions = [{ type: 'pointerUp', button: button }];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return _this.actions([{
|
|
44
|
+
type: 'pointer',
|
|
45
|
+
id: 'mouse',
|
|
46
|
+
parameters: { pointerType: 'mouse' },
|
|
47
|
+
actions
|
|
48
|
+
}]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return err;
|
|
52
|
+
});
|
|
20
53
|
};
|
|
21
54
|
|
|
22
55
|
exports.default = handleMouseButtonProtocol;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isSuccessfulResponse = isSuccessfulResponse;
|
|
7
7
|
exports.isUnknownCommand = isUnknownCommand;
|
|
8
|
+
exports.isUnknownError = isUnknownError;
|
|
8
9
|
exports.formatHostname = formatHostname;
|
|
9
10
|
|
|
10
11
|
var _net = require('net');
|
|
@@ -70,7 +71,7 @@ function isUnknownCommand(err) {
|
|
|
70
71
|
/**
|
|
71
72
|
* when running browser driver directly
|
|
72
73
|
*/
|
|
73
|
-
if (err.message.match(/Invalid Command Method/) || err.message.match(/did not match a known command/) || err.message.match(/unknown command/) || err.message.match(/Driver info: driver\.version: unknown/) || err.message.match(/Method has not yet been implemented/) || err.message.match(/did not map to a valid resource/)) {
|
|
74
|
+
if (err.message.match(/Command not found/) || err.message.match(/Invalid Command Method/) || err.message.match(/did not match a known command/) || err.message.match(/unknown command/) || err.message.match(/Driver info: driver\.version: unknown/) || err.message.match(/Method has not yet been implemented/) || err.message.match(/did not map to a valid resource/)) {
|
|
74
75
|
return true;
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -84,6 +85,24 @@ function isUnknownCommand(err) {
|
|
|
84
85
|
return false;
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Checks if the error message is an unknown error
|
|
90
|
+
* https://w3c.github.io/webdriver/#dfn-unknown-error
|
|
91
|
+
* @param {Error} err
|
|
92
|
+
* @return {Boolean} Whether the error message is an "Unknown Error"
|
|
93
|
+
*/
|
|
94
|
+
function isUnknownError(err) {
|
|
95
|
+
if (!err || typeof err !== 'object') {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (err.message.match(/Unknown error/i)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
87
106
|
/**
|
|
88
107
|
* Prepare the hostname to properly use IPv6 address
|
|
89
108
|
* @param {string} hostname
|
|
@@ -25,6 +25,12 @@ exports.config = {
|
|
|
25
25
|
//
|
|
26
26
|
user: process.env.<%= answers.env_user %>,
|
|
27
27
|
key: process.env.<%= answers.env_key %>,
|
|
28
|
+
//
|
|
29
|
+
// If you run your tests on SauceLabs you can specify the region you want to run your tests
|
|
30
|
+
// in via the `region` property. You can either provide the full region name or the short handle:
|
|
31
|
+
// us: us-west-1 (default)
|
|
32
|
+
// eu: eu-central-1
|
|
33
|
+
// region: 'eu', // for eu-central-1
|
|
28
34
|
<% }
|
|
29
35
|
if(answers.backend.indexOf('In the cloud') > -1) { %>
|
|
30
36
|
<% } %>
|
|
@@ -73,8 +73,11 @@ function execute() {
|
|
|
73
73
|
return this.requestHandler.create('/session/:sessionId/execute', { script, args }).catch(function (err) {
|
|
74
74
|
/**
|
|
75
75
|
* jsonwire command not supported try webdriver endpoint
|
|
76
|
+
* Note: MicrosoftWebDriver returns "UnknownError" when receiving
|
|
77
|
+
* a jsonwire command in W3C Mode
|
|
78
|
+
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19917561/
|
|
76
79
|
*/
|
|
77
|
-
if ((0, _utilities.isUnknownCommand)(err)) {
|
|
80
|
+
if ((0, _utilities.isUnknownCommand)(err) || (0, _utilities.isUnknownError)(err)) {
|
|
78
81
|
return _this.requestHandler.create('/session/:sessionId/execute/sync', { script, args });
|
|
79
82
|
}
|
|
80
83
|
|
|
@@ -12,6 +12,8 @@ exports.default = moveTo;
|
|
|
12
12
|
|
|
13
13
|
var _ErrorHandler = require('../utils/ErrorHandler');
|
|
14
14
|
|
|
15
|
+
var _utilities = require('../helpers/utilities');
|
|
16
|
+
|
|
15
17
|
var _eventSimulator = require('../scripts/eventSimulator');
|
|
16
18
|
|
|
17
19
|
var _eventSimulator2 = _interopRequireDefault(_eventSimulator);
|
|
@@ -20,9 +22,15 @@ var _deprecationWarning = require('../helpers/deprecationWarning');
|
|
|
20
22
|
|
|
21
23
|
var _deprecationWarning2 = _interopRequireDefault(_deprecationWarning);
|
|
22
24
|
|
|
25
|
+
var _findMoveToCoordinates = require('../helpers/findMoveToCoordinates');
|
|
26
|
+
|
|
27
|
+
var _findMoveToCoordinates2 = _interopRequireDefault(_findMoveToCoordinates);
|
|
28
|
+
|
|
23
29
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
30
|
|
|
25
31
|
function moveTo(element, xoffset, yoffset) {
|
|
32
|
+
var _this = this;
|
|
33
|
+
|
|
26
34
|
var data = {};
|
|
27
35
|
|
|
28
36
|
if (typeof element === 'string') {
|
|
@@ -37,6 +45,12 @@ function moveTo(element, xoffset, yoffset) {
|
|
|
37
45
|
data.yoffset = yoffset;
|
|
38
46
|
}
|
|
39
47
|
|
|
48
|
+
if (this.isMobile) {
|
|
49
|
+
return _findMoveToCoordinates2.default.call(this, element, xoffset, yoffset).then(function (coordinates) {
|
|
50
|
+
return _this.touchMove(coordinates.x, coordinates.y);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
40
54
|
/**
|
|
41
55
|
* if no attribute is set, throw error
|
|
42
56
|
*/
|
|
@@ -61,7 +75,27 @@ function moveTo(element, xoffset, yoffset) {
|
|
|
61
75
|
}, { ELEMENT: element }, target.x, target.y);
|
|
62
76
|
}
|
|
63
77
|
|
|
64
|
-
return this.requestHandler.create('/session/:sessionId/moveto', data)
|
|
78
|
+
return this.requestHandler.create('/session/:sessionId/moveto', data).catch(function (err) {
|
|
79
|
+
/**
|
|
80
|
+
* jsonwire command not supported try w3c protocol endpoint
|
|
81
|
+
*/
|
|
82
|
+
if ((0, _utilities.isUnknownCommand)(err)) {
|
|
83
|
+
return _findMoveToCoordinates2.default.call(_this, element, xoffset, yoffset).then(function (coordinates) {
|
|
84
|
+
return _this.actions([{
|
|
85
|
+
type: 'pointer',
|
|
86
|
+
id: 'mouse',
|
|
87
|
+
actions: [{
|
|
88
|
+
type: 'pointerMove',
|
|
89
|
+
duration: 0,
|
|
90
|
+
x: coordinates.x,
|
|
91
|
+
y: coordinates.y
|
|
92
|
+
}]
|
|
93
|
+
}]);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
throw err;
|
|
98
|
+
});
|
|
65
99
|
} /**
|
|
66
100
|
*
|
|
67
101
|
* Move the mouse by an offset of the specified element. If no element is specified,
|
|
@@ -265,7 +265,22 @@ var BaseReporter = function (_events$EventEmitter) {
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
/**
|
|
268
|
-
*
|
|
268
|
+
* Output the given passes as a list
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
}, {
|
|
272
|
+
key: 'listPasses',
|
|
273
|
+
value: function listPasses() {
|
|
274
|
+
console.log();
|
|
275
|
+
this.stats.getPasses().forEach(function (test, i) {
|
|
276
|
+
var fmt = this.color('green', '%s) %s:\n') + this.color('green', '%s') + this.color('bright yellow', '%s');
|
|
277
|
+
var title = typeof test.fullTitle !== 'undefined' ? test.fullTitle : typeof test.parent !== 'undefined' ? test.parent + ' ' + test.title : test.title;
|
|
278
|
+
console.log(fmt, i + 1, title, test.nonerr.message, test.runningBrowser);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Output the given failures as a list
|
|
269
284
|
*/
|
|
270
285
|
|
|
271
286
|
}, {
|
|
@@ -24,21 +24,21 @@ var _createClass2 = require('babel-runtime/helpers/createClass');
|
|
|
24
24
|
|
|
25
25
|
var _createClass3 = _interopRequireDefault(_createClass2);
|
|
26
26
|
|
|
27
|
-
var
|
|
27
|
+
var _deepmerge = require('deepmerge');
|
|
28
28
|
|
|
29
|
-
var
|
|
29
|
+
var _deepmerge2 = _interopRequireDefault(_deepmerge);
|
|
30
30
|
|
|
31
|
-
var
|
|
31
|
+
var _fs = require('fs');
|
|
32
32
|
|
|
33
|
-
var
|
|
33
|
+
var _fs2 = _interopRequireDefault(_fs);
|
|
34
34
|
|
|
35
35
|
var _glob = require('glob');
|
|
36
36
|
|
|
37
37
|
var _glob2 = _interopRequireDefault(_glob);
|
|
38
38
|
|
|
39
|
-
var
|
|
39
|
+
var _path = require('path');
|
|
40
40
|
|
|
41
|
-
var
|
|
41
|
+
var _path2 = _interopRequireDefault(_path);
|
|
42
42
|
|
|
43
43
|
var _detectSeleniumBackend = require('../helpers/detectSeleniumBackend');
|
|
44
44
|
|
|
@@ -114,6 +114,8 @@ var DEFAULT_CONFIGS = {
|
|
|
114
114
|
};
|
|
115
115
|
var FILE_EXTENSIONS = ['.js', '.ts', '.feature', '.coffee', '.es6'];
|
|
116
116
|
|
|
117
|
+
var FEATURE_FILE_SPEC_REGEX = /^(.+\.feature):[0-9]+$/;
|
|
118
|
+
|
|
117
119
|
var ConfigParser = function () {
|
|
118
120
|
function ConfigParser() {
|
|
119
121
|
(0, _classCallCheck3.default)(this, ConfigParser);
|
|
@@ -420,7 +422,18 @@ var ConfigParser = function () {
|
|
|
420
422
|
var filePathList = ConfigParser.getFilePaths(config);
|
|
421
423
|
|
|
422
424
|
var _loop = function _loop(file) {
|
|
423
|
-
|
|
425
|
+
var match = file.match(FEATURE_FILE_SPEC_REGEX);
|
|
426
|
+
var filename = void 0;
|
|
427
|
+
/*
|
|
428
|
+
* check whether a file is a feature file specifying a scenario by its line number
|
|
429
|
+
* if this is the case extract filename part
|
|
430
|
+
*/
|
|
431
|
+
if (match) {
|
|
432
|
+
filename = match[1];
|
|
433
|
+
} else {
|
|
434
|
+
filename = file;
|
|
435
|
+
}
|
|
436
|
+
if (_fs2.default.existsSync(filename) && _fs2.default.lstatSync(filename).isFile()) {
|
|
424
437
|
filesToFilter.add(_path2.default.resolve(process.cwd(), file));
|
|
425
438
|
return 'continue';
|
|
426
439
|
}
|
|
@@ -495,18 +508,27 @@ var ConfigParser = function () {
|
|
|
495
508
|
for (var _iterator6 = (0, _getIterator3.default)(patterns), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
|
|
496
509
|
var pattern = _step6.value;
|
|
497
510
|
|
|
498
|
-
var filenames =
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
511
|
+
var filenames = void 0;
|
|
512
|
+
/*
|
|
513
|
+
* check whether a pattern is a feature file specifying a scenario by its line number
|
|
514
|
+
* if this is the case don't glob the pattern
|
|
515
|
+
*/
|
|
516
|
+
if (pattern.match(FEATURE_FILE_SPEC_REGEX)) {
|
|
517
|
+
filenames = [_path2.default.isAbsolute(pattern) ? _path2.default.normalize(pattern) : _path2.default.resolve(process.cwd(), pattern)];
|
|
518
|
+
} else {
|
|
519
|
+
filenames = _glob2.default.sync(pattern);
|
|
520
|
+
|
|
521
|
+
filenames = filenames.filter(function (filename) {
|
|
522
|
+
return FILE_EXTENSIONS.indexOf(_path2.default.extname(filename)) !== -1;
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
filenames = filenames.map(function (filename) {
|
|
526
|
+
return _path2.default.isAbsolute(filename) ? _path2.default.normalize(filename) : _path2.default.resolve(process.cwd(), filename);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
if (filenames.length === 0 && !omitWarnings) {
|
|
530
|
+
console.warn('pattern', pattern, 'did not match any file');
|
|
531
|
+
}
|
|
510
532
|
}
|
|
511
533
|
|
|
512
534
|
files = (0, _deepmerge2.default)(files, filenames, MERGE_OPTIONS);
|
|
@@ -195,12 +195,18 @@ var ReporterStats = function (_RunnableStats6) {
|
|
|
195
195
|
failures: 0
|
|
196
196
|
};
|
|
197
197
|
this.failures = [];
|
|
198
|
+
this.passes = [];
|
|
198
199
|
}
|
|
199
200
|
}, {
|
|
200
201
|
key: 'getCounts',
|
|
201
202
|
value: function getCounts() {
|
|
202
203
|
return this.counts;
|
|
203
204
|
}
|
|
205
|
+
}, {
|
|
206
|
+
key: 'getPasses',
|
|
207
|
+
value: function getPasses() {
|
|
208
|
+
return this.passes;
|
|
209
|
+
}
|
|
204
210
|
}, {
|
|
205
211
|
key: 'getFailures',
|
|
206
212
|
value: function getFailures() {
|
|
@@ -414,6 +420,7 @@ var ReporterStats = function (_RunnableStats6) {
|
|
|
414
420
|
value: function testPass(runner) {
|
|
415
421
|
this.getTestStats(runner).state = 'pass';
|
|
416
422
|
this.counts.passes++;
|
|
423
|
+
this.passes.push(runner);
|
|
417
424
|
}
|
|
418
425
|
}, {
|
|
419
426
|
key: 'testPending',
|
|
@@ -126,6 +126,8 @@ var RequestHandler = function () {
|
|
|
126
126
|
newOptions.qs = this.defaultOptions.queryParams;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
this.defaultOptions.protocol = this.defaultOptions.protocol || 'http';
|
|
130
|
+
|
|
129
131
|
newOptions.uri = _url2.default.parse(this.defaultOptions.protocol + '://' + (0, _utilities.formatHostname)(this.defaultOptions.hostname) + ':' + this.defaultOptions.port + (requestOptions.gridCommand ? this.gridApiStartPath : this.startPath) + requestOptions.path.replace(':sessionId', this.sessionID || ''));
|
|
130
132
|
|
|
131
133
|
// send authentication credentials only when creating new session
|
|
@@ -277,7 +279,7 @@ var RequestHandler = function () {
|
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
if (fullRequestOptions.gridCommand) {
|
|
280
|
-
if (body.success) {
|
|
282
|
+
if (body && body.success) {
|
|
281
283
|
return resolve({ body, response });
|
|
282
284
|
}
|
|
283
285
|
|
|
@@ -316,6 +318,16 @@ var RequestHandler = function () {
|
|
|
316
318
|
return reject(new _ErrorHandler.RuntimeError(error));
|
|
317
319
|
}
|
|
318
320
|
|
|
321
|
+
// IEServer webdriver bug where the error is put into the Allow header
|
|
322
|
+
// https://github.com/SeleniumHQ/selenium/issues/6828
|
|
323
|
+
if (response && response.statusCode === 405) {
|
|
324
|
+
var allowHeader = response.headers && response.headers.allow;
|
|
325
|
+
var _err = new _ErrorHandler.RuntimeError(allowHeader);
|
|
326
|
+
if ((0, _utilities.isUnknownCommand)(_err)) {
|
|
327
|
+
return reject(_err);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
319
331
|
if (retryCount >= totalRetryCount) {
|
|
320
332
|
var message = 'Couldn\'t connect to selenium server';
|
|
321
333
|
var status = -1;
|
package/build/lib/webdriverio.js
CHANGED
|
@@ -113,7 +113,6 @@ var WebdriverIO = function WebdriverIO(args, modifier) {
|
|
|
113
113
|
* merge default options with given user options
|
|
114
114
|
*/
|
|
115
115
|
var options = (0, _deepmerge2.default)({
|
|
116
|
-
protocol: 'http',
|
|
117
116
|
waitforTimeout: 1000,
|
|
118
117
|
waitforInterval: 500,
|
|
119
118
|
coloredLogs: true,
|
package/build/package.json
CHANGED
|
@@ -136,3 +136,29 @@ Boilerplate repo for quick set up of WebdriverIO test scripts with TravisCI, Sau
|
|
|
136
136
|
- Local notifications
|
|
137
137
|
- ESLint using Semistandard style
|
|
138
138
|
- WebdriverIO tuned Gitignore file
|
|
139
|
+
|
|
140
|
+
## [webdriverio/appium-boilerplate](https://github.com/webdriverio/appium-boilerplate/)
|
|
141
|
+
|
|
142
|
+
Boilerplate project to run Appium tests together with WebdriverIO for:
|
|
143
|
+
|
|
144
|
+
- iOS/Android Native Apps
|
|
145
|
+
- iOS/Android Hybrid Apps
|
|
146
|
+
- Android Chrome and iOS Safari browser
|
|
147
|
+
|
|
148
|
+
The boilerplate holds the following things
|
|
149
|
+
- Framework: Jasmine
|
|
150
|
+
- Features:
|
|
151
|
+
- Configs for:
|
|
152
|
+
- iOS and Android app
|
|
153
|
+
- iOS and Android browsers
|
|
154
|
+
- Helpers for:
|
|
155
|
+
- WebView
|
|
156
|
+
- Gestures
|
|
157
|
+
- Native alerts
|
|
158
|
+
- Pickers
|
|
159
|
+
- Tests examples for:
|
|
160
|
+
- WebView
|
|
161
|
+
- Login
|
|
162
|
+
- Forms
|
|
163
|
+
- Swipe
|
|
164
|
+
- Browsers
|
|
@@ -37,6 +37,12 @@ exports.config = {
|
|
|
37
37
|
user: 'webdriverio',
|
|
38
38
|
key: 'xxxxxxxxxxxxxxxx-xxxxxx-xxxxx-xxxxxxxxx',
|
|
39
39
|
//
|
|
40
|
+
// If you run your tests on SauceLabs you can specify the region you want to run your tests
|
|
41
|
+
// in via the `region` property. You can either provide the full region name or the short handle:
|
|
42
|
+
// us: us-west-1 (default)
|
|
43
|
+
// eu: eu-central-1
|
|
44
|
+
region: 'eu', // for eu-central-1
|
|
45
|
+
//
|
|
40
46
|
// ==================
|
|
41
47
|
// Specify Test Files
|
|
42
48
|
// ==================
|
|
@@ -82,8 +88,8 @@ exports.config = {
|
|
|
82
88
|
chromeOptions: {
|
|
83
89
|
// to run chrome headless the following flags are required
|
|
84
90
|
// (see https://developers.google.com/web/updates/2017/04/headless-chrome)
|
|
85
|
-
// args: ['--headless', '--disable-gpu'],
|
|
86
|
-
}
|
|
91
|
+
// args: ['--headless', '--disable-gpu'],
|
|
92
|
+
}
|
|
87
93
|
}, {
|
|
88
94
|
// maxInstances can get overwritten per capability. So if you have an in house Selenium
|
|
89
95
|
// grid with only 5 firefox instance available you can make sure that not more than
|
|
@@ -142,9 +148,9 @@ exports.config = {
|
|
|
142
148
|
// Saves a screenshot to a given path if a command fails.
|
|
143
149
|
screenshotPath: 'shots',
|
|
144
150
|
//
|
|
145
|
-
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
|
|
146
|
-
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
|
|
147
|
-
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
|
|
151
|
+
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
|
|
152
|
+
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
|
|
153
|
+
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
|
|
148
154
|
// gets prepended directly.
|
|
149
155
|
baseUrl: 'http://localhost:8080',
|
|
150
156
|
//
|
|
@@ -257,7 +263,7 @@ exports.config = {
|
|
|
257
263
|
* @param {Array.<String>} specs List of spec file paths that are to be run
|
|
258
264
|
*/
|
|
259
265
|
beforeSession: function (config, capabilities, specs) {
|
|
260
|
-
},
|
|
266
|
+
},
|
|
261
267
|
/**
|
|
262
268
|
* Gets executed before test execution begins. At this point you can access to all global
|
|
263
269
|
* variables like `browser`. It is the perfect place to define custom commands.
|
|
@@ -111,6 +111,12 @@ or run multiple specs at once:
|
|
|
111
111
|
$ wdio wdio.conf.js --spec ./test/specs/signup.js,./test/specs/forgot-password.js
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
In case of a feature (Cucumber) you can specify a single scenario by adding a line number:
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
$ wdio wdio.conf.js --spec ./test/specs/login.feature:6
|
|
118
|
+
```
|
|
119
|
+
|
|
114
120
|
If the spec passed in is not a path to a spec file, it is used as a filter for the spec file names defined in your configuration file. To run all specs with the word 'dialog' in the spec file names, you could use:
|
|
115
121
|
|
|
116
122
|
```sh
|
|
@@ -43,7 +43,7 @@ let getCookie = function (name) {
|
|
|
43
43
|
res.value = res.value || []
|
|
44
44
|
|
|
45
45
|
if (typeof name === 'string') {
|
|
46
|
-
return res.value.filter((cookie) => cookie.name === name)[0] || null
|
|
46
|
+
return res.value.filter((cookie) => cookie.name === encodeURIComponent(encodeURIComponent(name)))[0] || null
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
return res.value || (typeof name === 'string' ? null : [])
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Apply left click on an element. If selector is not provided, click on the last
|
|
4
4
|
* moved-to location.
|
|
5
5
|
*
|
|
6
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
7
|
+
*
|
|
6
8
|
* @alias browser.leftClick
|
|
7
9
|
* @param {String} selector element to click on
|
|
8
10
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Apply middle click on an element. If selector is not provided, click on the last
|
|
4
4
|
* moved-to location.
|
|
5
5
|
*
|
|
6
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
7
|
+
*
|
|
6
8
|
* @alias browser.middleClick
|
|
7
9
|
* @param {String} selector element to click on
|
|
8
10
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -4,53 +4,20 @@
|
|
|
4
4
|
* offset, the mouse will be moved to the center of the element. If the element is not
|
|
5
5
|
* visible, it will be scrolled into view.
|
|
6
6
|
*
|
|
7
|
+
* Uses JSONWireframe moveTo protocol with W3C actions protocol fallback.
|
|
8
|
+
* Uses touchMove protocol for mobile.
|
|
9
|
+
*
|
|
7
10
|
* @alias browser.moveToObject
|
|
8
11
|
* @param {String} selector element to move to
|
|
9
12
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
10
13
|
* @param {Number} yoffset Y offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element.
|
|
11
|
-
* @uses protocol/element, protocol/elementIdLocation
|
|
14
|
+
* @uses protocol/element, protocol/elementIdLocation, protocol/elementIdSize
|
|
12
15
|
* @type action
|
|
13
16
|
*
|
|
14
17
|
*/
|
|
15
|
-
|
|
16
18
|
import { RuntimeError } from '../utils/ErrorHandler'
|
|
17
19
|
|
|
18
20
|
let moveToObject = function (selector, xoffset, yoffset) {
|
|
19
|
-
/**
|
|
20
|
-
* check for offset params
|
|
21
|
-
*/
|
|
22
|
-
var hasOffsetParams = true
|
|
23
|
-
if (typeof xoffset !== 'number' && typeof yoffset !== 'number') {
|
|
24
|
-
hasOffsetParams = false
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (this.isMobile) {
|
|
28
|
-
return this.element(selector).then((res) => {
|
|
29
|
-
/**
|
|
30
|
-
* check if element was found and throw error if not
|
|
31
|
-
*/
|
|
32
|
-
if (!res.value) {
|
|
33
|
-
throw new RuntimeError(7)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return this.elementIdSize(res.value.ELEMENT).then((size) =>
|
|
37
|
-
this.elementIdLocation(res.value.ELEMENT).then((location) => {
|
|
38
|
-
return { size, location }
|
|
39
|
-
})
|
|
40
|
-
)
|
|
41
|
-
}).then((res) => {
|
|
42
|
-
let x = res.location.value.x + (res.size.value.width / 2)
|
|
43
|
-
let y = res.location.value.y + (res.size.value.height / 2)
|
|
44
|
-
|
|
45
|
-
if (hasOffsetParams) {
|
|
46
|
-
x = res.location.value.x + xoffset
|
|
47
|
-
y = res.location.value.y + yoffset
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return this.touchMove(x, y)
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
21
|
return this.element(selector).then((res) => {
|
|
55
22
|
/**
|
|
56
23
|
* check if element was found and throw error if not
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Apply right click on an element. If selector is not provided, click on the last
|
|
4
4
|
* moved-to location.
|
|
5
5
|
*
|
|
6
|
+
* Uses JSONWireframe buttonPress protocol with W3C actions protocol as fallback.
|
|
7
|
+
*
|
|
6
8
|
* @alias browser.rightClick
|
|
7
9
|
* @param {String} selector element to click on
|
|
8
10
|
* @param {Number} xoffset X offset to move to, relative to the top-left corner of the element.
|
|
@@ -32,14 +32,22 @@
|
|
|
32
32
|
import { CommandError } from '../utils/ErrorHandler'
|
|
33
33
|
|
|
34
34
|
let setCookie = function (cookieObj) {
|
|
35
|
+
const { name } = cookieObj
|
|
35
36
|
/*!
|
|
36
37
|
* parameter check
|
|
37
38
|
*/
|
|
38
|
-
if (typeof cookieObj !== 'object') {
|
|
39
|
+
if (typeof cookieObj !== 'object' || !name || typeof name !== 'string') {
|
|
39
40
|
throw new CommandError('Please specify a cookie object to set (see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#cookie-json-object for documentation.')
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
return this.cookie(
|
|
43
|
+
return this.cookie(
|
|
44
|
+
'POST',
|
|
45
|
+
Object.assign(
|
|
46
|
+
{},
|
|
47
|
+
cookieObj,
|
|
48
|
+
{ name: encodeURIComponent(encodeURIComponent(name)) }
|
|
49
|
+
)
|
|
50
|
+
)
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
export default setCookie
|
package/lib/protocol/execute.js
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
import { ProtocolError } from '../utils/ErrorHandler'
|
|
39
|
-
import { isUnknownCommand } from '../helpers/utilities'
|
|
39
|
+
import { isUnknownCommand, isUnknownError } from '../helpers/utilities'
|
|
40
40
|
|
|
41
41
|
export default function execute (...args) {
|
|
42
42
|
let script = args.shift()
|
|
@@ -59,8 +59,11 @@ export default function execute (...args) {
|
|
|
59
59
|
return this.requestHandler.create('/session/:sessionId/execute', { script, args }).catch((err) => {
|
|
60
60
|
/**
|
|
61
61
|
* jsonwire command not supported try webdriver endpoint
|
|
62
|
+
* Note: MicrosoftWebDriver returns "UnknownError" when receiving
|
|
63
|
+
* a jsonwire command in W3C Mode
|
|
64
|
+
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19917561/
|
|
62
65
|
*/
|
|
63
|
-
if (isUnknownCommand(err)) {
|
|
66
|
+
if (isUnknownCommand(err) || isUnknownError(err)) {
|
|
64
67
|
return this.requestHandler.create('/session/:sessionId/execute/sync', { script, args })
|
|
65
68
|
}
|
|
66
69
|
|
package/lib/protocol/moveTo.js
CHANGED
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { ProtocolError } from '../utils/ErrorHandler'
|
|
22
|
+
import { isUnknownCommand } from '../helpers/utilities'
|
|
22
23
|
import eventSimulator from '../scripts/eventSimulator'
|
|
23
24
|
import deprecate from '../helpers/deprecationWarning'
|
|
25
|
+
import findMoveToCoordinates from '../helpers/findMoveToCoordinates'
|
|
24
26
|
|
|
25
27
|
export default function moveTo (element, xoffset, yoffset) {
|
|
26
28
|
let data = {}
|
|
@@ -37,6 +39,10 @@ export default function moveTo (element, xoffset, yoffset) {
|
|
|
37
39
|
data.yoffset = yoffset
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
if (this.isMobile) {
|
|
43
|
+
return findMoveToCoordinates.call(this, element, xoffset, yoffset).then(coordinates => this.touchMove(coordinates.x, coordinates.y))
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
/**
|
|
41
47
|
* if no attribute is set, throw error
|
|
42
48
|
*/
|
|
@@ -67,5 +73,25 @@ export default function moveTo (element, xoffset, yoffset) {
|
|
|
67
73
|
}, { ELEMENT: element }, target.x, target.y)
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
return this.requestHandler.create('/session/:sessionId/moveto', data)
|
|
76
|
+
return this.requestHandler.create('/session/:sessionId/moveto', data).catch(err => {
|
|
77
|
+
/**
|
|
78
|
+
* jsonwire command not supported try w3c protocol endpoint
|
|
79
|
+
*/
|
|
80
|
+
if (isUnknownCommand(err)) {
|
|
81
|
+
return findMoveToCoordinates.call(this, element, xoffset, yoffset).then((coordinates) => {
|
|
82
|
+
return this.actions([{
|
|
83
|
+
type: 'pointer',
|
|
84
|
+
id: 'mouse',
|
|
85
|
+
actions: [{
|
|
86
|
+
type: 'pointerMove',
|
|
87
|
+
duration: 0,
|
|
88
|
+
x: coordinates.x,
|
|
89
|
+
y: coordinates.y
|
|
90
|
+
}]
|
|
91
|
+
}])
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
throw err
|
|
96
|
+
})
|
|
71
97
|
}
|
package/package.json
CHANGED