webdriver 5.11.0 → 5.11.12
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/build/command.js +5 -30
- package/build/constants.js +0 -51
- package/build/index.js +16 -47
- package/build/monad.js +2 -70
- package/build/request.js +2 -43
- package/build/utils.js +11 -176
- package/package.json +2 -2
- package/protocol/saucelabs.json +24 -1
- package/webdriver.d.ts +4 -1
package/build/command.js
CHANGED
|
@@ -23,62 +23,37 @@ function _default(method, endpointUri, commandInfo) {
|
|
|
23
23
|
variables = [],
|
|
24
24
|
isHubCommand = false
|
|
25
25
|
} = commandInfo;
|
|
26
|
-
return function (...args) {
|
|
27
|
-
let endpoint = endpointUri;
|
|
28
|
-
|
|
26
|
+
return function protocolCommand(...args) {
|
|
27
|
+
let endpoint = endpointUri;
|
|
29
28
|
const commandParams = [...variables.map(v => Object.assign(v, {
|
|
30
|
-
/**
|
|
31
|
-
* url variables are:
|
|
32
|
-
*/
|
|
33
29
|
required: true,
|
|
34
|
-
|
|
35
|
-
type: 'string' // have to be always type of string
|
|
36
|
-
|
|
30
|
+
type: 'string'
|
|
37
31
|
})), ...parameters];
|
|
38
32
|
const commandUsage = `${command}(${commandParams.map(p => p.name).join(', ')})`;
|
|
39
33
|
const moreInfo = `\n\nFor more info see ${ref}\n`;
|
|
40
34
|
const body = {};
|
|
41
|
-
/**
|
|
42
|
-
* parameter check
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
35
|
const minAllowedParams = commandParams.filter(param => param.required).length;
|
|
46
36
|
|
|
47
37
|
if (args.length < minAllowedParams || args.length > commandParams.length) {
|
|
48
38
|
const parameterDescription = commandParams.length ? `\n\nProperty Description:\n${commandParams.map(p => ` "${p.name}" (${p.type}): ${p.description}`).join('\n')}` : '';
|
|
49
39
|
throw new Error(`Wrong parameters applied for ${command}\n` + `Usage: ${commandUsage}` + parameterDescription + moreInfo);
|
|
50
40
|
}
|
|
51
|
-
/**
|
|
52
|
-
* parameter type check
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
41
|
|
|
56
42
|
for (const [i, arg] of Object.entries(args)) {
|
|
57
43
|
const commandParam = commandParams[i];
|
|
58
44
|
|
|
59
45
|
if (!(0, _utils.isValidParameter)(arg, commandParam.type)) {
|
|
60
|
-
/**
|
|
61
|
-
* ignore if argument is not required
|
|
62
|
-
*/
|
|
63
46
|
if (typeof arg === 'undefined' && !commandParam.required) {
|
|
64
47
|
continue;
|
|
65
48
|
}
|
|
66
49
|
|
|
67
50
|
throw new Error(`Malformed type for "${commandParam.name}" parameter of command ${command}\n` + `Expected: ${commandParam.type}\n` + `Actual: ${(0, _utils.getArgumentType)(arg)}` + moreInfo);
|
|
68
51
|
}
|
|
69
|
-
/**
|
|
70
|
-
* inject url variables
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
52
|
|
|
74
53
|
if (i < variables.length) {
|
|
75
|
-
endpoint = endpoint.replace(`:${commandParams[i].name}`, arg);
|
|
54
|
+
endpoint = endpoint.replace(`:${commandParams[i].name}`, encodeURIComponent(encodeURIComponent(arg)));
|
|
76
55
|
continue;
|
|
77
56
|
}
|
|
78
|
-
/**
|
|
79
|
-
* rest of args are part of body payload
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
57
|
|
|
83
58
|
body[commandParams[i].name] = arg;
|
|
84
59
|
}
|
|
@@ -92,7 +67,7 @@ function _default(method, endpointUri, commandInfo) {
|
|
|
92
67
|
log.info('COMMAND', (0, _utils.commandCallStructure)(command, args));
|
|
93
68
|
return request.makeRequest(this.options, this.sessionId).then(result => {
|
|
94
69
|
if (result.value != null) {
|
|
95
|
-
log.info('RESULT',
|
|
70
|
+
log.info('RESULT', /screenshot|recording/i.test(command) && typeof result.value === 'string' && result.value.length > 64 ? `${result.value.substr(0, 61)}...` : result.value);
|
|
96
71
|
}
|
|
97
72
|
|
|
98
73
|
this.emit('result', {
|
package/build/constants.js
CHANGED
|
@@ -5,103 +5,52 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.DEFAULTS = void 0;
|
|
7
7
|
const DEFAULTS = {
|
|
8
|
-
/**
|
|
9
|
-
* protocol of automation driver
|
|
10
|
-
*/
|
|
11
8
|
protocol: {
|
|
12
9
|
type: 'string',
|
|
13
10
|
default: 'http',
|
|
14
11
|
match: /(http|https)/
|
|
15
12
|
},
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* hostname of automation driver
|
|
19
|
-
*/
|
|
20
13
|
hostname: {
|
|
21
14
|
type: 'string',
|
|
22
15
|
default: 'localhost'
|
|
23
16
|
},
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* port of automation driver
|
|
27
|
-
*/
|
|
28
17
|
port: {
|
|
29
18
|
type: 'number',
|
|
30
19
|
default: 4444
|
|
31
20
|
},
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* path to WebDriver endpoints
|
|
35
|
-
*/
|
|
36
21
|
path: {
|
|
37
22
|
type: 'string',
|
|
38
23
|
default: '/wd/hub'
|
|
39
24
|
},
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* A key-value store of query parameters to be added to every selenium request
|
|
43
|
-
*/
|
|
44
25
|
queryParams: {
|
|
45
26
|
type: 'object'
|
|
46
27
|
},
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* capability of WebDriver session
|
|
50
|
-
*/
|
|
51
28
|
capabilities: {
|
|
52
29
|
type: 'object',
|
|
53
30
|
required: true
|
|
54
31
|
},
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Level of logging verbosity
|
|
58
|
-
*/
|
|
59
32
|
logLevel: {
|
|
60
33
|
type: 'string',
|
|
61
34
|
default: 'info',
|
|
62
35
|
match: /(trace|debug|info|warn|error|silent)/
|
|
63
36
|
},
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Timeout for any request to the Selenium server
|
|
67
|
-
*/
|
|
68
37
|
connectionRetryTimeout: {
|
|
69
38
|
type: 'number',
|
|
70
39
|
default: 90000
|
|
71
40
|
},
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Count of request retries to the Selenium server
|
|
75
|
-
*/
|
|
76
41
|
connectionRetryCount: {
|
|
77
42
|
type: 'number',
|
|
78
43
|
default: 3
|
|
79
44
|
},
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* cloud user if applicable
|
|
83
|
-
*/
|
|
84
45
|
user: {
|
|
85
46
|
type: 'string'
|
|
86
47
|
},
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* access key to user
|
|
90
|
-
*/
|
|
91
48
|
key: {
|
|
92
49
|
type: 'string'
|
|
93
50
|
},
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Override default agent
|
|
97
|
-
*/
|
|
98
51
|
agent: {
|
|
99
52
|
type: 'object'
|
|
100
53
|
},
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Pass custom headers
|
|
104
|
-
*/
|
|
105
54
|
headers: {
|
|
106
55
|
type: 'object'
|
|
107
56
|
}
|
package/build/index.js
CHANGED
|
@@ -19,8 +19,6 @@ exports.default = void 0;
|
|
|
19
19
|
|
|
20
20
|
var _logger = _interopRequireDefault(require("@wdio/logger"));
|
|
21
21
|
|
|
22
|
-
var _lodash = _interopRequireDefault(require("lodash.merge"));
|
|
23
|
-
|
|
24
22
|
var _config = require("@wdio/config");
|
|
25
23
|
|
|
26
24
|
var _monad = _interopRequireDefault(require("./monad"));
|
|
@@ -43,6 +41,12 @@ var _chromium = _interopRequireDefault(require("../protocol/chromium.json"));
|
|
|
43
41
|
|
|
44
42
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
45
43
|
|
|
44
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
45
|
+
|
|
46
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
47
|
+
|
|
48
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
49
|
+
|
|
46
50
|
class WebDriver {
|
|
47
51
|
static async newSession(options = {}, modifier, userPrototype = {}, commandWrapper) {
|
|
48
52
|
const params = (0, _config.validateConfig)(_constants.DEFAULTS, options);
|
|
@@ -50,64 +54,35 @@ class WebDriver {
|
|
|
50
54
|
if (!options.logLevels || !options.logLevels['webdriver']) {
|
|
51
55
|
_logger.default.setLevel('webdriver', params.logLevel);
|
|
52
56
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* and we want to pass both styles to the server, which means we need
|
|
56
|
-
* to check what style the user sent in so we know how to construct the
|
|
57
|
-
* object for the other style
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const [w3cCaps, jsonwpCaps] = params.capabilities && params.capabilities.alwaysMatch
|
|
62
|
-
/**
|
|
63
|
-
* in case W3C compliant capabilities are provided
|
|
64
|
-
*/
|
|
65
|
-
? [params.capabilities, params.capabilities.alwaysMatch]
|
|
66
|
-
/**
|
|
67
|
-
* otherwise assume they passed in jsonwp-style caps (flat object)
|
|
68
|
-
*/
|
|
69
|
-
: [{
|
|
57
|
+
|
|
58
|
+
const [w3cCaps, jsonwpCaps] = params.capabilities && params.capabilities.alwaysMatch ? [params.capabilities, params.capabilities.alwaysMatch] : [{
|
|
70
59
|
alwaysMatch: params.capabilities,
|
|
71
60
|
firstMatch: [{}]
|
|
72
61
|
}, params.capabilities];
|
|
73
62
|
const sessionRequest = new _request.default('POST', '/session', {
|
|
74
63
|
capabilities: w3cCaps,
|
|
75
|
-
|
|
76
|
-
desiredCapabilities: jsonwpCaps // JSONWP compliant
|
|
77
|
-
|
|
64
|
+
desiredCapabilities: jsonwpCaps
|
|
78
65
|
});
|
|
79
66
|
const response = await sessionRequest.makeRequest(params);
|
|
80
|
-
/**
|
|
81
|
-
* save original set of capabilities to allow to request the same session again
|
|
82
|
-
* (e.g. for reloadSession command in WebdriverIO)
|
|
83
|
-
*/
|
|
84
|
-
|
|
85
67
|
params.requestedCapabilities = {
|
|
86
68
|
w3cCaps,
|
|
87
69
|
jsonwpCaps
|
|
88
|
-
/**
|
|
89
|
-
* save actual receveived session details
|
|
90
|
-
*/
|
|
91
|
-
|
|
92
70
|
};
|
|
93
71
|
params.capabilities = response.value.capabilities || response.value;
|
|
94
72
|
const environment = (0, _utils.environmentDetector)(params);
|
|
95
73
|
const environmentPrototype = (0, _utils.getEnvironmentVars)(environment);
|
|
96
74
|
const protocolCommands = (0, _utils.getPrototype)(environment);
|
|
97
|
-
|
|
75
|
+
|
|
76
|
+
const prototype = _objectSpread({}, protocolCommands, {}, environmentPrototype, {}, userPrototype);
|
|
77
|
+
|
|
98
78
|
const monad = (0, _monad.default)(params, modifier, prototype);
|
|
99
79
|
return monad(response.value.sessionId || response.sessionId, commandWrapper);
|
|
100
80
|
}
|
|
101
|
-
/**
|
|
102
|
-
* allows user to attach to existing sessions
|
|
103
|
-
*/
|
|
104
|
-
|
|
105
81
|
|
|
106
82
|
static attachToSession(options = {}, modifier, userPrototype = {}, commandWrapper) {
|
|
107
83
|
if (typeof options.sessionId !== 'string') {
|
|
108
84
|
throw new Error('sessionId is required to attach to existing session');
|
|
109
|
-
}
|
|
110
|
-
|
|
85
|
+
}
|
|
111
86
|
|
|
112
87
|
if (options.logLevel !== undefined) {
|
|
113
88
|
_logger.default.setLevel('webdriver', options.logLevel);
|
|
@@ -117,7 +92,9 @@ class WebDriver {
|
|
|
117
92
|
options.isW3C = options.isW3C === false ? false : true;
|
|
118
93
|
const environmentPrototype = (0, _utils.getEnvironmentVars)(options);
|
|
119
94
|
const protocolCommands = (0, _utils.getPrototype)(options);
|
|
120
|
-
|
|
95
|
+
|
|
96
|
+
const prototype = _objectSpread({}, protocolCommands, {}, environmentPrototype, {}, userPrototype);
|
|
97
|
+
|
|
121
98
|
const monad = (0, _monad.default)(options, modifier, prototype);
|
|
122
99
|
return monad(options.sessionId, commandWrapper);
|
|
123
100
|
}
|
|
@@ -129,10 +106,6 @@ class WebDriver {
|
|
|
129
106
|
static get DEFAULTS() {
|
|
130
107
|
return _constants.DEFAULTS;
|
|
131
108
|
}
|
|
132
|
-
/**
|
|
133
|
-
* Protocols
|
|
134
|
-
*/
|
|
135
|
-
|
|
136
109
|
|
|
137
110
|
static get WebDriverProtocol() {
|
|
138
111
|
return _webdriver.default;
|
|
@@ -155,9 +128,5 @@ class WebDriver {
|
|
|
155
128
|
}
|
|
156
129
|
|
|
157
130
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Helper methods consumed by webdriverio package
|
|
160
|
-
*/
|
|
161
|
-
|
|
162
131
|
|
|
163
132
|
exports.default = WebDriver;
|
package/build/monad.js
CHANGED
|
@@ -14,29 +14,17 @@ var _utils = require("./utils");
|
|
|
14
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
15
|
|
|
16
16
|
const SCOPE_TYPES = {
|
|
17
|
-
'browser':
|
|
18
|
-
|
|
19
|
-
function Browser() {},
|
|
20
|
-
'element':
|
|
21
|
-
/* istanbul ignore next */
|
|
22
|
-
function Element() {}
|
|
17
|
+
'browser': function Browser() {},
|
|
18
|
+
'element': function Element() {}
|
|
23
19
|
};
|
|
24
20
|
|
|
25
21
|
function WebDriver(options, modifier, propertiesObject = {}) {
|
|
26
|
-
/**
|
|
27
|
-
* In order to allow named scopes for elements we have to propagate that
|
|
28
|
-
* info within the `propertiesObject` object. This doesn't have any functional
|
|
29
|
-
* advantages just provides better description of objects when debugging them
|
|
30
|
-
*/
|
|
31
22
|
const scopeType = SCOPE_TYPES[propertiesObject.scope] || SCOPE_TYPES['browser'];
|
|
32
23
|
delete propertiesObject.scope;
|
|
33
24
|
const prototype = Object.create(scopeType.prototype);
|
|
34
25
|
const log = (0, _logger.default)('webdriver');
|
|
35
26
|
const eventHandler = new _events.EventEmitter();
|
|
36
27
|
const EVENTHANDLER_FUNCTIONS = Object.getPrototypeOf(eventHandler);
|
|
37
|
-
/**
|
|
38
|
-
* WebDriver monad
|
|
39
|
-
*/
|
|
40
28
|
|
|
41
29
|
function unit(sessionId, commandWrapper) {
|
|
42
30
|
propertiesObject.commandList = {
|
|
@@ -44,11 +32,6 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
44
32
|
};
|
|
45
33
|
propertiesObject.options = {
|
|
46
34
|
value: options
|
|
47
|
-
/**
|
|
48
|
-
* allow to wrap commands if necessary
|
|
49
|
-
* e.g. in wdio-cli to make them synchronous
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
35
|
};
|
|
53
36
|
|
|
54
37
|
if (typeof commandWrapper === 'function') {
|
|
@@ -63,25 +46,14 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
63
46
|
propertiesObject[commandName].configurable = true;
|
|
64
47
|
}
|
|
65
48
|
}
|
|
66
|
-
/**
|
|
67
|
-
* overwrite native element commands with user defined
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
49
|
|
|
71
50
|
_utils.overwriteElementCommands.call(this, propertiesObject);
|
|
72
|
-
/**
|
|
73
|
-
* assign propertiesObject to itself so the client can be recreated
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
51
|
|
|
77
52
|
propertiesObject['__propertiesObject__'] = {
|
|
78
53
|
value: propertiesObject
|
|
79
54
|
};
|
|
80
55
|
let client = Object.create(prototype, propertiesObject);
|
|
81
56
|
client.sessionId = sessionId;
|
|
82
|
-
/**
|
|
83
|
-
* register capabilities only to browser scope
|
|
84
|
-
*/
|
|
85
57
|
|
|
86
58
|
if (scopeType.name === 'Browser') {
|
|
87
59
|
client.capabilities = options.capabilities;
|
|
@@ -95,9 +67,6 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
95
67
|
const customCommand = typeof commandWrapper === 'function' ? commandWrapper(name, func) : func;
|
|
96
68
|
|
|
97
69
|
if (attachToElement) {
|
|
98
|
-
/**
|
|
99
|
-
* add command to every multiremote instance
|
|
100
|
-
*/
|
|
101
70
|
if (instances) {
|
|
102
71
|
Object.values(instances).forEach(instance => {
|
|
103
72
|
instance.__propertiesObject__[name] = {
|
|
@@ -113,32 +82,16 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
113
82
|
unit.lift(name, customCommand, proto);
|
|
114
83
|
}
|
|
115
84
|
};
|
|
116
|
-
/**
|
|
117
|
-
* overwriteCommand
|
|
118
|
-
* @param {String} name command name to be overwritten
|
|
119
|
-
* @param {Function} func function to replace original command with;
|
|
120
|
-
* takes original function as first argument.
|
|
121
|
-
* @param {boolean=} attachToElement overwrite browser command (false) or element command (true)
|
|
122
|
-
* @param {Object=} proto prototype to add function to (optional)
|
|
123
|
-
* @param {Object=} instances multiremote instances
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
85
|
|
|
127
86
|
client.overwriteCommand = function (name, func, attachToElement = false, proto, instances) {
|
|
128
87
|
let customCommand = typeof commandWrapper === 'function' ? commandWrapper(name, func) : func;
|
|
129
88
|
|
|
130
89
|
if (attachToElement) {
|
|
131
90
|
if (instances) {
|
|
132
|
-
/**
|
|
133
|
-
* add command to every multiremote instance
|
|
134
|
-
*/
|
|
135
91
|
Object.values(instances).forEach(instance => {
|
|
136
92
|
instance.__propertiesObject__.__elementOverrides__.value[name] = customCommand;
|
|
137
93
|
});
|
|
138
94
|
} else {
|
|
139
|
-
/**
|
|
140
|
-
* regular mode
|
|
141
|
-
*/
|
|
142
95
|
this.__propertiesObject__.__elementOverrides__.value[name] = customCommand;
|
|
143
96
|
}
|
|
144
97
|
} else if (client[name]) {
|
|
@@ -152,32 +105,15 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
152
105
|
|
|
153
106
|
return client;
|
|
154
107
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Enhance monad prototype with function
|
|
157
|
-
* @param {String} name name of function to attach to prototype
|
|
158
|
-
* @param {Function} func function to be added to prototype
|
|
159
|
-
* @param {Object} proto prototype to add function to (optional)
|
|
160
|
-
* @param {Function} origCommand original command to be passed to custom command as first argument
|
|
161
|
-
*/
|
|
162
|
-
|
|
163
108
|
|
|
164
109
|
unit.lift = function (name, func, proto, origCommand) {
|
|
165
110
|
(proto || prototype)[name] = function next(...args) {
|
|
166
111
|
log.info('COMMAND', (0, _utils.commandCallStructure)(name, args));
|
|
167
|
-
/**
|
|
168
|
-
* set name of function for better error stack
|
|
169
|
-
*/
|
|
170
|
-
|
|
171
112
|
Object.defineProperty(func, 'name', {
|
|
172
113
|
value: name,
|
|
173
114
|
writable: false
|
|
174
115
|
});
|
|
175
116
|
const result = func.apply(this, origCommand ? [origCommand, ...args] : args);
|
|
176
|
-
/**
|
|
177
|
-
* always transform result into promise as we don't know whether or not
|
|
178
|
-
* the user is running tests with wdio-sync or not
|
|
179
|
-
*/
|
|
180
|
-
|
|
181
117
|
Promise.resolve(result).then(res => {
|
|
182
118
|
log.info('RESULT', res);
|
|
183
119
|
this.emit('result', {
|
|
@@ -188,10 +124,6 @@ function WebDriver(options, modifier, propertiesObject = {}) {
|
|
|
188
124
|
return result;
|
|
189
125
|
};
|
|
190
126
|
};
|
|
191
|
-
/**
|
|
192
|
-
* register event emitter
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
127
|
|
|
196
128
|
for (let eventCommand in EVENTHANDLER_FUNCTIONS) {
|
|
197
129
|
prototype[eventCommand] = function (...args) {
|
package/build/request.js
CHANGED
|
@@ -13,8 +13,6 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
13
13
|
|
|
14
14
|
var _https = _interopRequireDefault(require("https"));
|
|
15
15
|
|
|
16
|
-
var _lodash = _interopRequireDefault(require("lodash.merge"));
|
|
17
|
-
|
|
18
16
|
var _request = _interopRequireDefault(require("request"));
|
|
19
17
|
|
|
20
18
|
var _events = _interopRequireDefault(require("events"));
|
|
@@ -58,7 +56,7 @@ class WebDriverRequest extends _events.default {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
makeRequest(options, sessionId) {
|
|
61
|
-
const fullRequestOptions =
|
|
59
|
+
const fullRequestOptions = Object.assign({}, this.defaultOptions, this._createOptions(options, sessionId));
|
|
62
60
|
this.emit('request', fullRequestOptions);
|
|
63
61
|
return this._request(fullRequestOptions, options.connectionRetryCount);
|
|
64
62
|
}
|
|
@@ -68,33 +66,20 @@ class WebDriverRequest extends _events.default {
|
|
|
68
66
|
agent: options.agent || agents[options.protocol],
|
|
69
67
|
headers: typeof options.headers === 'object' ? options.headers : {},
|
|
70
68
|
qs: typeof options.queryParams === 'object' ? options.queryParams : {}
|
|
71
|
-
/**
|
|
72
|
-
* only apply body property if existing
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
69
|
};
|
|
76
70
|
|
|
77
71
|
if (this.body && (Object.keys(this.body).length || this.method === 'POST')) {
|
|
78
72
|
requestOptions.body = this.body;
|
|
79
|
-
requestOptions.headers =
|
|
73
|
+
requestOptions.headers = Object.assign({}, requestOptions.headers, {
|
|
80
74
|
'Content-Length': Buffer.byteLength(JSON.stringify(requestOptions.body), 'UTF-8')
|
|
81
75
|
});
|
|
82
76
|
}
|
|
83
|
-
/**
|
|
84
|
-
* if we don't have a session id we set it here, unless we call commands that don't require session ids, for
|
|
85
|
-
* example /sessions. The call to /sessions is not connected to a session itself and it therefore doesn't
|
|
86
|
-
* require it
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
77
|
|
|
90
78
|
if (this.requiresSessionId && !sessionId) {
|
|
91
79
|
throw new Error('A sessionId is required for this command');
|
|
92
80
|
}
|
|
93
81
|
|
|
94
82
|
requestOptions.uri = _url.default.parse(`${options.protocol}://` + `${options.hostname}:${options.port}` + (this.isHubCommand ? this.endpoint : _path.default.join(options.path, this.endpoint.replace(':sessionId', sessionId))));
|
|
95
|
-
/**
|
|
96
|
-
* send authentication credentials only when creating new session
|
|
97
|
-
*/
|
|
98
83
|
|
|
99
84
|
if (this.endpoint === '/session' && options.user && options.key) {
|
|
100
85
|
requestOptions.auth = {
|
|
@@ -102,10 +87,6 @@ class WebDriverRequest extends _events.default {
|
|
|
102
87
|
pass: options.key
|
|
103
88
|
};
|
|
104
89
|
}
|
|
105
|
-
/**
|
|
106
|
-
* if the environment variable "STRICT_SSL" is defined as "false", it doesn't require SSL certificates to be valid.
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
90
|
|
|
110
91
|
requestOptions.strictSSL = !(process.env.STRICT_SSL === 'false' || process.env.strict_ssl === 'false');
|
|
111
92
|
return requestOptions;
|
|
@@ -120,16 +101,8 @@ class WebDriverRequest extends _events.default {
|
|
|
120
101
|
|
|
121
102
|
return new Promise((resolve, reject) => (0, _request.default)(fullRequestOptions, (err, response, body) => {
|
|
122
103
|
const error = err || (0, _utils.getErrorFromResponseBody)(body);
|
|
123
|
-
/**
|
|
124
|
-
* hub commands don't follow standard response formats
|
|
125
|
-
* and can have empty bodies
|
|
126
|
-
*/
|
|
127
104
|
|
|
128
105
|
if (this.isHubCommand) {
|
|
129
|
-
/**
|
|
130
|
-
* if body contains HTML the command was called on a node
|
|
131
|
-
* directly without using a hub, therefor throw
|
|
132
|
-
*/
|
|
133
106
|
if (typeof body === 'string' && body.startsWith('<!DOCTYPE html>')) {
|
|
134
107
|
return reject(new Error('Command can only be called to a Selenium Hub'));
|
|
135
108
|
}
|
|
@@ -138,10 +111,6 @@ class WebDriverRequest extends _events.default {
|
|
|
138
111
|
value: body || null
|
|
139
112
|
};
|
|
140
113
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Resolve only if successful response
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
114
|
|
|
146
115
|
if (!err && (0, _utils.isSuccessfulResponse)(response.statusCode, body)) {
|
|
147
116
|
this.emit('response', {
|
|
@@ -149,11 +118,6 @@ class WebDriverRequest extends _events.default {
|
|
|
149
118
|
});
|
|
150
119
|
return resolve(body);
|
|
151
120
|
}
|
|
152
|
-
/**
|
|
153
|
-
* stop retrying as this will never be successful.
|
|
154
|
-
* we will handle this at the elementErrorHandler
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
121
|
|
|
158
122
|
if (error.name === 'stale element reference') {
|
|
159
123
|
log.warn('Request encountered a stale element - terminating request');
|
|
@@ -162,11 +126,6 @@ class WebDriverRequest extends _events.default {
|
|
|
162
126
|
});
|
|
163
127
|
return reject(error);
|
|
164
128
|
}
|
|
165
|
-
/**
|
|
166
|
-
* stop retrying if totalRetryCount was exceeded or there is no reason to
|
|
167
|
-
* retry, e.g. if sessionId is invalid
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
129
|
|
|
171
130
|
if (retryCount >= totalRetryCount || error.message.includes('invalid session id')) {
|
|
172
131
|
log.error('Request failed due to', error);
|
package/build/utils.js
CHANGED
|
@@ -44,35 +44,16 @@ var _selenium = _interopRequireDefault(require("../protocol/selenium.json"));
|
|
|
44
44
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
45
45
|
|
|
46
46
|
const log = (0, _logger.default)('webdriver');
|
|
47
|
-
/**
|
|
48
|
-
* check if WebDriver requests was successful
|
|
49
|
-
* @param {Object} body body payload of response
|
|
50
|
-
* @return {Boolean} true if request was successful
|
|
51
|
-
*/
|
|
52
47
|
|
|
53
48
|
function isSuccessfulResponse(statusCode, body) {
|
|
54
|
-
/**
|
|
55
|
-
* response contains a body
|
|
56
|
-
*/
|
|
57
49
|
if (!body || typeof body.value === 'undefined') {
|
|
58
50
|
log.debug('request failed due to missing body');
|
|
59
51
|
return false;
|
|
60
52
|
}
|
|
61
|
-
/**
|
|
62
|
-
* ignore failing element request to enable lazy loading capability
|
|
63
|
-
*/
|
|
64
53
|
|
|
65
|
-
|
|
66
|
-
if (body.status === 7 && body.value && body.value.message && (body.value.message.toLowerCase().startsWith('no such element') || // Appium
|
|
67
|
-
body.value.message === 'An element could not be located on the page using the given search parameters.' || // Internet Explorter
|
|
68
|
-
body.value.message.toLowerCase().startsWith('unable to find element'))) {
|
|
54
|
+
if (body.status === 7 && body.value && body.value.message && (body.value.message.toLowerCase().startsWith('no such element') || body.value.message === 'An element could not be located on the page using the given search parameters.' || body.value.message.toLowerCase().startsWith('unable to find element'))) {
|
|
69
55
|
return true;
|
|
70
56
|
}
|
|
71
|
-
/**
|
|
72
|
-
* if it has a status property, it should be 0
|
|
73
|
-
* (just here to stay backwards compatible to the jsonwire protocol)
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
57
|
|
|
77
58
|
if (body.status && body.status !== 0) {
|
|
78
59
|
log.debug(`request failed due to status ${body.status}`);
|
|
@@ -80,26 +61,14 @@ function isSuccessfulResponse(statusCode, body) {
|
|
|
80
61
|
}
|
|
81
62
|
|
|
82
63
|
const hasErrorResponse = body.value && (body.value.error || body.value.stackTrace || body.value.stacktrace);
|
|
83
|
-
/**
|
|
84
|
-
* check status code
|
|
85
|
-
*/
|
|
86
64
|
|
|
87
65
|
if (statusCode === 200 && !hasErrorResponse) {
|
|
88
66
|
return true;
|
|
89
67
|
}
|
|
90
|
-
/**
|
|
91
|
-
* if an element was not found we don't flag it as failed request because
|
|
92
|
-
* we lazy load it
|
|
93
|
-
*/
|
|
94
|
-
|
|
95
68
|
|
|
96
69
|
if (statusCode === 404 && body.value && body.value.error === 'no such element') {
|
|
97
70
|
return true;
|
|
98
71
|
}
|
|
99
|
-
/**
|
|
100
|
-
* that has no error property (Appium only)
|
|
101
|
-
*/
|
|
102
|
-
|
|
103
72
|
|
|
104
73
|
if (hasErrorResponse) {
|
|
105
74
|
log.debug('request failed due to response error:', body.value.error);
|
|
@@ -108,14 +77,6 @@ function isSuccessfulResponse(statusCode, body) {
|
|
|
108
77
|
|
|
109
78
|
return true;
|
|
110
79
|
}
|
|
111
|
-
/**
|
|
112
|
-
* checks if command argument is valid according to specificiation
|
|
113
|
-
*
|
|
114
|
-
* @param {*} arg command argument
|
|
115
|
-
* @param {Object} expectedType parameter type (e.g. `number`, `string[]` or `(number|string)`)
|
|
116
|
-
* @return {Boolean} true if argument is valid
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
80
|
|
|
120
81
|
function isValidParameter(arg, expectedType) {
|
|
121
82
|
let shouldBeArray = false;
|
|
@@ -124,19 +85,12 @@ function isValidParameter(arg, expectedType) {
|
|
|
124
85
|
expectedType = expectedType.slice(0, -2);
|
|
125
86
|
shouldBeArray = true;
|
|
126
87
|
}
|
|
127
|
-
/**
|
|
128
|
-
* check type of each individual array element
|
|
129
|
-
*/
|
|
130
|
-
|
|
131
88
|
|
|
132
89
|
if (shouldBeArray) {
|
|
133
90
|
if (!Array.isArray(arg)) {
|
|
134
91
|
return false;
|
|
135
92
|
}
|
|
136
93
|
} else {
|
|
137
|
-
/**
|
|
138
|
-
* transform to array to have a unified check
|
|
139
|
-
*/
|
|
140
94
|
arg = [arg];
|
|
141
95
|
}
|
|
142
96
|
|
|
@@ -150,18 +104,10 @@ function isValidParameter(arg, expectedType) {
|
|
|
150
104
|
|
|
151
105
|
return true;
|
|
152
106
|
}
|
|
153
|
-
/**
|
|
154
|
-
* get type of command argument
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
107
|
|
|
158
108
|
function getArgumentType(arg) {
|
|
159
109
|
return arg === null ? 'null' : typeof arg;
|
|
160
110
|
}
|
|
161
|
-
/**
|
|
162
|
-
* creates the base prototype for the webdriver monad
|
|
163
|
-
*/
|
|
164
|
-
|
|
165
111
|
|
|
166
112
|
function getPrototype({
|
|
167
113
|
isW3C,
|
|
@@ -171,30 +117,7 @@ function getPrototype({
|
|
|
171
117
|
isSeleniumStandalone
|
|
172
118
|
}) {
|
|
173
119
|
const prototype = {};
|
|
174
|
-
const ProtocolCommands = (0, _lodash.default)(
|
|
175
|
-
/**
|
|
176
|
-
* if mobile apply JSONWire and WebDriver protocol because
|
|
177
|
-
* some legacy JSONWire commands are still used in Appium
|
|
178
|
-
* (e.g. set/get geolocation)
|
|
179
|
-
*/
|
|
180
|
-
isMobile ? (0, _lodash.default)({}, _jsonwp.default, _webdriver.default) : isW3C ? _webdriver.default : _jsonwp.default,
|
|
181
|
-
/**
|
|
182
|
-
* only apply mobile protocol if session is actually for mobile
|
|
183
|
-
*/
|
|
184
|
-
isMobile ? (0, _lodash.default)({}, _mjsonwp.default, _appium.default) : {},
|
|
185
|
-
/**
|
|
186
|
-
* only apply special Chrome commands if session is using Chrome
|
|
187
|
-
*/
|
|
188
|
-
isChrome ? _chromium.default : {},
|
|
189
|
-
/**
|
|
190
|
-
* only Sauce Labs specific vendor commands
|
|
191
|
-
*/
|
|
192
|
-
isSauce ? _saucelabs.default : {},
|
|
193
|
-
/**
|
|
194
|
-
* only apply special commands when running tests using
|
|
195
|
-
* Selenium Grid or Selenium Standalone server
|
|
196
|
-
*/
|
|
197
|
-
isSeleniumStandalone ? _selenium.default : {});
|
|
120
|
+
const ProtocolCommands = (0, _lodash.default)(isMobile ? (0, _lodash.default)({}, _jsonwp.default, _webdriver.default) : isW3C ? _webdriver.default : _jsonwp.default, isMobile ? (0, _lodash.default)({}, _mjsonwp.default, _appium.default) : {}, isChrome ? _chromium.default : {}, isSauce ? _saucelabs.default : {}, isSeleniumStandalone ? _selenium.default : {});
|
|
198
121
|
|
|
199
122
|
for (const [endpoint, methods] of Object.entries(ProtocolCommands)) {
|
|
200
123
|
for (const [method, commandData] of Object.entries(methods)) {
|
|
@@ -206,11 +129,6 @@ function getPrototype({
|
|
|
206
129
|
|
|
207
130
|
return prototype;
|
|
208
131
|
}
|
|
209
|
-
/**
|
|
210
|
-
* get command call structure
|
|
211
|
-
* (for logging purposes)
|
|
212
|
-
*/
|
|
213
|
-
|
|
214
132
|
|
|
215
133
|
function commandCallStructure(commandName, args) {
|
|
216
134
|
const callArgs = args.map(arg => {
|
|
@@ -230,108 +148,40 @@ function commandCallStructure(commandName, args) {
|
|
|
230
148
|
}).join(', ');
|
|
231
149
|
return `${commandName}(${callArgs})`;
|
|
232
150
|
}
|
|
233
|
-
/**
|
|
234
|
-
* check if session is based on W3C protocol based on the /session response
|
|
235
|
-
* @param {Object} capabilities caps of session response
|
|
236
|
-
* @return {Boolean} true if W3C (browser)
|
|
237
|
-
*/
|
|
238
|
-
|
|
239
151
|
|
|
240
152
|
function isW3C(capabilities) {
|
|
241
|
-
/**
|
|
242
|
-
* JSONWire protocol doesn't return a property `capabilities`.
|
|
243
|
-
* Also check for Appium response as it is using JSONWire protocol for most of the part.
|
|
244
|
-
*/
|
|
245
153
|
if (!capabilities) {
|
|
246
154
|
return false;
|
|
247
155
|
}
|
|
248
|
-
/**
|
|
249
|
-
* assume session to be a WebDriver session when
|
|
250
|
-
* - capabilities are returned
|
|
251
|
-
* (https://w3c.github.io/webdriver/#dfn-new-sessions)
|
|
252
|
-
* - it is an Appium session (since Appium is full W3C compliant)
|
|
253
|
-
*/
|
|
254
|
-
|
|
255
156
|
|
|
256
157
|
const isAppium = capabilities.automationName || capabilities.deviceName;
|
|
257
|
-
const hasW3CCaps = capabilities.platformName && capabilities.browserVersion && (
|
|
258
|
-
/**
|
|
259
|
-
* local safari and BrowserStack don't provide platformVersion therefor
|
|
260
|
-
* check also if setWindowRect is provided
|
|
261
|
-
*/
|
|
262
|
-
capabilities.platformVersion || Object.prototype.hasOwnProperty.call(capabilities, 'setWindowRect'));
|
|
158
|
+
const hasW3CCaps = capabilities.platformName && capabilities.browserVersion && (capabilities.platformVersion || Object.prototype.hasOwnProperty.call(capabilities, 'setWindowRect'));
|
|
263
159
|
return Boolean(hasW3CCaps || isAppium);
|
|
264
160
|
}
|
|
265
|
-
/**
|
|
266
|
-
* check if session is run by Chromedriver
|
|
267
|
-
* @param {Object} capabilities caps of session response
|
|
268
|
-
* @return {Boolean} true if run by Chromedriver
|
|
269
|
-
*/
|
|
270
|
-
|
|
271
161
|
|
|
272
162
|
function isChrome(caps) {
|
|
273
163
|
return Boolean(caps.chrome) || Boolean(caps['goog:chromeOptions']);
|
|
274
164
|
}
|
|
275
|
-
/**
|
|
276
|
-
* check if current platform is mobile device
|
|
277
|
-
*
|
|
278
|
-
* @param {Object} caps capabilities
|
|
279
|
-
* @return {Boolean} true if platform is mobile device
|
|
280
|
-
*/
|
|
281
|
-
|
|
282
165
|
|
|
283
166
|
function isMobile(caps) {
|
|
284
|
-
return Boolean(typeof caps['appium-version'] !== 'undefined' || typeof caps['device-type'] !== 'undefined' || typeof caps['deviceType'] !== 'undefined' || typeof caps['device-orientation'] !== 'undefined' || typeof caps['deviceOrientation'] !== 'undefined' || typeof caps.deviceName !== 'undefined' ||
|
|
285
|
-
caps.browserName === '' || caps.browserName !== undefined && (caps.browserName.toLowerCase() === 'ipad' || caps.browserName.toLowerCase() === 'iphone' || caps.browserName.toLowerCase() === 'android'));
|
|
167
|
+
return Boolean(typeof caps['appium-version'] !== 'undefined' || typeof caps['device-type'] !== 'undefined' || typeof caps['deviceType'] !== 'undefined' || typeof caps['device-orientation'] !== 'undefined' || typeof caps['deviceOrientation'] !== 'undefined' || typeof caps.deviceName !== 'undefined' || caps.browserName === '' || caps.browserName !== undefined && (caps.browserName.toLowerCase() === 'ipad' || caps.browserName.toLowerCase() === 'iphone' || caps.browserName.toLowerCase() === 'android'));
|
|
286
168
|
}
|
|
287
|
-
/**
|
|
288
|
-
* check if session is run on iOS device
|
|
289
|
-
* @param {Object} capabilities caps of session response
|
|
290
|
-
* @return {Boolean} true if run on iOS device
|
|
291
|
-
*/
|
|
292
|
-
|
|
293
169
|
|
|
294
170
|
function isIOS(caps) {
|
|
295
171
|
return Boolean(caps.platformName && caps.platformName.match(/iOS/i) || caps.deviceName && caps.deviceName.match(/(iPad|iPhone)/i));
|
|
296
172
|
}
|
|
297
|
-
/**
|
|
298
|
-
* check if session is run on Android device
|
|
299
|
-
* @param {Object} capabilities caps of session response
|
|
300
|
-
* @return {Boolean} true if run on Android device
|
|
301
|
-
*/
|
|
302
|
-
|
|
303
173
|
|
|
304
174
|
function isAndroid(caps) {
|
|
305
175
|
return Boolean(caps.platformName && caps.platformName.match(/Android/i) || caps.browserName && caps.browserName.match(/Android/i));
|
|
306
176
|
}
|
|
307
|
-
/**
|
|
308
|
-
* detects if session is run on Sauce with extended debugging enabled
|
|
309
|
-
* @param {string} hostname hostname of session request
|
|
310
|
-
* @param {object} capabilities session capabilities
|
|
311
|
-
* @return {Boolean} true if session is running on Sauce with extended debugging enabled
|
|
312
|
-
*/
|
|
313
|
-
|
|
314
177
|
|
|
315
178
|
function isSauce(hostname, caps) {
|
|
316
|
-
return Boolean(
|
|
179
|
+
return Boolean(caps.extendedDebugging || caps['sauce:options'] && caps['sauce:options'].extendedDebugging);
|
|
317
180
|
}
|
|
318
|
-
/**
|
|
319
|
-
* detects if session is run using Selenium Standalone server
|
|
320
|
-
* @param {object} capabilities session capabilities
|
|
321
|
-
* @return {Boolean} true if session is run with Selenium Standalone Server
|
|
322
|
-
*/
|
|
323
|
-
|
|
324
181
|
|
|
325
182
|
function isSeleniumStandalone(caps) {
|
|
326
183
|
return Boolean(caps['webdriver.remote.sessionid']);
|
|
327
184
|
}
|
|
328
|
-
/**
|
|
329
|
-
* returns information about the environment
|
|
330
|
-
* @param {Object} hostname name of the host to run the session against
|
|
331
|
-
* @param {Object} capabilities caps of session response
|
|
332
|
-
* @return {Object} object with environment flags
|
|
333
|
-
*/
|
|
334
|
-
|
|
335
185
|
|
|
336
186
|
function environmentDetector({
|
|
337
187
|
hostname,
|
|
@@ -348,12 +198,6 @@ function environmentDetector({
|
|
|
348
198
|
isSeleniumStandalone: isSeleniumStandalone(capabilities)
|
|
349
199
|
};
|
|
350
200
|
}
|
|
351
|
-
/**
|
|
352
|
-
* helper method to determine the error from webdriver response
|
|
353
|
-
* @param {Object} body body object
|
|
354
|
-
* @return {Object} error
|
|
355
|
-
*/
|
|
356
|
-
|
|
357
201
|
|
|
358
202
|
function getErrorFromResponseBody(body) {
|
|
359
203
|
if (!body) {
|
|
@@ -369,8 +213,7 @@ function getErrorFromResponseBody(body) {
|
|
|
369
213
|
}
|
|
370
214
|
|
|
371
215
|
return new CustomRequestError(body);
|
|
372
|
-
}
|
|
373
|
-
|
|
216
|
+
}
|
|
374
217
|
|
|
375
218
|
class CustomRequestError extends Error {
|
|
376
219
|
constructor(body) {
|
|
@@ -384,11 +227,6 @@ class CustomRequestError extends Error {
|
|
|
384
227
|
}
|
|
385
228
|
|
|
386
229
|
}
|
|
387
|
-
/**
|
|
388
|
-
* overwrite native element commands with user defined
|
|
389
|
-
* @param {object} propertiesObject propertiesObject
|
|
390
|
-
*/
|
|
391
|
-
|
|
392
230
|
|
|
393
231
|
exports.CustomRequestError = CustomRequestError;
|
|
394
232
|
|
|
@@ -412,7 +250,11 @@ function overwriteElementCommands(propertiesObject) {
|
|
|
412
250
|
delete propertiesObject[commandName];
|
|
413
251
|
|
|
414
252
|
const newCommand = function (...args) {
|
|
415
|
-
|
|
253
|
+
const element = this;
|
|
254
|
+
return userDefinedCommand.apply(element, [function origCommandFunction() {
|
|
255
|
+
const context = this || element;
|
|
256
|
+
return origCommand.apply(context, arguments);
|
|
257
|
+
}, ...args]);
|
|
416
258
|
};
|
|
417
259
|
|
|
418
260
|
propertiesObject[commandName] = {
|
|
@@ -426,13 +268,6 @@ function overwriteElementCommands(propertiesObject) {
|
|
|
426
268
|
value: {}
|
|
427
269
|
};
|
|
428
270
|
}
|
|
429
|
-
/**
|
|
430
|
-
* return all supported flags and return them in a format so we can attach them
|
|
431
|
-
* to the instance protocol
|
|
432
|
-
* @param {Object} options driver instance or option object containing these flags
|
|
433
|
-
* @return {Object} prototype object
|
|
434
|
-
*/
|
|
435
|
-
|
|
436
271
|
|
|
437
272
|
function getEnvironmentVars({
|
|
438
273
|
isW3C,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webdriver",
|
|
3
|
-
"version": "5.11.
|
|
3
|
+
"version": "5.11.12",
|
|
4
4
|
"description": "A Node.js bindings implementation for the W3C WebDriver and Mobile JSONWire Protocol",
|
|
5
5
|
"author": "Christian Bromann <christian@saucelabs.com>",
|
|
6
6
|
"homepage": "https://github.com/webdriverio/webdriverio/tree/master/packages/webdriver",
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"lodash.merge": "^4.6.1",
|
|
37
37
|
"request": "^2.83.0"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "32d9805f8dee10f0665e31eed14f774aaa48c914"
|
|
40
40
|
}
|
package/protocol/saucelabs.json
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
|
-
"/session/:sessionId/sauce/ondemand/throttle": {
|
|
84
|
+
"/session/:sessionId/sauce/ondemand/throttle/network": {
|
|
85
85
|
"POST": {
|
|
86
86
|
"command": "throttleNetwork",
|
|
87
87
|
"description": "With network conditioning you can test your site on a variety of network connections, including Edge, 3G, and even offline. You can throttle the data throughput, including the maximum download and upload throughput, and use latency manipulation to enforce a minimum delay in connection round-trip time (RTT).",
|
|
@@ -108,6 +108,29 @@
|
|
|
108
108
|
}]
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
|
+
"/session/:sessionId/sauce/ondemand/throttle/cpu": {
|
|
112
|
+
"POST": {
|
|
113
|
+
"command": "throttleCPU",
|
|
114
|
+
"description": "You can throttle the CPU in DevTools to understand how your page performs under that constraint.",
|
|
115
|
+
"ref": "https://wiki.saucelabs.com/display/DOCS/Custom+Sauce+Labs+WebDriver+Extensions+for+Network+and+Log+Commands#CustomSauceLabsWebDriverExtensionsforNetworkandLogCommands-ThrottleCPUCapabilities",
|
|
116
|
+
"examples": [
|
|
117
|
+
[
|
|
118
|
+
"// throttle CPU and make it run 4x slower",
|
|
119
|
+
"browser.throttleCPU(4)"
|
|
120
|
+
],
|
|
121
|
+
[
|
|
122
|
+
"// reset CPU throttling",
|
|
123
|
+
"browser.throttleCPU(0)"
|
|
124
|
+
]
|
|
125
|
+
],
|
|
126
|
+
"parameters": [{
|
|
127
|
+
"name": "rate",
|
|
128
|
+
"type": "number",
|
|
129
|
+
"description": "Rate on how much the CPU should get throttled.",
|
|
130
|
+
"required": true
|
|
131
|
+
}]
|
|
132
|
+
}
|
|
133
|
+
},
|
|
111
134
|
"/session/:sessionId/sauce/ondemand/intercept": {
|
|
112
135
|
"POST": {
|
|
113
136
|
"command": "interceptRequest",
|
package/webdriver.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ declare namespace WebDriver {
|
|
|
66
66
|
perfLoggingPrefs?: {
|
|
67
67
|
[name: string]: any;
|
|
68
68
|
};
|
|
69
|
+
prefs?: string[];
|
|
69
70
|
windowTypes?: string[];
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -78,7 +79,7 @@ declare namespace WebDriver {
|
|
|
78
79
|
args?: string[],
|
|
79
80
|
profile?: string,
|
|
80
81
|
log?: FirefoxLogObject,
|
|
81
|
-
prefs
|
|
82
|
+
prefs?: {
|
|
82
83
|
[name: string]: string | number | boolean;
|
|
83
84
|
}
|
|
84
85
|
}
|
|
@@ -368,6 +369,7 @@ declare namespace WebDriver {
|
|
|
368
369
|
interface ClientOptions {
|
|
369
370
|
capabilities: DesiredCapabilities;
|
|
370
371
|
isW3C: boolean;
|
|
372
|
+
isChrome: boolean;
|
|
371
373
|
isAndroid: boolean;
|
|
372
374
|
isMobile: boolean;
|
|
373
375
|
isIOS: boolean;
|
|
@@ -639,6 +641,7 @@ declare namespace WebDriver {
|
|
|
639
641
|
interface Client {
|
|
640
642
|
getPageLogs(type: string): object;
|
|
641
643
|
throttleNetwork(condition: (string|object)): void;
|
|
644
|
+
throttleCPU(rate: number): void;
|
|
642
645
|
interceptRequest(rule: object): void;
|
|
643
646
|
assertPerformance(name: string, metrics?: string[]): boolean;
|
|
644
647
|
}
|