webdriver 5.11.10 → 5.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/command.js +3 -28
- package/build/constants.js +0 -51
- package/build/index.js +9 -46
- package/build/monad.js +2 -70
- package/build/request.js +0 -39
- package/build/utils.js +6 -176
- package/package.json +4 -4
- package/protocol/appium.json +28 -0
- package/protocol/chromium.json +31 -0
- package/webdriver.d.ts +131 -63
package/build/command.js
CHANGED
|
@@ -24,61 +24,36 @@ function _default(method, endpointUri, commandInfo) {
|
|
|
24
24
|
isHubCommand = false
|
|
25
25
|
} = commandInfo;
|
|
26
26
|
return function protocolCommand(...args) {
|
|
27
|
-
let endpoint = endpointUri;
|
|
28
|
-
|
|
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
|
}
|
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
|
@@ -41,7 +41,9 @@ var _chromium = _interopRequireDefault(require("../protocol/chromium.json"));
|
|
|
41
41
|
|
|
42
42
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
43
43
|
|
|
44
|
-
function
|
|
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; }
|
|
45
47
|
|
|
46
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; }
|
|
47
49
|
|
|
@@ -52,66 +54,35 @@ class WebDriver {
|
|
|
52
54
|
if (!options.logLevels || !options.logLevels['webdriver']) {
|
|
53
55
|
_logger.default.setLevel('webdriver', params.logLevel);
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* and we want to pass both styles to the server, which means we need
|
|
58
|
-
* to check what style the user sent in so we know how to construct the
|
|
59
|
-
* object for the other style
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const [w3cCaps, jsonwpCaps] = params.capabilities && params.capabilities.alwaysMatch
|
|
64
|
-
/**
|
|
65
|
-
* in case W3C compliant capabilities are provided
|
|
66
|
-
*/
|
|
67
|
-
? [params.capabilities, params.capabilities.alwaysMatch]
|
|
68
|
-
/**
|
|
69
|
-
* otherwise assume they passed in jsonwp-style caps (flat object)
|
|
70
|
-
*/
|
|
71
|
-
: [{
|
|
57
|
+
|
|
58
|
+
const [w3cCaps, jsonwpCaps] = params.capabilities && params.capabilities.alwaysMatch ? [params.capabilities, params.capabilities.alwaysMatch] : [{
|
|
72
59
|
alwaysMatch: params.capabilities,
|
|
73
60
|
firstMatch: [{}]
|
|
74
61
|
}, params.capabilities];
|
|
75
62
|
const sessionRequest = new _request.default('POST', '/session', {
|
|
76
63
|
capabilities: w3cCaps,
|
|
77
|
-
|
|
78
|
-
desiredCapabilities: jsonwpCaps // JSONWP compliant
|
|
79
|
-
|
|
64
|
+
desiredCapabilities: jsonwpCaps
|
|
80
65
|
});
|
|
81
66
|
const response = await sessionRequest.makeRequest(params);
|
|
82
|
-
/**
|
|
83
|
-
* save original set of capabilities to allow to request the same session again
|
|
84
|
-
* (e.g. for reloadSession command in WebdriverIO)
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
67
|
params.requestedCapabilities = {
|
|
88
68
|
w3cCaps,
|
|
89
69
|
jsonwpCaps
|
|
90
|
-
/**
|
|
91
|
-
* save actual receveived session details
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
70
|
};
|
|
95
71
|
params.capabilities = response.value.capabilities || response.value;
|
|
96
72
|
const environment = (0, _utils.environmentDetector)(params);
|
|
97
73
|
const environmentPrototype = (0, _utils.getEnvironmentVars)(environment);
|
|
98
74
|
const protocolCommands = (0, _utils.getPrototype)(environment);
|
|
99
75
|
|
|
100
|
-
const prototype = _objectSpread({}, protocolCommands, environmentPrototype, userPrototype);
|
|
76
|
+
const prototype = _objectSpread({}, protocolCommands, {}, environmentPrototype, {}, userPrototype);
|
|
101
77
|
|
|
102
78
|
const monad = (0, _monad.default)(params, modifier, prototype);
|
|
103
79
|
return monad(response.value.sessionId || response.sessionId, commandWrapper);
|
|
104
80
|
}
|
|
105
|
-
/**
|
|
106
|
-
* allows user to attach to existing sessions
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
81
|
|
|
110
82
|
static attachToSession(options = {}, modifier, userPrototype = {}, commandWrapper) {
|
|
111
83
|
if (typeof options.sessionId !== 'string') {
|
|
112
84
|
throw new Error('sessionId is required to attach to existing session');
|
|
113
|
-
}
|
|
114
|
-
|
|
85
|
+
}
|
|
115
86
|
|
|
116
87
|
if (options.logLevel !== undefined) {
|
|
117
88
|
_logger.default.setLevel('webdriver', options.logLevel);
|
|
@@ -122,7 +93,7 @@ class WebDriver {
|
|
|
122
93
|
const environmentPrototype = (0, _utils.getEnvironmentVars)(options);
|
|
123
94
|
const protocolCommands = (0, _utils.getPrototype)(options);
|
|
124
95
|
|
|
125
|
-
const prototype = _objectSpread({}, protocolCommands, environmentPrototype, userPrototype);
|
|
96
|
+
const prototype = _objectSpread({}, protocolCommands, {}, environmentPrototype, {}, userPrototype);
|
|
126
97
|
|
|
127
98
|
const monad = (0, _monad.default)(options, modifier, prototype);
|
|
128
99
|
return monad(options.sessionId, commandWrapper);
|
|
@@ -135,10 +106,6 @@ class WebDriver {
|
|
|
135
106
|
static get DEFAULTS() {
|
|
136
107
|
return _constants.DEFAULTS;
|
|
137
108
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Protocols
|
|
140
|
-
*/
|
|
141
|
-
|
|
142
109
|
|
|
143
110
|
static get WebDriverProtocol() {
|
|
144
111
|
return _webdriver.default;
|
|
@@ -161,9 +128,5 @@ class WebDriver {
|
|
|
161
128
|
}
|
|
162
129
|
|
|
163
130
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Helper methods consumed by webdriverio package
|
|
166
|
-
*/
|
|
167
|
-
|
|
168
131
|
|
|
169
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
|
@@ -66,10 +66,6 @@ class WebDriverRequest extends _events.default {
|
|
|
66
66
|
agent: options.agent || agents[options.protocol],
|
|
67
67
|
headers: typeof options.headers === 'object' ? options.headers : {},
|
|
68
68
|
qs: typeof options.queryParams === 'object' ? options.queryParams : {}
|
|
69
|
-
/**
|
|
70
|
-
* only apply body property if existing
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
69
|
};
|
|
74
70
|
|
|
75
71
|
if (this.body && (Object.keys(this.body).length || this.method === 'POST')) {
|
|
@@ -78,21 +74,12 @@ class WebDriverRequest extends _events.default {
|
|
|
78
74
|
'Content-Length': Buffer.byteLength(JSON.stringify(requestOptions.body), 'UTF-8')
|
|
79
75
|
});
|
|
80
76
|
}
|
|
81
|
-
/**
|
|
82
|
-
* if we don't have a session id we set it here, unless we call commands that don't require session ids, for
|
|
83
|
-
* example /sessions. The call to /sessions is not connected to a session itself and it therefore doesn't
|
|
84
|
-
* require it
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
77
|
|
|
88
78
|
if (this.requiresSessionId && !sessionId) {
|
|
89
79
|
throw new Error('A sessionId is required for this command');
|
|
90
80
|
}
|
|
91
81
|
|
|
92
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))));
|
|
93
|
-
/**
|
|
94
|
-
* send authentication credentials only when creating new session
|
|
95
|
-
*/
|
|
96
83
|
|
|
97
84
|
if (this.endpoint === '/session' && options.user && options.key) {
|
|
98
85
|
requestOptions.auth = {
|
|
@@ -100,10 +87,6 @@ class WebDriverRequest extends _events.default {
|
|
|
100
87
|
pass: options.key
|
|
101
88
|
};
|
|
102
89
|
}
|
|
103
|
-
/**
|
|
104
|
-
* if the environment variable "STRICT_SSL" is defined as "false", it doesn't require SSL certificates to be valid.
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
90
|
|
|
108
91
|
requestOptions.strictSSL = !(process.env.STRICT_SSL === 'false' || process.env.strict_ssl === 'false');
|
|
109
92
|
return requestOptions;
|
|
@@ -118,16 +101,8 @@ class WebDriverRequest extends _events.default {
|
|
|
118
101
|
|
|
119
102
|
return new Promise((resolve, reject) => (0, _request.default)(fullRequestOptions, (err, response, body) => {
|
|
120
103
|
const error = err || (0, _utils.getErrorFromResponseBody)(body);
|
|
121
|
-
/**
|
|
122
|
-
* hub commands don't follow standard response formats
|
|
123
|
-
* and can have empty bodies
|
|
124
|
-
*/
|
|
125
104
|
|
|
126
105
|
if (this.isHubCommand) {
|
|
127
|
-
/**
|
|
128
|
-
* if body contains HTML the command was called on a node
|
|
129
|
-
* directly without using a hub, therefor throw
|
|
130
|
-
*/
|
|
131
106
|
if (typeof body === 'string' && body.startsWith('<!DOCTYPE html>')) {
|
|
132
107
|
return reject(new Error('Command can only be called to a Selenium Hub'));
|
|
133
108
|
}
|
|
@@ -136,10 +111,6 @@ class WebDriverRequest extends _events.default {
|
|
|
136
111
|
value: body || null
|
|
137
112
|
};
|
|
138
113
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Resolve only if successful response
|
|
141
|
-
*/
|
|
142
|
-
|
|
143
114
|
|
|
144
115
|
if (!err && (0, _utils.isSuccessfulResponse)(response.statusCode, body)) {
|
|
145
116
|
this.emit('response', {
|
|
@@ -147,11 +118,6 @@ class WebDriverRequest extends _events.default {
|
|
|
147
118
|
});
|
|
148
119
|
return resolve(body);
|
|
149
120
|
}
|
|
150
|
-
/**
|
|
151
|
-
* stop retrying as this will never be successful.
|
|
152
|
-
* we will handle this at the elementErrorHandler
|
|
153
|
-
*/
|
|
154
|
-
|
|
155
121
|
|
|
156
122
|
if (error.name === 'stale element reference') {
|
|
157
123
|
log.warn('Request encountered a stale element - terminating request');
|
|
@@ -160,11 +126,6 @@ class WebDriverRequest extends _events.default {
|
|
|
160
126
|
});
|
|
161
127
|
return reject(error);
|
|
162
128
|
}
|
|
163
|
-
/**
|
|
164
|
-
* stop retrying if totalRetryCount was exceeded or there is no reason to
|
|
165
|
-
* retry, e.g. if sessionId is invalid
|
|
166
|
-
*/
|
|
167
|
-
|
|
168
129
|
|
|
169
130
|
if (retryCount >= totalRetryCount || error.message.includes('invalid session id')) {
|
|
170
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
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
|
|
|
@@ -414,8 +252,7 @@ function overwriteElementCommands(propertiesObject) {
|
|
|
414
252
|
const newCommand = function (...args) {
|
|
415
253
|
const element = this;
|
|
416
254
|
return userDefinedCommand.apply(element, [function origCommandFunction() {
|
|
417
|
-
const context = this || element;
|
|
418
|
-
|
|
255
|
+
const context = this || element;
|
|
419
256
|
return origCommand.apply(context, arguments);
|
|
420
257
|
}, ...args]);
|
|
421
258
|
};
|
|
@@ -431,13 +268,6 @@ function overwriteElementCommands(propertiesObject) {
|
|
|
431
268
|
value: {}
|
|
432
269
|
};
|
|
433
270
|
}
|
|
434
|
-
/**
|
|
435
|
-
* return all supported flags and return them in a format so we can attach them
|
|
436
|
-
* to the instance protocol
|
|
437
|
-
* @param {Object} options driver instance or option object containing these flags
|
|
438
|
-
* @return {Object} prototype object
|
|
439
|
-
*/
|
|
440
|
-
|
|
441
271
|
|
|
442
272
|
function getEnvironmentVars({
|
|
443
273
|
isW3C,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webdriver",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.12.1",
|
|
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",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"url": "https://github.com/webdriverio/webdriverio/issues"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@wdio/config": "^5.
|
|
34
|
-
"@wdio/logger": "^5.
|
|
33
|
+
"@wdio/config": "^5.12.1",
|
|
34
|
+
"@wdio/logger": "^5.12.1",
|
|
35
35
|
"deepmerge": "^4.0.0",
|
|
36
36
|
"lodash.merge": "^4.6.1",
|
|
37
37
|
"request": "^2.83.0"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "848151e5fdcb8b694c1a273b9b69852c22875687"
|
|
40
40
|
}
|
package/protocol/appium.json
CHANGED
|
@@ -1401,5 +1401,33 @@
|
|
|
1401
1401
|
}
|
|
1402
1402
|
}
|
|
1403
1403
|
}
|
|
1404
|
+
},
|
|
1405
|
+
"/session/:sessionId/appium/execute_driver": {
|
|
1406
|
+
"POST": {
|
|
1407
|
+
"command": "driverScript",
|
|
1408
|
+
"description": "This command allows you to define a webdriverio script in a string and send it to the Appium server to be executed locally to the server itself, thus reducing latency that might otherwise occur along with each command.",
|
|
1409
|
+
"ref": "https://github.com/appium/appium/blob/master/docs/en/commands/session/execute-driver.md",
|
|
1410
|
+
"parameters": [{
|
|
1411
|
+
"name": "script",
|
|
1412
|
+
"type": "string",
|
|
1413
|
+
"description": "The script to execute. It has access to a 'driver' object which represents a webdriverio session attached to the current server.",
|
|
1414
|
+
"required": true
|
|
1415
|
+
}, {
|
|
1416
|
+
"name": "type",
|
|
1417
|
+
"type": "string",
|
|
1418
|
+
"description": "The language/framework used in the script. Currently, only 'webdriverio' is supported and is the default.",
|
|
1419
|
+
"required": false
|
|
1420
|
+
}, {
|
|
1421
|
+
"name": "timeout",
|
|
1422
|
+
"type": "number",
|
|
1423
|
+
"description": "The number of milliseconds the script should be allowed to run before being killed by the Appium server. Defaults to the equivalent of 1 hour.",
|
|
1424
|
+
"required": false
|
|
1425
|
+
}],
|
|
1426
|
+
"returns": {
|
|
1427
|
+
"type": "object",
|
|
1428
|
+
"name": "result",
|
|
1429
|
+
"description": "An object containing two fields: 'result', which is the return value of the script itself, and 'logs', which contains 3 inner fields, 'log', 'warn', and 'error', which hold an array of strings logged by console.log, console.warn, and console.error in the script's execution."
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1404
1432
|
}
|
|
1405
1433
|
}
|
package/protocol/chromium.json
CHANGED
|
@@ -414,5 +414,36 @@
|
|
|
414
414
|
"description": "The base64-encoded PNG image data comprising the screenshot of the visible region of an element’s bounding rectangle after it has been scrolled into view."
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
|
+
},
|
|
418
|
+
"/session/:sessionId/se/log/types": {
|
|
419
|
+
"GET": {
|
|
420
|
+
"command": "getLogTypes",
|
|
421
|
+
"description": "Get available log types.",
|
|
422
|
+
"ref": "https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidlogtypes",
|
|
423
|
+
"parameters": [],
|
|
424
|
+
"returns": {
|
|
425
|
+
"type": "String[]",
|
|
426
|
+
"name": "logTypes",
|
|
427
|
+
"description": "The list of available log types, example: browser, driver."
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
"/session/:sessionId/se/log": {
|
|
432
|
+
"POST": {
|
|
433
|
+
"command": "getLogs",
|
|
434
|
+
"description": "Get the log for a given log type. Log buffer is reset after each request.",
|
|
435
|
+
"ref": "https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidlog",
|
|
436
|
+
"parameters": [{
|
|
437
|
+
"name": "type",
|
|
438
|
+
"type": "string",
|
|
439
|
+
"description": "the log type",
|
|
440
|
+
"required": true
|
|
441
|
+
}],
|
|
442
|
+
"returns": {
|
|
443
|
+
"type": "Object[]",
|
|
444
|
+
"name": "logs",
|
|
445
|
+
"description": "The list of log entries."
|
|
446
|
+
}
|
|
447
|
+
}
|
|
417
448
|
}
|
|
418
449
|
}
|
package/webdriver.d.ts
CHANGED
|
@@ -79,7 +79,7 @@ declare namespace WebDriver {
|
|
|
79
79
|
args?: string[],
|
|
80
80
|
profile?: string,
|
|
81
81
|
log?: FirefoxLogObject,
|
|
82
|
-
prefs
|
|
82
|
+
prefs?: {
|
|
83
83
|
[name: string]: string | number | boolean;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -213,6 +213,21 @@ declare namespace WebDriver {
|
|
|
213
213
|
// wdio-sauce-service specific
|
|
214
214
|
build?: string;
|
|
215
215
|
|
|
216
|
+
// Saucelabs w3c specific
|
|
217
|
+
'sauce:options'?: {
|
|
218
|
+
[name: string]: any;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Browserstack w3c specific
|
|
222
|
+
'bstack:options'?: {
|
|
223
|
+
[name: string]: any;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Testingbot w3c specific
|
|
227
|
+
'tb:options'?: {
|
|
228
|
+
[name: string]: any;
|
|
229
|
+
};
|
|
230
|
+
|
|
216
231
|
// Appium General Capabilities
|
|
217
232
|
automationName?: string;
|
|
218
233
|
platformVersion?: string;
|
|
@@ -369,19 +384,69 @@ declare namespace WebDriver {
|
|
|
369
384
|
interface ClientOptions {
|
|
370
385
|
capabilities: DesiredCapabilities;
|
|
371
386
|
isW3C: boolean;
|
|
387
|
+
isChrome: boolean;
|
|
372
388
|
isAndroid: boolean;
|
|
373
389
|
isMobile: boolean;
|
|
374
390
|
isIOS: boolean;
|
|
375
391
|
sessionId: string;
|
|
376
392
|
}
|
|
377
393
|
|
|
394
|
+
// object with no match
|
|
395
|
+
interface ProtocolCommandResponse {
|
|
396
|
+
[key: string]: any;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// webdriver.json
|
|
400
|
+
interface SessionReturn extends DesiredCapabilities, ProtocolCommandResponse { }
|
|
401
|
+
|
|
402
|
+
interface StatusReturn extends ProtocolCommandResponse {
|
|
403
|
+
ready?: boolean,
|
|
404
|
+
message?: string,
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
interface WindowHandle {
|
|
408
|
+
handle: string,
|
|
409
|
+
type: string
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
interface RectReturn {
|
|
413
|
+
x: number,
|
|
414
|
+
y: number,
|
|
415
|
+
width: number,
|
|
416
|
+
height: number
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// appium.json
|
|
420
|
+
interface StringsReturn {
|
|
421
|
+
[key:string]: string
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
interface SettingsReturn extends ProtocolCommandResponse {
|
|
425
|
+
shouldUseCompactResponses?: boolean,
|
|
426
|
+
elementResponseAttributes?: string,
|
|
427
|
+
ignoreUnimportantViews?: boolean,
|
|
428
|
+
allowInvisibleElements?: boolean,
|
|
429
|
+
enableNotificationListener?: boolean,
|
|
430
|
+
actionAcknowledgmentTimeout?: number,
|
|
431
|
+
keyInjectionDelay?: number,
|
|
432
|
+
scrollAcknowledgmentTimeout?: number,
|
|
433
|
+
waitForIdleTimeout?: number,
|
|
434
|
+
waitForSelectorTimeout?: number,
|
|
435
|
+
normalizeTagNames?: boolean,
|
|
436
|
+
shutdownOnPowerDisconnect?: boolean,
|
|
437
|
+
mjpegServerScreenshotQuality?: number,
|
|
438
|
+
mjpegServerFramerate?: number,
|
|
439
|
+
screenshotQuality?: number,
|
|
440
|
+
mjpegScalingFactor?: number,
|
|
441
|
+
}
|
|
442
|
+
|
|
378
443
|
// generated typings
|
|
379
444
|
// webdriver types
|
|
380
445
|
interface Client {
|
|
381
|
-
newSession(capabilities: object):
|
|
446
|
+
newSession(capabilities: object): SessionReturn;
|
|
382
447
|
deleteSession(): void;
|
|
383
|
-
status():
|
|
384
|
-
getTimeouts():
|
|
448
|
+
status(): StatusReturn;
|
|
449
|
+
getTimeouts(): Timeouts;
|
|
385
450
|
setTimeouts(implicit?: number, pageLoad?: number, script?: number): void;
|
|
386
451
|
getUrl(): string;
|
|
387
452
|
navigateTo(url: string): string;
|
|
@@ -392,39 +457,39 @@ declare namespace WebDriver {
|
|
|
392
457
|
getWindowHandle(): string;
|
|
393
458
|
closeWindow(): void;
|
|
394
459
|
switchToWindow(handle: string): void;
|
|
395
|
-
createWindow(type: string):
|
|
460
|
+
createWindow(type: string): WindowHandle;
|
|
396
461
|
getWindowHandles(): string[];
|
|
397
462
|
switchToFrame(id: (number|string|object|null)): void;
|
|
398
463
|
switchToParentFrame(): void;
|
|
399
|
-
getWindowRect():
|
|
400
|
-
setWindowRect(x: (number|null), y: (number|null), width: (number|null), height: (number|null)):
|
|
401
|
-
maximizeWindow():
|
|
402
|
-
minimizeWindow():
|
|
403
|
-
fullscreenWindow():
|
|
464
|
+
getWindowRect(): RectReturn;
|
|
465
|
+
setWindowRect(x: (number|null), y: (number|null), width: (number|null), height: (number|null)): RectReturn;
|
|
466
|
+
maximizeWindow(): RectReturn;
|
|
467
|
+
minimizeWindow(): RectReturn;
|
|
468
|
+
fullscreenWindow(): RectReturn;
|
|
404
469
|
findElement(using: string, value: string): string;
|
|
405
470
|
findElements(using: string, value: string): string[];
|
|
406
|
-
findElementFromElement(using: string, value: string): string;
|
|
407
|
-
findElementsFromElement(using: string, value: string): string[];
|
|
471
|
+
findElementFromElement(elementId: string, using: string, value: string): string;
|
|
472
|
+
findElementsFromElement(elementId: string, using: string, value: string): string[];
|
|
408
473
|
getActiveElement(): string;
|
|
409
|
-
isElementSelected(): boolean;
|
|
410
|
-
isElementDisplayed(): boolean;
|
|
411
|
-
getElementAttribute(name: string): string;
|
|
412
|
-
getElementProperty(name: string): string;
|
|
413
|
-
getElementCSSValue(propertyName: string): string;
|
|
414
|
-
getElementText(): string;
|
|
415
|
-
getElementTagName(): string;
|
|
416
|
-
getElementRect():
|
|
417
|
-
isElementEnabled(): boolean;
|
|
418
|
-
elementClick(): void;
|
|
419
|
-
elementClear(): void;
|
|
420
|
-
elementSendKeys(text: string, value?: string[]): void;
|
|
474
|
+
isElementSelected(elementId: string): boolean;
|
|
475
|
+
isElementDisplayed(elementId: string): boolean;
|
|
476
|
+
getElementAttribute(elementId: string, name: string): string;
|
|
477
|
+
getElementProperty(elementId: string, name: string): string;
|
|
478
|
+
getElementCSSValue(elementId: string, propertyName: string): string;
|
|
479
|
+
getElementText(elementId: string): string;
|
|
480
|
+
getElementTagName(elementId: string): string;
|
|
481
|
+
getElementRect(elementId: string): RectReturn;
|
|
482
|
+
isElementEnabled(elementId: string): boolean;
|
|
483
|
+
elementClick(elementId: string): void;
|
|
484
|
+
elementClear(elementId: string): void;
|
|
485
|
+
elementSendKeys(elementId: string, text: string, value?: string[]): void;
|
|
421
486
|
getPageSource(): string;
|
|
422
487
|
executeScript(script: string, args?: (string|object|number|boolean|undefined)[]): any;
|
|
423
488
|
executeAsyncScript(script: string, args: (string|object|number|boolean|undefined)[]): any;
|
|
424
489
|
getAllCookies(): object[];
|
|
425
490
|
addCookie(cookie: object): void;
|
|
426
491
|
deleteAllCookies(): void;
|
|
427
|
-
getNamedCookie(name: string):
|
|
492
|
+
getNamedCookie(name: string): Cookie;
|
|
428
493
|
deleteCookie(name: string): void;
|
|
429
494
|
performActions(actions: object[]): void;
|
|
430
495
|
releaseActions(): void;
|
|
@@ -433,7 +498,7 @@ declare namespace WebDriver {
|
|
|
433
498
|
getAlertText(): string;
|
|
434
499
|
sendAlertText(text: string): void;
|
|
435
500
|
takeScreenshot(): string;
|
|
436
|
-
takeElementScreenshot(scroll?: boolean): string;
|
|
501
|
+
takeElementScreenshot(elementId: string, scroll?: boolean): string;
|
|
437
502
|
}
|
|
438
503
|
|
|
439
504
|
// appium types
|
|
@@ -479,10 +544,10 @@ declare namespace WebDriver {
|
|
|
479
544
|
reset(): void;
|
|
480
545
|
background(seconds: (number|null)): void;
|
|
481
546
|
endCoverage(intent: string, path: string): void;
|
|
482
|
-
getStrings(language?: string, stringFile?: string):
|
|
483
|
-
setValueImmediate(value: string): void;
|
|
484
|
-
replaceValue(value: string): void;
|
|
485
|
-
getSettings():
|
|
547
|
+
getStrings(language?: string, stringFile?: string): StringsReturn;
|
|
548
|
+
setValueImmediate(elementId: string, value: string): void;
|
|
549
|
+
replaceValue(elementId: string, value: string): void;
|
|
550
|
+
getSettings(): SettingsReturn;
|
|
486
551
|
updateSettings(settings: object): void;
|
|
487
552
|
receiveAsyncResponse(response: object): void;
|
|
488
553
|
gsmCall(phoneNumber: string, action: string): void;
|
|
@@ -496,14 +561,15 @@ declare namespace WebDriver {
|
|
|
496
561
|
getClipboard(contentType?: string): string;
|
|
497
562
|
touchPerform(actions: object[]): void;
|
|
498
563
|
multiTouchPerform(actions: object[]): void;
|
|
564
|
+
driverScript(script: string, type?: string, timeout?: number): ProtocolCommandResponse;
|
|
499
565
|
}
|
|
500
566
|
|
|
501
567
|
// jsonwp types
|
|
502
568
|
interface Client {
|
|
503
|
-
status():
|
|
504
|
-
newSession(desiredCapabilities: object, requiredCapabilities: object):
|
|
569
|
+
status(): StatusReturn;
|
|
570
|
+
newSession(desiredCapabilities: object, requiredCapabilities: object): SessionReturn;
|
|
505
571
|
getSessions(): object[];
|
|
506
|
-
getSession():
|
|
572
|
+
getSession(): ProtocolCommandResponse;
|
|
507
573
|
deleteSession(): void;
|
|
508
574
|
setTimeouts(type: string, ms: number): void;
|
|
509
575
|
setAsyncTimeout(ms: number): void;
|
|
@@ -520,31 +586,31 @@ declare namespace WebDriver {
|
|
|
520
586
|
switchToWindow(name: string): void;
|
|
521
587
|
switchToFrame(id: (string|number|object|null)): void;
|
|
522
588
|
switchToParentFrame(): void;
|
|
523
|
-
getWindowPosition():
|
|
524
|
-
setWindowPosition(x: number, y: number):
|
|
525
|
-
_getWindowSize():
|
|
589
|
+
getWindowPosition(): ProtocolCommandResponse;
|
|
590
|
+
setWindowPosition(x: number, y: number): ProtocolCommandResponse;
|
|
591
|
+
_getWindowSize(): ProtocolCommandResponse;
|
|
526
592
|
_setWindowSize(width: number, height: number): void;
|
|
527
593
|
maximizeWindow(): void;
|
|
528
594
|
findElement(using: string, value: string): string;
|
|
529
595
|
findElements(using: string, value: string): string[];
|
|
530
|
-
findElementFromElement(using: string, value: string): string;
|
|
531
|
-
findElementsFromElement(using: string, value: string): string[];
|
|
596
|
+
findElementFromElement(elementId: string, using: string, value: string): string;
|
|
597
|
+
findElementsFromElement(elementId: string, using: string, value: string): string[];
|
|
532
598
|
getActiveElement(): string;
|
|
533
|
-
isElementSelected(): boolean;
|
|
534
|
-
isElementDisplayed(): boolean;
|
|
535
|
-
getElementAttribute(name: string): string|null;
|
|
536
|
-
getElementCSSValue(propertyName: string): string;
|
|
537
|
-
getElementText(): string;
|
|
538
|
-
getElementTagName(): string;
|
|
539
|
-
getElementLocation():
|
|
540
|
-
getElementLocationInView():
|
|
541
|
-
getElementSize():
|
|
542
|
-
isElementEnabled(): boolean;
|
|
543
|
-
elementClick(): void;
|
|
544
|
-
elementEquals(otherElementId: string): boolean;
|
|
545
|
-
elementSubmit(): void;
|
|
546
|
-
elementClear(): void;
|
|
547
|
-
elementSendKeys(value: string[]): void;
|
|
599
|
+
isElementSelected(elementId: string): boolean;
|
|
600
|
+
isElementDisplayed(elementId: string): boolean;
|
|
601
|
+
getElementAttribute(elementId: string, name: string): string|null;
|
|
602
|
+
getElementCSSValue(elementId: string, propertyName: string): string;
|
|
603
|
+
getElementText(elementId: string): string;
|
|
604
|
+
getElementTagName(elementId: string): string;
|
|
605
|
+
getElementLocation(elementId: string): ProtocolCommandResponse;
|
|
606
|
+
getElementLocationInView(elementId: string): ProtocolCommandResponse;
|
|
607
|
+
getElementSize(elementId: string): ProtocolCommandResponse;
|
|
608
|
+
isElementEnabled(elementId: string): boolean;
|
|
609
|
+
elementClick(elementId: string): void;
|
|
610
|
+
elementEquals(elementId: string, otherElementId: string): boolean;
|
|
611
|
+
elementSubmit(elementId: string): void;
|
|
612
|
+
elementClear(elementId: string): void;
|
|
613
|
+
elementSendKeys(elementId: string, value: string[]): void;
|
|
548
614
|
sendKeys(value: string[]): void;
|
|
549
615
|
getPageSource(): string;
|
|
550
616
|
executeScript(script: string, args?: (string|object|number|boolean|undefined)[]): any;
|
|
@@ -578,7 +644,7 @@ declare namespace WebDriver {
|
|
|
578
644
|
touchDoubleClick(element: string): void;
|
|
579
645
|
touchLongClick(element: string): void;
|
|
580
646
|
touchFlick(xoffset?: number, yoffset?: number, element?: string, speed?: number, xspeed?: number, yspeed?: number): void;
|
|
581
|
-
getGeoLocation():
|
|
647
|
+
getGeoLocation(): ProtocolCommandResponse;
|
|
582
648
|
setGeoLocation(location: object): void;
|
|
583
649
|
getLocalStorage(): string[];
|
|
584
650
|
setLocalStorage(key: string, value: string): void;
|
|
@@ -616,10 +682,10 @@ declare namespace WebDriver {
|
|
|
616
682
|
isAutoReporting(): boolean;
|
|
617
683
|
setAutoReporting(enabled: boolean): object|null;
|
|
618
684
|
isLoading(): boolean;
|
|
619
|
-
takeHeapSnapshot():
|
|
685
|
+
takeHeapSnapshot(): ProtocolCommandResponse;
|
|
620
686
|
getNetworkConnection(): number;
|
|
621
687
|
setNetworkConnection(parameters: object): number;
|
|
622
|
-
getNetworkConditions():
|
|
688
|
+
getNetworkConditions(): ProtocolCommandResponse;
|
|
623
689
|
setNetworkConditions(network_conditions: object, network_name?: string): void;
|
|
624
690
|
deleteNetworkConditions(): void;
|
|
625
691
|
sendCommand(cmd: string, params: object): void;
|
|
@@ -627,18 +693,20 @@ declare namespace WebDriver {
|
|
|
627
693
|
generateTestReport(message: string, group: string): void;
|
|
628
694
|
file(file: string): string;
|
|
629
695
|
launchApp(id: string): void;
|
|
630
|
-
getElementValue(): string|null;
|
|
631
|
-
elementHover(): void;
|
|
696
|
+
getElementValue(elementId: string): string|null;
|
|
697
|
+
elementHover(elementId: string): void;
|
|
632
698
|
touchPinch(x: number, y: number, scale: number): void;
|
|
633
699
|
freeze(): void;
|
|
634
700
|
resume(): void;
|
|
635
701
|
shutdown(): void;
|
|
636
|
-
takeElementScreenshot(scroll?: boolean): string;
|
|
702
|
+
takeElementScreenshot(elementId: string, scroll?: boolean): string;
|
|
703
|
+
getLogTypes(): string[];
|
|
704
|
+
getLogs(type: string): object[];
|
|
637
705
|
}
|
|
638
706
|
|
|
639
707
|
// saucelabs types
|
|
640
708
|
interface Client {
|
|
641
|
-
getPageLogs(type: string):
|
|
709
|
+
getPageLogs(type: string): ProtocolCommandResponse;
|
|
642
710
|
throttleNetwork(condition: (string|object)): void;
|
|
643
711
|
throttleCPU(rate: number): void;
|
|
644
712
|
interceptRequest(rule: object): void;
|
|
@@ -648,9 +716,9 @@ declare namespace WebDriver {
|
|
|
648
716
|
// selenium types
|
|
649
717
|
interface Client {
|
|
650
718
|
file(file: string): string;
|
|
651
|
-
getHubConfig():
|
|
652
|
-
gridTestSession(session: string):
|
|
653
|
-
gridProxyDetails(id: string):
|
|
719
|
+
getHubConfig(): ProtocolCommandResponse;
|
|
720
|
+
gridTestSession(session: string): ProtocolCommandResponse;
|
|
721
|
+
gridProxyDetails(id: string): ProtocolCommandResponse;
|
|
654
722
|
manageSeleniumHubLifecycle(action: string): void;
|
|
655
723
|
}
|
|
656
724
|
|