selenium-webdriver 3.3.0 → 4.0.0-alpha.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/CHANGES.md +273 -0
- package/NOTICE +1 -1
- package/README.md +28 -36
- package/chrome.js +221 -146
- package/edge.js +43 -118
- package/example/chrome_android.js +8 -9
- package/example/chrome_mobile_emulation.js +9 -10
- package/example/firefox_channels.js +23 -19
- package/example/google_search.js +3 -3
- package/example/google_search_test.js +39 -27
- package/example/headless.js +55 -0
- package/example/logging.js +40 -7
- package/firefox.js +769 -0
- package/http/index.js +41 -4
- package/http/util.js +11 -6
- package/ie.js +57 -98
- package/index.js +182 -115
- package/io/index.js +59 -0
- package/io/zip.js +214 -0
- package/jasmine.json +11 -0
- package/lib/actions.js +68 -63
- package/lib/atoms/get-attribute.js +9 -0
- package/lib/atoms/is-displayed.js +73 -78
- package/lib/by.js +9 -1
- package/lib/capabilities.js +303 -201
- package/lib/command.js +28 -50
- package/lib/error.js +113 -42
- package/lib/http.js +167 -135
- package/lib/input.js +1044 -8
- package/lib/promise.js +222 -3331
- package/lib/proxy.js +134 -39
- package/lib/test/bootstrap_jasmine.js +28 -0
- package/lib/test/data/actions/click.html +24 -0
- package/lib/test/data/actions/drag.html +77 -0
- package/lib/test/data/actions/record_click.html +21 -0
- package/lib/test/data/chrome/download.html +2 -0
- package/lib/test/data/click_tests/disabled_element.html +12 -0
- package/lib/test/data/content-editable.html +10 -0
- package/lib/test/data/firefox/webextension.xpi +0 -0
- package/lib/test/data/inputs.html +42 -0
- package/lib/test/data/key_logger.html +34 -0
- package/lib/test/data/nestedElements.html +10 -1
- package/lib/test/data/scrolling_tests/page_with_partially_hidden_element.html +14 -0
- package/lib/test/data/selectPage.html +12 -0
- package/lib/test/data/simpleTest.html +5 -0
- package/lib/test/data/single_text_input.html +12 -0
- package/lib/test/data/upload_invisible.html +45 -0
- package/lib/test/fileserver.js +23 -19
- package/lib/test/index.js +30 -244
- package/lib/test/resources.js +0 -1
- package/lib/webdriver.js +770 -939
- package/net/index.js +21 -25
- package/net/portprober.js +51 -68
- package/package.json +6 -4
- package/remote/index.js +18 -30
- package/safari.js +42 -129
- package/test/actions_test.js +173 -18
- package/test/builder_test.js +106 -0
- package/test/chrome/devtools_test.js +93 -0
- package/test/chrome/options_test.js +48 -154
- package/test/chrome/service_test.js +7 -7
- package/test/cookie_test.js +77 -63
- package/test/element_finding_test.js +206 -201
- package/test/execute_script_test.js +115 -114
- package/test/fingerprint_test.js +16 -15
- package/test/firefox_test.js +251 -0
- package/test/http/http_test.js +18 -1
- package/test/http/util_test.js +2 -2
- package/test/{io_test.js → io/io_test.js} +40 -1
- package/test/io/zip_test.js +127 -0
- package/test/lib/by_test.js +21 -0
- package/test/lib/error_test.js +55 -8
- package/test/lib/http_test.js +18 -130
- package/test/lib/input_test.js +1379 -0
- package/test/lib/promise_test.js +473 -908
- package/test/lib/webdriver_test.js +357 -825
- package/test/logging_test.js +37 -43
- package/test/page_loading_test.js +70 -86
- package/test/proxy_test.js +64 -72
- package/test/rect_test.js +14 -25
- package/test/remote_test.js +13 -32
- package/test/safari_test.js +7 -71
- package/test/stale_element_test.js +20 -23
- package/test/tag_name_test.js +10 -9
- package/test/upload_test.js +27 -35
- package/test/window_test.js +72 -85
- package/testing/index.js +386 -315
- package/.npmignore +0 -2
- package/example/async_await_test.js +0 -68
- package/example/google_search_generator.js +0 -50
- package/example/parallel_flows.js +0 -54
- package/firefox/binary.js +0 -344
- package/firefox/extension.js +0 -187
- package/firefox/index.js +0 -722
- package/firefox/profile.js +0 -430
- package/lib/atoms/getAttribute.js +0 -12
- package/lib/events.js +0 -210
- package/lib/firefox/webdriver.json +0 -70
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/test/data/firefox/jetpack-sample.xpi +0 -0
- package/lib/test/data/firefox/sample.xpi +0 -0
- package/lib/test/promise.js +0 -79
- package/opera.js +0 -405
- package/phantomjs.js +0 -282
- package/test/firefox/extension_test.js +0 -96
- package/test/firefox/firefox_test.js +0 -226
- package/test/firefox/profile_test.js +0 -185
- package/test/lib/events_test.js +0 -177
- package/test/lib/promise_aplus_test.js +0 -78
- package/test/lib/promise_error_test.js +0 -884
- package/test/lib/promise_flow_test.js +0 -2288
- package/test/lib/promise_generator_test.js +0 -310
- package/test/phantomjs/execute_phantomjs_test.js +0 -59
- package/test/session_test.js +0 -54
- package/test/testing/assert_test.js +0 -373
- package/test/testing/index_test.js +0 -224
- package/testing/assert.js +0 -378
|
@@ -0,0 +1,1379 @@
|
|
|
1
|
+
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
2
|
+
// or more contributor license agreements. See the NOTICE file
|
|
3
|
+
// distributed with this work for additional information
|
|
4
|
+
// regarding copyright ownership. The SFC licenses this file
|
|
5
|
+
// to you under the Apache License, Version 2.0 (the
|
|
6
|
+
// "License"); you may not use this file except in compliance
|
|
7
|
+
// with the License. You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing,
|
|
12
|
+
// software distributed under the License is distributed on an
|
|
13
|
+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
// KIND, either express or implied. See the License for the
|
|
15
|
+
// specific language governing permissions and limitations
|
|
16
|
+
// under the License.
|
|
17
|
+
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
const assert = require('assert');
|
|
21
|
+
const sinon = require('sinon');
|
|
22
|
+
|
|
23
|
+
const command = require('../../lib/command');
|
|
24
|
+
const error = require('../../lib/error');
|
|
25
|
+
const input = require('../../lib/input');
|
|
26
|
+
const {WebElement} = require('../../lib/webdriver');
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
describe('input.Actions', function() {
|
|
30
|
+
class StubExecutor {
|
|
31
|
+
constructor(...responses) {
|
|
32
|
+
this.responses = responses;
|
|
33
|
+
this.commands = [];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
execute(command) {
|
|
37
|
+
const name = command.getName();
|
|
38
|
+
const parameters = command.getParameters();
|
|
39
|
+
this.commands.push({name, parameters});
|
|
40
|
+
return this.responses.shift()
|
|
41
|
+
|| Promise.reject(
|
|
42
|
+
new Error('unexpected command: ' + command.getName()));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe('perform()', function() {
|
|
47
|
+
it('omits idle devices', async function() {
|
|
48
|
+
let executor = new StubExecutor(
|
|
49
|
+
Promise.resolve(),
|
|
50
|
+
Promise.resolve(),
|
|
51
|
+
Promise.resolve(),
|
|
52
|
+
Promise.resolve());
|
|
53
|
+
|
|
54
|
+
await new input.Actions(executor).perform();
|
|
55
|
+
assert.deepEqual(executor.commands, []);
|
|
56
|
+
|
|
57
|
+
await new input.Actions(executor).pause().perform();
|
|
58
|
+
assert.deepEqual(executor.commands, []);
|
|
59
|
+
|
|
60
|
+
await new input.Actions(executor).pause(1).perform();
|
|
61
|
+
assert.deepEqual(executor.commands, [{
|
|
62
|
+
name: command.Name.ACTIONS,
|
|
63
|
+
parameters: {
|
|
64
|
+
actions: [
|
|
65
|
+
{
|
|
66
|
+
id: 'default keyboard',
|
|
67
|
+
type: 'key',
|
|
68
|
+
actions: [{type: 'pause', duration: 1}],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'default mouse',
|
|
72
|
+
type: 'pointer',
|
|
73
|
+
parameters: {pointerType: 'mouse'},
|
|
74
|
+
actions: [{type: 'pause', duration: 1}],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
}
|
|
78
|
+
}]);
|
|
79
|
+
|
|
80
|
+
executor.commands.length = 0;
|
|
81
|
+
let actions = new input.Actions(executor);
|
|
82
|
+
await actions.pause(1, actions.keyboard()).perform();
|
|
83
|
+
assert.deepEqual(executor.commands, [{
|
|
84
|
+
name: command.Name.ACTIONS,
|
|
85
|
+
parameters: {
|
|
86
|
+
actions: [{
|
|
87
|
+
id: 'default keyboard',
|
|
88
|
+
type: 'key',
|
|
89
|
+
actions: [{type: 'pause', duration: 1}],
|
|
90
|
+
}],
|
|
91
|
+
}
|
|
92
|
+
}]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('can be called multiple times', async function() {
|
|
96
|
+
const executor = new StubExecutor(Promise.resolve(), Promise.resolve());
|
|
97
|
+
const actions = new input.Actions(executor).keyDown(input.Key.SHIFT);
|
|
98
|
+
|
|
99
|
+
const expected = {
|
|
100
|
+
name: command.Name.ACTIONS,
|
|
101
|
+
parameters: {
|
|
102
|
+
actions: [{
|
|
103
|
+
id: 'default keyboard',
|
|
104
|
+
type: 'key',
|
|
105
|
+
actions: [{type: 'keyDown', value: input.Key.SHIFT}],
|
|
106
|
+
}]}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
await actions.perform();
|
|
110
|
+
assert.deepEqual(executor.commands, [expected]);
|
|
111
|
+
|
|
112
|
+
await actions.perform();
|
|
113
|
+
assert.deepEqual(executor.commands, [expected, expected]);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('pause()', function() {
|
|
118
|
+
it('defaults to all devices', async function() {
|
|
119
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
120
|
+
|
|
121
|
+
await new input.Actions(executor).pause(3).perform();
|
|
122
|
+
|
|
123
|
+
assert.deepEqual(executor.commands, [{
|
|
124
|
+
name: command.Name.ACTIONS,
|
|
125
|
+
parameters: {
|
|
126
|
+
actions: [
|
|
127
|
+
{
|
|
128
|
+
id: 'default keyboard',
|
|
129
|
+
type: 'key',
|
|
130
|
+
actions: [{type: 'pause', duration: 3}],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 'default mouse',
|
|
134
|
+
type: 'pointer',
|
|
135
|
+
parameters: {pointerType: 'mouse'},
|
|
136
|
+
actions: [{type: 'pause', duration: 3}],
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
}
|
|
140
|
+
}]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('duration defaults to 0', async function() {
|
|
144
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
145
|
+
|
|
146
|
+
await new input.Actions(executor)
|
|
147
|
+
.pause()
|
|
148
|
+
.pause(3)
|
|
149
|
+
.perform();
|
|
150
|
+
|
|
151
|
+
assert.deepEqual(executor.commands, [{
|
|
152
|
+
name: command.Name.ACTIONS,
|
|
153
|
+
parameters: {
|
|
154
|
+
actions: [
|
|
155
|
+
{
|
|
156
|
+
id: 'default keyboard',
|
|
157
|
+
type: 'key',
|
|
158
|
+
actions: [
|
|
159
|
+
{type: 'pause', duration: 0},
|
|
160
|
+
{type: 'pause', duration: 3},
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'default mouse',
|
|
165
|
+
type: 'pointer',
|
|
166
|
+
parameters: {pointerType: 'mouse'},
|
|
167
|
+
actions: [
|
|
168
|
+
{type: 'pause', duration: 0},
|
|
169
|
+
{type: 'pause', duration: 3},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
}
|
|
174
|
+
}]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('single device w/ synchronization', async function() {
|
|
178
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
179
|
+
const actions = new input.Actions(executor);
|
|
180
|
+
|
|
181
|
+
await actions
|
|
182
|
+
.pause(100, actions.keyboard())
|
|
183
|
+
.pause(100, actions.mouse())
|
|
184
|
+
.perform();
|
|
185
|
+
|
|
186
|
+
assert.deepEqual(executor.commands, [{
|
|
187
|
+
name: command.Name.ACTIONS,
|
|
188
|
+
parameters: {
|
|
189
|
+
actions: [
|
|
190
|
+
{
|
|
191
|
+
id: 'default keyboard',
|
|
192
|
+
type: 'key',
|
|
193
|
+
actions: [
|
|
194
|
+
{type: 'pause', duration: 100},
|
|
195
|
+
{type: 'pause', duration: 0},
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 'default mouse',
|
|
200
|
+
type: 'pointer',
|
|
201
|
+
parameters: {pointerType: 'mouse'},
|
|
202
|
+
actions: [
|
|
203
|
+
{type: 'pause', duration: 0},
|
|
204
|
+
{type: 'pause', duration: 100},
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
}
|
|
209
|
+
}]);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('single device w/o synchronization', async function() {
|
|
213
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
214
|
+
const actions = new input.Actions(executor, {async: true});
|
|
215
|
+
|
|
216
|
+
await actions
|
|
217
|
+
.pause(100, actions.keyboard())
|
|
218
|
+
.pause(100, actions.mouse())
|
|
219
|
+
.perform();
|
|
220
|
+
|
|
221
|
+
assert.deepEqual(executor.commands, [{
|
|
222
|
+
name: command.Name.ACTIONS,
|
|
223
|
+
parameters: {
|
|
224
|
+
actions: [
|
|
225
|
+
{
|
|
226
|
+
id: 'default keyboard',
|
|
227
|
+
type: 'key',
|
|
228
|
+
actions: [
|
|
229
|
+
{type: 'pause', duration: 100},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: 'default mouse',
|
|
234
|
+
type: 'pointer',
|
|
235
|
+
parameters: {pointerType: 'mouse'},
|
|
236
|
+
actions: [
|
|
237
|
+
{type: 'pause', duration: 100},
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
}
|
|
242
|
+
}]);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('pause a single device multiple times by specifying it multiple times',
|
|
246
|
+
async function() {
|
|
247
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
248
|
+
const actions = new input.Actions(executor);
|
|
249
|
+
|
|
250
|
+
await actions
|
|
251
|
+
.pause(100, actions.keyboard(), actions.keyboard())
|
|
252
|
+
.perform();
|
|
253
|
+
|
|
254
|
+
assert.deepEqual(executor.commands, [{
|
|
255
|
+
name: command.Name.ACTIONS,
|
|
256
|
+
parameters: {
|
|
257
|
+
actions: [{
|
|
258
|
+
id: 'default keyboard',
|
|
259
|
+
type: 'key',
|
|
260
|
+
actions: [
|
|
261
|
+
{type: 'pause', duration: 100},
|
|
262
|
+
{type: 'pause', duration: 100},
|
|
263
|
+
],
|
|
264
|
+
}],
|
|
265
|
+
}
|
|
266
|
+
}]);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('keyDown()', function() {
|
|
271
|
+
it('sends normalized code point', async function() {
|
|
272
|
+
let executor = new StubExecutor(Promise.resolve());
|
|
273
|
+
|
|
274
|
+
await new input.Actions(executor).keyDown('\u0041\u030a').perform();
|
|
275
|
+
assert.deepEqual(executor.commands, [{
|
|
276
|
+
name: command.Name.ACTIONS,
|
|
277
|
+
parameters: {
|
|
278
|
+
actions: [{
|
|
279
|
+
id: 'default keyboard',
|
|
280
|
+
type: 'key',
|
|
281
|
+
actions: [{type: 'keyDown', value: '\u00c5'}],
|
|
282
|
+
}],
|
|
283
|
+
}
|
|
284
|
+
}]);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('rejects keys that are not a single code point', function() {
|
|
288
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
289
|
+
const actions = new input.Actions(executor);
|
|
290
|
+
assert.throws(
|
|
291
|
+
() => actions.keyDown('\u1E9B\u0323'),
|
|
292
|
+
error.InvalidArgumentError);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe('keyUp()', function() {
|
|
297
|
+
it('sends normalized code point', async function() {
|
|
298
|
+
let executor = new StubExecutor(Promise.resolve());
|
|
299
|
+
|
|
300
|
+
await new input.Actions(executor).keyUp('\u0041\u030a').perform();
|
|
301
|
+
assert.deepEqual(executor.commands, [{
|
|
302
|
+
name: command.Name.ACTIONS,
|
|
303
|
+
parameters: {
|
|
304
|
+
actions: [{
|
|
305
|
+
id: 'default keyboard',
|
|
306
|
+
type: 'key',
|
|
307
|
+
actions: [{type: 'keyUp', value: '\u00c5'}],
|
|
308
|
+
}],
|
|
309
|
+
}
|
|
310
|
+
}]);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('rejects keys that are not a single code point', function() {
|
|
314
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
315
|
+
const actions = new input.Actions(executor);
|
|
316
|
+
assert.throws(
|
|
317
|
+
() => actions.keyUp('\u1E9B\u0323'),
|
|
318
|
+
error.InvalidArgumentError);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
describe('sendKeys()', function() {
|
|
323
|
+
it('sends down/up for single key', async function() {
|
|
324
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
325
|
+
const actions = new input.Actions(executor);
|
|
326
|
+
|
|
327
|
+
await actions.sendKeys('a').perform();
|
|
328
|
+
assert.deepEqual(executor.commands, [{
|
|
329
|
+
name: command.Name.ACTIONS,
|
|
330
|
+
parameters: {
|
|
331
|
+
actions: [{
|
|
332
|
+
id: 'default keyboard',
|
|
333
|
+
type: 'key',
|
|
334
|
+
actions: [
|
|
335
|
+
{type: 'keyDown', value: 'a'},
|
|
336
|
+
{type: 'keyUp', value: 'a'},
|
|
337
|
+
],
|
|
338
|
+
}],
|
|
339
|
+
}
|
|
340
|
+
}]);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('sends down/up for vararg keys', async function() {
|
|
344
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
345
|
+
const actions = new input.Actions(executor);
|
|
346
|
+
|
|
347
|
+
await actions.sendKeys('a', 'b').perform();
|
|
348
|
+
assert.deepEqual(executor.commands, [{
|
|
349
|
+
name: command.Name.ACTIONS,
|
|
350
|
+
parameters: {
|
|
351
|
+
actions: [{
|
|
352
|
+
id: 'default keyboard',
|
|
353
|
+
type: 'key',
|
|
354
|
+
actions: [
|
|
355
|
+
{type: 'keyDown', value: 'a'},
|
|
356
|
+
{type: 'keyUp', value: 'a'},
|
|
357
|
+
{type: 'keyDown', value: 'b'},
|
|
358
|
+
{type: 'keyUp', value: 'b'},
|
|
359
|
+
],
|
|
360
|
+
}],
|
|
361
|
+
}
|
|
362
|
+
}]);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('sends down/up for multichar strings in varargs', async function() {
|
|
366
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
367
|
+
const actions = new input.Actions(executor);
|
|
368
|
+
|
|
369
|
+
await actions.sendKeys('a', 'bc', 'd').perform();
|
|
370
|
+
assert.deepEqual(executor.commands, [{
|
|
371
|
+
name: command.Name.ACTIONS,
|
|
372
|
+
parameters: {
|
|
373
|
+
actions: [{
|
|
374
|
+
id: 'default keyboard',
|
|
375
|
+
type: 'key',
|
|
376
|
+
actions: [
|
|
377
|
+
{type: 'keyDown', value: 'a'},
|
|
378
|
+
{type: 'keyUp', value: 'a'},
|
|
379
|
+
{type: 'keyDown', value: 'b'},
|
|
380
|
+
{type: 'keyUp', value: 'b'},
|
|
381
|
+
{type: 'keyDown', value: 'c'},
|
|
382
|
+
{type: 'keyUp', value: 'c'},
|
|
383
|
+
{type: 'keyDown', value: 'd'},
|
|
384
|
+
{type: 'keyUp', value: 'd'},
|
|
385
|
+
],
|
|
386
|
+
}],
|
|
387
|
+
}
|
|
388
|
+
}]);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('synchronizes with other devices', async function() {
|
|
392
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
393
|
+
const actions = new input.Actions(executor);
|
|
394
|
+
|
|
395
|
+
await actions.sendKeys('ab').pause(100, actions.mouse()).perform();
|
|
396
|
+
assert.deepEqual(executor.commands, [{
|
|
397
|
+
name: command.Name.ACTIONS,
|
|
398
|
+
parameters: {
|
|
399
|
+
actions: [
|
|
400
|
+
{
|
|
401
|
+
id: 'default keyboard',
|
|
402
|
+
type: 'key',
|
|
403
|
+
actions: [
|
|
404
|
+
{type: 'keyDown', value: 'a'},
|
|
405
|
+
{type: 'keyUp', value: 'a'},
|
|
406
|
+
{type: 'keyDown', value: 'b'},
|
|
407
|
+
{type: 'keyUp', value: 'b'},
|
|
408
|
+
{type: 'pause', duration: 0},
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'default mouse',
|
|
413
|
+
type: 'pointer',
|
|
414
|
+
parameters: {pointerType: 'mouse'},
|
|
415
|
+
actions: [
|
|
416
|
+
{type: 'pause', duration: 0},
|
|
417
|
+
{type: 'pause', duration: 0},
|
|
418
|
+
{type: 'pause', duration: 0},
|
|
419
|
+
{type: 'pause', duration: 0},
|
|
420
|
+
{type: 'pause', duration: 100},
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
],
|
|
424
|
+
}
|
|
425
|
+
}]);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('without device synchronization', async function() {
|
|
429
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
430
|
+
const actions = new input.Actions(executor, {async: true});
|
|
431
|
+
|
|
432
|
+
await actions.sendKeys('ab').pause(100, actions.mouse()).perform();
|
|
433
|
+
assert.deepEqual(executor.commands, [{
|
|
434
|
+
name: command.Name.ACTIONS,
|
|
435
|
+
parameters: {
|
|
436
|
+
actions: [
|
|
437
|
+
{
|
|
438
|
+
id: 'default keyboard',
|
|
439
|
+
type: 'key',
|
|
440
|
+
actions: [
|
|
441
|
+
{type: 'keyDown', value: 'a'},
|
|
442
|
+
{type: 'keyUp', value: 'a'},
|
|
443
|
+
{type: 'keyDown', value: 'b'},
|
|
444
|
+
{type: 'keyUp', value: 'b'},
|
|
445
|
+
],
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
id: 'default mouse',
|
|
449
|
+
type: 'pointer',
|
|
450
|
+
parameters: {pointerType: 'mouse'},
|
|
451
|
+
actions: [{type: 'pause', duration: 100}],
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
}
|
|
455
|
+
}]);
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
describe('click()', function() {
|
|
460
|
+
it('clicks immediately if no element provided', async function() {
|
|
461
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
462
|
+
const actions = new input.Actions(executor);
|
|
463
|
+
|
|
464
|
+
await actions.click().perform();
|
|
465
|
+
assert.deepEqual(executor.commands, [{
|
|
466
|
+
name: command.Name.ACTIONS,
|
|
467
|
+
parameters: {
|
|
468
|
+
actions: [{
|
|
469
|
+
id: 'default mouse',
|
|
470
|
+
type: 'pointer',
|
|
471
|
+
parameters: {pointerType: 'mouse'},
|
|
472
|
+
actions: [
|
|
473
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
474
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
475
|
+
],
|
|
476
|
+
}],
|
|
477
|
+
},
|
|
478
|
+
}]);
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it('moves to target element before clicking', async function() {
|
|
482
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
483
|
+
const actions = new input.Actions(executor);
|
|
484
|
+
|
|
485
|
+
const fakeElement = {};
|
|
486
|
+
|
|
487
|
+
await actions.click(fakeElement).perform();
|
|
488
|
+
assert.deepEqual(executor.commands, [{
|
|
489
|
+
name: command.Name.ACTIONS,
|
|
490
|
+
parameters: {
|
|
491
|
+
actions: [{
|
|
492
|
+
id: 'default mouse',
|
|
493
|
+
type: 'pointer',
|
|
494
|
+
parameters: {pointerType: 'mouse'},
|
|
495
|
+
actions: [
|
|
496
|
+
{
|
|
497
|
+
type: 'pointerMove',
|
|
498
|
+
origin: fakeElement,
|
|
499
|
+
duration: 100,
|
|
500
|
+
x: 0,
|
|
501
|
+
y: 0,
|
|
502
|
+
},
|
|
503
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
504
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
505
|
+
],
|
|
506
|
+
}],
|
|
507
|
+
},
|
|
508
|
+
}]);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('synchronizes with other devices', async function() {
|
|
512
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
513
|
+
const actions = new input.Actions(executor);
|
|
514
|
+
|
|
515
|
+
const fakeElement = {};
|
|
516
|
+
|
|
517
|
+
await actions.click(fakeElement).sendKeys('a').perform();
|
|
518
|
+
assert.deepEqual(executor.commands, [{
|
|
519
|
+
name: command.Name.ACTIONS,
|
|
520
|
+
parameters: {
|
|
521
|
+
actions: [{
|
|
522
|
+
id: 'default keyboard',
|
|
523
|
+
type: 'key',
|
|
524
|
+
actions: [
|
|
525
|
+
{type: 'pause', duration: 0},
|
|
526
|
+
{type: 'pause', duration: 0},
|
|
527
|
+
{type: 'pause', duration: 0},
|
|
528
|
+
{type: 'keyDown', value: 'a'},
|
|
529
|
+
{type: 'keyUp', value: 'a'},
|
|
530
|
+
],
|
|
531
|
+
}, {
|
|
532
|
+
id: 'default mouse',
|
|
533
|
+
type: 'pointer',
|
|
534
|
+
parameters: {pointerType: 'mouse'},
|
|
535
|
+
actions: [
|
|
536
|
+
{
|
|
537
|
+
type: 'pointerMove',
|
|
538
|
+
origin: fakeElement,
|
|
539
|
+
duration: 100,
|
|
540
|
+
x: 0,
|
|
541
|
+
y: 0,
|
|
542
|
+
},
|
|
543
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
544
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
545
|
+
{type: 'pause', duration: 0},
|
|
546
|
+
{type: 'pause', duration: 0},
|
|
547
|
+
],
|
|
548
|
+
}],
|
|
549
|
+
},
|
|
550
|
+
}]);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
describe('dragAndDrop', function() {
|
|
555
|
+
it('dragAndDrop(fromEl, toEl)', async function() {
|
|
556
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
557
|
+
const actions = new input.Actions(executor);
|
|
558
|
+
const e1 = new WebElement(null, 'abc123');
|
|
559
|
+
const e2 = new WebElement(null, 'def456');
|
|
560
|
+
|
|
561
|
+
await actions.dragAndDrop(e1, e2).perform();
|
|
562
|
+
|
|
563
|
+
assert.deepEqual(executor.commands, [{
|
|
564
|
+
name: command.Name.ACTIONS,
|
|
565
|
+
parameters: {
|
|
566
|
+
actions: [{
|
|
567
|
+
id: 'default mouse',
|
|
568
|
+
type: 'pointer',
|
|
569
|
+
parameters: {pointerType: 'mouse'},
|
|
570
|
+
actions: [
|
|
571
|
+
{
|
|
572
|
+
type: 'pointerMove',
|
|
573
|
+
duration: 100,
|
|
574
|
+
origin: e1,
|
|
575
|
+
x: 0,
|
|
576
|
+
y: 0,
|
|
577
|
+
},
|
|
578
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
579
|
+
{
|
|
580
|
+
type: 'pointerMove',
|
|
581
|
+
duration: 100,
|
|
582
|
+
origin: e2,
|
|
583
|
+
x: 0,
|
|
584
|
+
y: 0,
|
|
585
|
+
},
|
|
586
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
587
|
+
],
|
|
588
|
+
}],
|
|
589
|
+
}
|
|
590
|
+
}]);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('dragAndDrop(el, offset)', async function() {
|
|
594
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
595
|
+
const actions = new input.Actions(executor);
|
|
596
|
+
const e1 = new WebElement(null, 'abc123');
|
|
597
|
+
|
|
598
|
+
await actions.dragAndDrop(e1, {x: 30, y: 40}).perform();
|
|
599
|
+
|
|
600
|
+
assert.deepEqual(executor.commands, [{
|
|
601
|
+
name: command.Name.ACTIONS,
|
|
602
|
+
parameters: {
|
|
603
|
+
actions: [{
|
|
604
|
+
id: 'default mouse',
|
|
605
|
+
type: 'pointer',
|
|
606
|
+
parameters: {pointerType: 'mouse'},
|
|
607
|
+
actions: [
|
|
608
|
+
{
|
|
609
|
+
type: 'pointerMove',
|
|
610
|
+
duration: 100,
|
|
611
|
+
origin: e1,
|
|
612
|
+
x: 0,
|
|
613
|
+
y: 0,
|
|
614
|
+
},
|
|
615
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
616
|
+
{
|
|
617
|
+
type: 'pointerMove',
|
|
618
|
+
duration: 100,
|
|
619
|
+
origin: input.Origin.POINTER,
|
|
620
|
+
x: 30,
|
|
621
|
+
y: 40,
|
|
622
|
+
},
|
|
623
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
624
|
+
],
|
|
625
|
+
}],
|
|
626
|
+
}
|
|
627
|
+
}]);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('throws if target is invalid', async function() {
|
|
631
|
+
const executor = new StubExecutor(Promise.resolve());
|
|
632
|
+
const actions = new input.Actions(executor);
|
|
633
|
+
const e = new WebElement(null, 'abc123');
|
|
634
|
+
|
|
635
|
+
assert.throws(
|
|
636
|
+
() => actions.dragAndDrop(e),
|
|
637
|
+
error.InvalidArgumentError);
|
|
638
|
+
assert.throws(
|
|
639
|
+
() => actions.dragAndDrop(e, null),
|
|
640
|
+
error.InvalidArgumentError);
|
|
641
|
+
assert.throws(
|
|
642
|
+
() => actions.dragAndDrop(e, {}),
|
|
643
|
+
error.InvalidArgumentError);
|
|
644
|
+
assert.throws(
|
|
645
|
+
() => actions.dragAndDrop(e, {x:0}),
|
|
646
|
+
error.InvalidArgumentError);
|
|
647
|
+
assert.throws(
|
|
648
|
+
() => actions.dragAndDrop(e, {y:0}),
|
|
649
|
+
error.InvalidArgumentError);
|
|
650
|
+
assert.throws(
|
|
651
|
+
() => actions.dragAndDrop(e, {x:0, y:'a'}),
|
|
652
|
+
error.InvalidArgumentError);
|
|
653
|
+
assert.throws(
|
|
654
|
+
() => actions.dragAndDrop(e, {x:'a', y:0}),
|
|
655
|
+
error.InvalidArgumentError);
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
describe('bridge mode', function() {
|
|
660
|
+
it('cannot enable async and bridge at the same time', function() {
|
|
661
|
+
let exe = new StubExecutor;
|
|
662
|
+
assert.throws(
|
|
663
|
+
() => new input.Actions(exe, {async: true, bridge: true}),
|
|
664
|
+
error.InvalidArgumentError);
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it('behaves as normal if first command succeeds', async function() {
|
|
668
|
+
const actions = new input.Actions(new StubExecutor(Promise.resolve()));
|
|
669
|
+
await actions.click().sendKeys('a').perform();
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
it('handles pauses locally', async function() {
|
|
673
|
+
const start = Date.now();
|
|
674
|
+
const actions =
|
|
675
|
+
new input.Actions(
|
|
676
|
+
new StubExecutor(
|
|
677
|
+
Promise.reject(new error.UnknownCommandError)),
|
|
678
|
+
{bridge: true});
|
|
679
|
+
|
|
680
|
+
await actions.pause(100).perform();
|
|
681
|
+
|
|
682
|
+
const elapsed = Date.now() - start;
|
|
683
|
+
assert.ok(elapsed > 100, elapsed);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
it('requires non-modifier keys to be used in keydown/up sequences', async function() {
|
|
687
|
+
const actions =
|
|
688
|
+
new input.Actions(
|
|
689
|
+
new StubExecutor(
|
|
690
|
+
Promise.reject(new error.UnknownCommandError)),
|
|
691
|
+
{bridge: true});
|
|
692
|
+
|
|
693
|
+
try {
|
|
694
|
+
await actions.keyDown(input.Key.SHIFT).keyDown('a').perform();
|
|
695
|
+
return Promise.reject(Error('should have failed!'));
|
|
696
|
+
} catch (err) {
|
|
697
|
+
if (!(err instanceof error.UnsupportedOperationError)
|
|
698
|
+
|| !err.message.endsWith('must be followed by a keyup for the same key')) {
|
|
699
|
+
throw err;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
it('key sequence', async function() {
|
|
705
|
+
const executor =
|
|
706
|
+
new StubExecutor(
|
|
707
|
+
Promise.reject(new error.UnknownCommandError),
|
|
708
|
+
Promise.resolve('shift down'),
|
|
709
|
+
Promise.resolve(),
|
|
710
|
+
Promise.resolve(),
|
|
711
|
+
Promise.resolve(),
|
|
712
|
+
Promise.resolve('shift up'));
|
|
713
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
714
|
+
|
|
715
|
+
await actions
|
|
716
|
+
.keyDown(input.Key.SHIFT)
|
|
717
|
+
.sendKeys('abc')
|
|
718
|
+
.keyUp(input.Key.SHIFT)
|
|
719
|
+
.sendKeys('de')
|
|
720
|
+
.perform();
|
|
721
|
+
|
|
722
|
+
assert.deepEqual(executor.commands, [
|
|
723
|
+
{
|
|
724
|
+
name: command.Name.ACTIONS,
|
|
725
|
+
parameters: {
|
|
726
|
+
actions: [{
|
|
727
|
+
id: 'default keyboard',
|
|
728
|
+
type: 'key',
|
|
729
|
+
actions: [
|
|
730
|
+
{type: 'keyDown', value: input.Key.SHIFT},
|
|
731
|
+
{type: 'keyDown', value: 'a'},
|
|
732
|
+
{type: 'keyUp', value: 'a'},
|
|
733
|
+
{type: 'keyDown', value: 'b'},
|
|
734
|
+
{type: 'keyUp', value: 'b'},
|
|
735
|
+
{type: 'keyDown', value: 'c'},
|
|
736
|
+
{type: 'keyUp', value: 'c'},
|
|
737
|
+
{type: 'keyUp', value: input.Key.SHIFT},
|
|
738
|
+
{type: 'keyDown', value: 'd'},
|
|
739
|
+
{type: 'keyUp', value: 'd'},
|
|
740
|
+
{type: 'keyDown', value: 'e'},
|
|
741
|
+
{type: 'keyUp', value: 'e'},
|
|
742
|
+
],
|
|
743
|
+
}],
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
name: command.Name.LEGACY_ACTION_SEND_KEYS,
|
|
748
|
+
parameters: {value: [input.Key.SHIFT]}
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
name: command.Name.LEGACY_ACTION_SEND_KEYS,
|
|
752
|
+
parameters: {value: ['a', 'b', 'c']}
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
name: command.Name.LEGACY_ACTION_SEND_KEYS,
|
|
756
|
+
parameters: {value: [input.Key.SHIFT]}
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
name: command.Name.LEGACY_ACTION_SEND_KEYS,
|
|
760
|
+
parameters: {value: ['d', 'e']}
|
|
761
|
+
},
|
|
762
|
+
]);
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
it('mouse movements cannot be relative to the viewport', async function() {
|
|
766
|
+
const actions =
|
|
767
|
+
new input.Actions(
|
|
768
|
+
new StubExecutor(
|
|
769
|
+
Promise.reject(new error.UnknownCommandError)),
|
|
770
|
+
{bridge: true});
|
|
771
|
+
|
|
772
|
+
try {
|
|
773
|
+
await actions.move({x: 10, y: 15}).perform();
|
|
774
|
+
return Promise.reject(Error('should have failed!'));
|
|
775
|
+
} catch (err) {
|
|
776
|
+
if (!(err instanceof error.UnsupportedOperationError)
|
|
777
|
+
|| !err.message.startsWith('pointer movements relative to viewport')) {
|
|
778
|
+
throw err;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
describe('detects clicks', function() {
|
|
784
|
+
it('press/release for same button is a click', async function() {
|
|
785
|
+
const executor =
|
|
786
|
+
new StubExecutor(
|
|
787
|
+
Promise.reject(new error.UnknownCommandError),
|
|
788
|
+
Promise.resolve());
|
|
789
|
+
|
|
790
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
791
|
+
const element = new WebElement(null, 'abc123');
|
|
792
|
+
|
|
793
|
+
await actions
|
|
794
|
+
.press(input.Button.LEFT)
|
|
795
|
+
.release(input.Button.LEFT)
|
|
796
|
+
.perform();
|
|
797
|
+
|
|
798
|
+
assert.deepEqual(executor.commands, [
|
|
799
|
+
{
|
|
800
|
+
name: command.Name.ACTIONS,
|
|
801
|
+
parameters: {
|
|
802
|
+
actions: [{
|
|
803
|
+
id: 'default mouse',
|
|
804
|
+
type: 'pointer',
|
|
805
|
+
parameters: {pointerType: 'mouse'},
|
|
806
|
+
actions: [
|
|
807
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
808
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
809
|
+
],
|
|
810
|
+
}],
|
|
811
|
+
}
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
815
|
+
parameters: {button: input.Button.LEFT},
|
|
816
|
+
},
|
|
817
|
+
]);
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
it('not a click if release is a different button', async function() {
|
|
821
|
+
const executor =
|
|
822
|
+
new StubExecutor(
|
|
823
|
+
Promise.reject(new error.UnknownCommandError),
|
|
824
|
+
Promise.resolve(),
|
|
825
|
+
Promise.resolve(),
|
|
826
|
+
Promise.resolve(),
|
|
827
|
+
Promise.resolve());
|
|
828
|
+
|
|
829
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
830
|
+
const element = new WebElement(null, 'abc123');
|
|
831
|
+
|
|
832
|
+
await actions
|
|
833
|
+
.press(input.Button.LEFT)
|
|
834
|
+
.press(input.Button.RIGHT)
|
|
835
|
+
.release(input.Button.LEFT)
|
|
836
|
+
.release(input.Button.RIGHT)
|
|
837
|
+
.perform();
|
|
838
|
+
|
|
839
|
+
assert.deepEqual(executor.commands, [
|
|
840
|
+
{
|
|
841
|
+
name: command.Name.ACTIONS,
|
|
842
|
+
parameters: {
|
|
843
|
+
actions: [{
|
|
844
|
+
id: 'default mouse',
|
|
845
|
+
type: 'pointer',
|
|
846
|
+
parameters: {pointerType: 'mouse'},
|
|
847
|
+
actions: [
|
|
848
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
849
|
+
{type: 'pointerDown', button: input.Button.RIGHT},
|
|
850
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
851
|
+
{type: 'pointerUp', button: input.Button.RIGHT},
|
|
852
|
+
],
|
|
853
|
+
}],
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
name: command.Name.LEGACY_ACTION_MOUSE_DOWN,
|
|
858
|
+
parameters: {button: input.Button.LEFT},
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
name: command.Name.LEGACY_ACTION_MOUSE_DOWN,
|
|
862
|
+
parameters: {button: input.Button.RIGHT},
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
name: command.Name.LEGACY_ACTION_MOUSE_UP,
|
|
866
|
+
parameters: {button: input.Button.LEFT},
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
name: command.Name.LEGACY_ACTION_MOUSE_UP,
|
|
870
|
+
parameters: {button: input.Button.RIGHT},
|
|
871
|
+
},
|
|
872
|
+
]);
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
it('click() shortcut', async function() {
|
|
876
|
+
const executor =
|
|
877
|
+
new StubExecutor(
|
|
878
|
+
Promise.reject(new error.UnknownCommandError),
|
|
879
|
+
Promise.resolve());
|
|
880
|
+
|
|
881
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
882
|
+
const element = new WebElement(null, 'abc123');
|
|
883
|
+
|
|
884
|
+
await actions.click().perform();
|
|
885
|
+
|
|
886
|
+
assert.deepEqual(executor.commands, [
|
|
887
|
+
{
|
|
888
|
+
name: command.Name.ACTIONS,
|
|
889
|
+
parameters: {
|
|
890
|
+
actions: [{
|
|
891
|
+
id: 'default mouse',
|
|
892
|
+
type: 'pointer',
|
|
893
|
+
parameters: {pointerType: 'mouse'},
|
|
894
|
+
actions: [
|
|
895
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
896
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
897
|
+
],
|
|
898
|
+
}],
|
|
899
|
+
}
|
|
900
|
+
},
|
|
901
|
+
{
|
|
902
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
903
|
+
parameters: {button: input.Button.LEFT},
|
|
904
|
+
},
|
|
905
|
+
]);
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
it('detects context-clicks', async function() {
|
|
909
|
+
const executor =
|
|
910
|
+
new StubExecutor(
|
|
911
|
+
Promise.reject(new error.UnknownCommandError),
|
|
912
|
+
Promise.resolve());
|
|
913
|
+
|
|
914
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
915
|
+
const element = new WebElement(null, 'abc123');
|
|
916
|
+
|
|
917
|
+
await actions
|
|
918
|
+
.press(input.Button.RIGHT)
|
|
919
|
+
.release(input.Button.RIGHT)
|
|
920
|
+
.perform();
|
|
921
|
+
|
|
922
|
+
assert.deepEqual(executor.commands, [
|
|
923
|
+
{
|
|
924
|
+
name: command.Name.ACTIONS,
|
|
925
|
+
parameters: {
|
|
926
|
+
actions: [{
|
|
927
|
+
id: 'default mouse',
|
|
928
|
+
type: 'pointer',
|
|
929
|
+
parameters: {pointerType: 'mouse'},
|
|
930
|
+
actions: [
|
|
931
|
+
{type: 'pointerDown', button: input.Button.RIGHT},
|
|
932
|
+
{type: 'pointerUp', button: input.Button.RIGHT},
|
|
933
|
+
],
|
|
934
|
+
}],
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
939
|
+
parameters: {button: input.Button.RIGHT},
|
|
940
|
+
},
|
|
941
|
+
]);
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it('contextClick() shortcut', async function() {
|
|
945
|
+
const executor =
|
|
946
|
+
new StubExecutor(
|
|
947
|
+
Promise.reject(new error.UnknownCommandError),
|
|
948
|
+
Promise.resolve());
|
|
949
|
+
|
|
950
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
951
|
+
const element = new WebElement(null, 'abc123');
|
|
952
|
+
|
|
953
|
+
await actions.contextClick().perform();
|
|
954
|
+
|
|
955
|
+
assert.deepEqual(executor.commands, [
|
|
956
|
+
{
|
|
957
|
+
name: command.Name.ACTIONS,
|
|
958
|
+
parameters: {
|
|
959
|
+
actions: [{
|
|
960
|
+
id: 'default mouse',
|
|
961
|
+
type: 'pointer',
|
|
962
|
+
parameters: {pointerType: 'mouse'},
|
|
963
|
+
actions: [
|
|
964
|
+
{type: 'pointerDown', button: input.Button.RIGHT},
|
|
965
|
+
{type: 'pointerUp', button: input.Button.RIGHT},
|
|
966
|
+
],
|
|
967
|
+
}],
|
|
968
|
+
}
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
972
|
+
parameters: {button: input.Button.RIGHT},
|
|
973
|
+
},
|
|
974
|
+
]);
|
|
975
|
+
});
|
|
976
|
+
|
|
977
|
+
it('click(element)', async function() {
|
|
978
|
+
const executor =
|
|
979
|
+
new StubExecutor(
|
|
980
|
+
Promise.reject(new error.UnknownCommandError),
|
|
981
|
+
Promise.resolve([0, 0]),
|
|
982
|
+
Promise.resolve(),
|
|
983
|
+
Promise.resolve());
|
|
984
|
+
|
|
985
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
986
|
+
const element = new WebElement(null, 'abc123');
|
|
987
|
+
|
|
988
|
+
await actions.click(element).perform();
|
|
989
|
+
|
|
990
|
+
assert.deepEqual(executor.commands, [
|
|
991
|
+
{
|
|
992
|
+
name: command.Name.ACTIONS,
|
|
993
|
+
parameters: {
|
|
994
|
+
actions: [{
|
|
995
|
+
id: 'default mouse',
|
|
996
|
+
type: 'pointer',
|
|
997
|
+
parameters: {pointerType: 'mouse'},
|
|
998
|
+
actions: [
|
|
999
|
+
{
|
|
1000
|
+
type: 'pointerMove',
|
|
1001
|
+
duration: 100,
|
|
1002
|
+
origin: element,
|
|
1003
|
+
x: 0,
|
|
1004
|
+
y: 0,
|
|
1005
|
+
},
|
|
1006
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1007
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1008
|
+
],
|
|
1009
|
+
}],
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
name: command.Name.EXECUTE_SCRIPT,
|
|
1014
|
+
parameters: {
|
|
1015
|
+
script: input.INTERNAL_COMPUTE_OFFSET_SCRIPT,
|
|
1016
|
+
args: [element],
|
|
1017
|
+
},
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1021
|
+
parameters: {
|
|
1022
|
+
element: 'abc123',
|
|
1023
|
+
xoffset: 0,
|
|
1024
|
+
yoffset: 0,
|
|
1025
|
+
},
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
1029
|
+
parameters: {button: input.Button.LEFT},
|
|
1030
|
+
},
|
|
1031
|
+
]);
|
|
1032
|
+
});
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
describe('detects double-clicks', function() {
|
|
1036
|
+
it('press/release x2 for same button is a double-click', async function() {
|
|
1037
|
+
const executor =
|
|
1038
|
+
new StubExecutor(
|
|
1039
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1040
|
+
Promise.resolve());
|
|
1041
|
+
|
|
1042
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1043
|
+
const element = new WebElement(null, 'abc123');
|
|
1044
|
+
|
|
1045
|
+
await actions
|
|
1046
|
+
.press(input.Button.LEFT)
|
|
1047
|
+
.release(input.Button.LEFT)
|
|
1048
|
+
.press(input.Button.LEFT)
|
|
1049
|
+
.release(input.Button.LEFT)
|
|
1050
|
+
.perform();
|
|
1051
|
+
|
|
1052
|
+
assert.deepEqual(executor.commands, [
|
|
1053
|
+
{
|
|
1054
|
+
name: command.Name.ACTIONS,
|
|
1055
|
+
parameters: {
|
|
1056
|
+
actions: [{
|
|
1057
|
+
id: 'default mouse',
|
|
1058
|
+
type: 'pointer',
|
|
1059
|
+
parameters: {pointerType: 'mouse'},
|
|
1060
|
+
actions: [
|
|
1061
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1062
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1063
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1064
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1065
|
+
],
|
|
1066
|
+
}],
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
name: command.Name.LEGACY_ACTION_DOUBLE_CLICK,
|
|
1071
|
+
parameters: {button: input.Button.LEFT},
|
|
1072
|
+
},
|
|
1073
|
+
]);
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
it('doubleClick() shortcut', async function() {
|
|
1077
|
+
const executor =
|
|
1078
|
+
new StubExecutor(
|
|
1079
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1080
|
+
Promise.resolve());
|
|
1081
|
+
|
|
1082
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1083
|
+
|
|
1084
|
+
await actions.doubleClick().perform();
|
|
1085
|
+
|
|
1086
|
+
assert.deepEqual(executor.commands, [
|
|
1087
|
+
{
|
|
1088
|
+
name: command.Name.ACTIONS,
|
|
1089
|
+
parameters: {
|
|
1090
|
+
actions: [{
|
|
1091
|
+
id: 'default mouse',
|
|
1092
|
+
type: 'pointer',
|
|
1093
|
+
parameters: {pointerType: 'mouse'},
|
|
1094
|
+
actions: [
|
|
1095
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1096
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1097
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1098
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1099
|
+
],
|
|
1100
|
+
}],
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
name: command.Name.LEGACY_ACTION_DOUBLE_CLICK,
|
|
1105
|
+
parameters: {button: input.Button.LEFT},
|
|
1106
|
+
},
|
|
1107
|
+
]);
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
it('not a double-click if second click is another button', async function() {
|
|
1111
|
+
const executor =
|
|
1112
|
+
new StubExecutor(
|
|
1113
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1114
|
+
Promise.resolve(),
|
|
1115
|
+
Promise.resolve());
|
|
1116
|
+
|
|
1117
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1118
|
+
|
|
1119
|
+
await actions.click().contextClick().perform();
|
|
1120
|
+
|
|
1121
|
+
assert.deepEqual(executor.commands, [
|
|
1122
|
+
{
|
|
1123
|
+
name: command.Name.ACTIONS,
|
|
1124
|
+
parameters: {
|
|
1125
|
+
actions: [{
|
|
1126
|
+
id: 'default mouse',
|
|
1127
|
+
type: 'pointer',
|
|
1128
|
+
parameters: {pointerType: 'mouse'},
|
|
1129
|
+
actions: [
|
|
1130
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1131
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1132
|
+
{type: 'pointerDown', button: input.Button.RIGHT},
|
|
1133
|
+
{type: 'pointerUp', button: input.Button.RIGHT},
|
|
1134
|
+
],
|
|
1135
|
+
}],
|
|
1136
|
+
}
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
1140
|
+
parameters: {button: input.Button.LEFT},
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
1144
|
+
parameters: {button: input.Button.RIGHT},
|
|
1145
|
+
},
|
|
1146
|
+
]);
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
it('doubleClick(element)', async function() {
|
|
1150
|
+
const executor =
|
|
1151
|
+
new StubExecutor(
|
|
1152
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1153
|
+
Promise.resolve([7, 10]),
|
|
1154
|
+
Promise.resolve(),
|
|
1155
|
+
Promise.resolve());
|
|
1156
|
+
|
|
1157
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1158
|
+
const element = new WebElement(null, 'abc123');
|
|
1159
|
+
|
|
1160
|
+
await actions.doubleClick(element).perform();
|
|
1161
|
+
|
|
1162
|
+
assert.deepEqual(executor.commands, [
|
|
1163
|
+
{
|
|
1164
|
+
name: command.Name.ACTIONS,
|
|
1165
|
+
parameters: {
|
|
1166
|
+
actions: [{
|
|
1167
|
+
id: 'default mouse',
|
|
1168
|
+
type: 'pointer',
|
|
1169
|
+
parameters: {pointerType: 'mouse'},
|
|
1170
|
+
actions: [
|
|
1171
|
+
{
|
|
1172
|
+
type: 'pointerMove',
|
|
1173
|
+
duration: 100,
|
|
1174
|
+
origin: element,
|
|
1175
|
+
x: 0,
|
|
1176
|
+
y: 0,
|
|
1177
|
+
},
|
|
1178
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1179
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1180
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1181
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1182
|
+
],
|
|
1183
|
+
}],
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
name: command.Name.EXECUTE_SCRIPT,
|
|
1188
|
+
parameters: {
|
|
1189
|
+
script: input.INTERNAL_COMPUTE_OFFSET_SCRIPT,
|
|
1190
|
+
args: [element],
|
|
1191
|
+
},
|
|
1192
|
+
},
|
|
1193
|
+
{
|
|
1194
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1195
|
+
parameters: {
|
|
1196
|
+
element: 'abc123',
|
|
1197
|
+
xoffset: 7,
|
|
1198
|
+
yoffset: 10,
|
|
1199
|
+
},
|
|
1200
|
+
},
|
|
1201
|
+
{
|
|
1202
|
+
name: command.Name.LEGACY_ACTION_DOUBLE_CLICK,
|
|
1203
|
+
parameters: {button: input.Button.LEFT},
|
|
1204
|
+
},
|
|
1205
|
+
]);
|
|
1206
|
+
});
|
|
1207
|
+
});
|
|
1208
|
+
|
|
1209
|
+
it('mouse sequence', async function() {
|
|
1210
|
+
const executor =
|
|
1211
|
+
new StubExecutor(
|
|
1212
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1213
|
+
Promise.resolve([-6, 9]),
|
|
1214
|
+
Promise.resolve(),
|
|
1215
|
+
Promise.resolve(),
|
|
1216
|
+
Promise.resolve(),
|
|
1217
|
+
Promise.resolve());
|
|
1218
|
+
|
|
1219
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1220
|
+
const element = new WebElement(null, 'abc123');
|
|
1221
|
+
|
|
1222
|
+
await actions
|
|
1223
|
+
.move({x: 5, y: 5, origin: element})
|
|
1224
|
+
.click()
|
|
1225
|
+
.move({x: 10, y: 15, origin: input.Origin.POINTER})
|
|
1226
|
+
.doubleClick()
|
|
1227
|
+
.perform();
|
|
1228
|
+
|
|
1229
|
+
assert.deepEqual(executor.commands, [
|
|
1230
|
+
{
|
|
1231
|
+
name: command.Name.ACTIONS,
|
|
1232
|
+
parameters: {
|
|
1233
|
+
actions: [{
|
|
1234
|
+
id: 'default mouse',
|
|
1235
|
+
type: 'pointer',
|
|
1236
|
+
parameters: {pointerType: 'mouse'},
|
|
1237
|
+
actions: [
|
|
1238
|
+
{
|
|
1239
|
+
type: 'pointerMove',
|
|
1240
|
+
duration: 100,
|
|
1241
|
+
origin: element,
|
|
1242
|
+
x: 5,
|
|
1243
|
+
y: 5,
|
|
1244
|
+
},
|
|
1245
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1246
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1247
|
+
{
|
|
1248
|
+
type: 'pointerMove',
|
|
1249
|
+
duration: 100,
|
|
1250
|
+
origin: input.Origin.POINTER,
|
|
1251
|
+
x: 10,
|
|
1252
|
+
y: 15,
|
|
1253
|
+
},
|
|
1254
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1255
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1256
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1257
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1258
|
+
],
|
|
1259
|
+
}],
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
name: command.Name.EXECUTE_SCRIPT,
|
|
1264
|
+
parameters: {
|
|
1265
|
+
script: input.INTERNAL_COMPUTE_OFFSET_SCRIPT,
|
|
1266
|
+
args: [element],
|
|
1267
|
+
},
|
|
1268
|
+
},
|
|
1269
|
+
{
|
|
1270
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1271
|
+
parameters: {
|
|
1272
|
+
element: 'abc123',
|
|
1273
|
+
xoffset: -1,
|
|
1274
|
+
yoffset: 14,
|
|
1275
|
+
},
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
name: command.Name.LEGACY_ACTION_CLICK,
|
|
1279
|
+
parameters: {button: input.Button.LEFT},
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1283
|
+
parameters: {xoffset: 10, yoffset: 15},
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
name: command.Name.LEGACY_ACTION_DOUBLE_CLICK,
|
|
1287
|
+
parameters: {button: input.Button.LEFT},
|
|
1288
|
+
},
|
|
1289
|
+
]);
|
|
1290
|
+
});
|
|
1291
|
+
|
|
1292
|
+
it('dragAndDrop', async function() {
|
|
1293
|
+
const executor =
|
|
1294
|
+
new StubExecutor(
|
|
1295
|
+
Promise.reject(new error.UnknownCommandError),
|
|
1296
|
+
Promise.resolve([15, 20]),
|
|
1297
|
+
Promise.resolve(),
|
|
1298
|
+
Promise.resolve(),
|
|
1299
|
+
Promise.resolve([25, 30]),
|
|
1300
|
+
Promise.resolve(),
|
|
1301
|
+
Promise.resolve());
|
|
1302
|
+
|
|
1303
|
+
const actions = new input.Actions(executor, {bridge: true});
|
|
1304
|
+
const e1 = new WebElement(null, 'abc123');
|
|
1305
|
+
const e2 = new WebElement(null, 'def456');
|
|
1306
|
+
|
|
1307
|
+
await actions.dragAndDrop(e1, e2).perform();
|
|
1308
|
+
|
|
1309
|
+
assert.deepEqual(executor.commands, [
|
|
1310
|
+
{
|
|
1311
|
+
name: command.Name.ACTIONS,
|
|
1312
|
+
parameters: {
|
|
1313
|
+
actions: [{
|
|
1314
|
+
id: 'default mouse',
|
|
1315
|
+
type: 'pointer',
|
|
1316
|
+
parameters: {pointerType: 'mouse'},
|
|
1317
|
+
actions: [
|
|
1318
|
+
{
|
|
1319
|
+
type: 'pointerMove',
|
|
1320
|
+
duration: 100,
|
|
1321
|
+
origin: e1,
|
|
1322
|
+
x: 0,
|
|
1323
|
+
y: 0,
|
|
1324
|
+
},
|
|
1325
|
+
{type: 'pointerDown', button: input.Button.LEFT},
|
|
1326
|
+
{
|
|
1327
|
+
type: 'pointerMove',
|
|
1328
|
+
duration: 100,
|
|
1329
|
+
origin: e2,
|
|
1330
|
+
x: 0,
|
|
1331
|
+
y: 0,
|
|
1332
|
+
},
|
|
1333
|
+
{type: 'pointerUp', button: input.Button.LEFT},
|
|
1334
|
+
],
|
|
1335
|
+
}],
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
name: command.Name.EXECUTE_SCRIPT,
|
|
1340
|
+
parameters: {
|
|
1341
|
+
script: input.INTERNAL_COMPUTE_OFFSET_SCRIPT,
|
|
1342
|
+
args: [e1],
|
|
1343
|
+
},
|
|
1344
|
+
},
|
|
1345
|
+
{
|
|
1346
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1347
|
+
parameters: {
|
|
1348
|
+
element: 'abc123',
|
|
1349
|
+
xoffset: 15,
|
|
1350
|
+
yoffset: 20,
|
|
1351
|
+
},
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
name: command.Name.LEGACY_ACTION_MOUSE_DOWN,
|
|
1355
|
+
parameters: {button: input.Button.LEFT},
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
name: command.Name.EXECUTE_SCRIPT,
|
|
1359
|
+
parameters: {
|
|
1360
|
+
script: input.INTERNAL_COMPUTE_OFFSET_SCRIPT,
|
|
1361
|
+
args: [e2],
|
|
1362
|
+
},
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
name: command.Name.LEGACY_ACTION_MOUSE_MOVE,
|
|
1366
|
+
parameters: {
|
|
1367
|
+
element: 'def456',
|
|
1368
|
+
xoffset: 25,
|
|
1369
|
+
yoffset: 30,
|
|
1370
|
+
},
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
name: command.Name.LEGACY_ACTION_MOUSE_UP,
|
|
1374
|
+
parameters: {button: input.Button.LEFT},
|
|
1375
|
+
},
|
|
1376
|
+
]);
|
|
1377
|
+
});
|
|
1378
|
+
});
|
|
1379
|
+
});
|