-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
perform.js
133 lines (118 loc) · 4.03 KB
/
perform.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* A simple perform command which allows access to the Nightwatch API in a callback. Can be useful if you want to read variables set by other commands.
*
* The callback signature can have up to two parameters.
* - no parameters: callback runs and perform completes immediately at the end of the execution of the callback.
* - one parameter: allows for asynchronous execution within the callback providing a done callback function for completion as the first argument.
* - two parameters: allows for asynchronous execution with the Nightwatch `api` object passed in as the first argument, followed by the done callback.
*
* In the case of asynchronous execution, the timeout can be controlled by setting the `asyncHookTimeout` global. See [Using test globals](https://nightwatchjs.org/gettingstarted/concepts/#using-test-globals) for more info.
*
* @example
* describe('perform example', function() {
* var elementValue;
*
* it('basic perform', function(browser) {
* browser
* .getValue('.some-element', function(result) {
* elementValue = result.value;
* })
* // other stuff going on ...
*
* // self-completing callback
* .perform(function() {
* console.log('elementValue', elementValue);
* // without any defined parameters, perform
* // completes immediately (synchronously)
* })
*
* // returning a Promise
* .perform(async function() {
* console.log('elementValue', elementValue);
* // potentially other async stuff going on
*
* return elementValue;
* })
*
* // DEPRECATED: asynchronous completion including api (client)
* .perform(function(client, done) {
* console.log('elementValue', elementValue);
* done();
* });
* });
*
* it('perform with async', function(browser) {
* const result = await browser.perform(async function() {
* return 100;
* });
* console.log('result:', result); // 100
* })
* }
*
*
* @method perform
* @param {function} callback The function to run as part of the queue.
* @api protocol.utilities
*/
const {Actions} = require('selenium-webdriver/lib/input');
const EventEmitter = require('events');
class Perform extends EventEmitter {
static get alwaysAsync() {
return true;
}
command(callback = function() {}) {
let doneCallback;
let asyncHookTimeout = this.client.settings.globals.asyncHookTimeout;
this.timeoutId = setTimeout(() => {
this.emit('error', new Error(`Timeout while waiting (${asyncHookTimeout}ms) for the .perform() command callback to be called.`));
}, asyncHookTimeout);
if (callback.length === 0) {
let cbResult = this.runCallback(callback, [this.api]);
// support for Selenium Actions API:
// https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html
if (cbResult instanceof Actions) {
cbResult = cbResult.perform();
}
if (cbResult instanceof Promise) {
clearTimeout(this.timeoutId);
cbResult.then(async result => {
if (result instanceof Actions) {
result = await result.perform();
}
this.emit('complete', result);
}).catch(err => {
this.emit('error', err);
});
return this;
}
doneCallback = () => {
clearTimeout(this.timeoutId);
this.emit('complete', cbResult);
};
} else {
doneCallback = () => {
let args = [(result) => {
clearTimeout(this.timeoutId);
this.emit('complete', result);
}];
if (callback.length > 1) {
args.unshift(this.api);
}
this.runCallback(callback, args);
};
}
process.nextTick(doneCallback);
return this;
}
runCallback(cb, args) {
try {
return cb.apply(this.api, args);
} catch (err) {
if (this.timeoutId) {
clearTimeout(this.timeoutId);
}
this.emit('error', err);
}
}
}
module.exports = Perform;