Skip to content

Commit

Permalink
added support for waitUntil to use a custom message for timeout errors
Browse files Browse the repository at this point in the history
  • Loading branch information
beatfactor committed Jul 20, 2022
1 parent 8eb8c39 commit 4b79d79
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 28 deletions.
51 changes: 30 additions & 21 deletions lib/api/protocol/waitUntil.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ const ProtocolAction = require('./_base-action.js');
* @syntax .waitUntil(conditionFn, [callback])
* @syntax .waitUntil(conditionFn, [waitTimeMs], [callback])
* @syntax .waitUntil(conditionFn, [waitTimeMs], [retryInterval], [callback])
* @syntax .waitUntil(conditionFn, [waitTimeMs], [retryInterval], [message], [callback])
* @param {function} conditionFn The condition to wait on, defined as function which returns a Promise
* @param {number} [waitTimeMs] How long to wait for the condition to be true (in milliseconds).
* @param {number} [retryInterval] The interval to use between checks (in milliseconds).
* @param {Function} [callback] An optional callback which will be called with the result
* @api protocol.utilities
* @since 2.0.0
*/
const {makePromise, isFunction, isUndefined, isNumber} = require('../../utils');
const {makePromise, isFunction, isUndefined, isNumber, isString} = require('../../utils');

module.exports = class WaitUntil extends ProtocolAction {
get requiresSeleniumWebdriver() {
Expand All @@ -51,38 +52,46 @@ module.exports = class WaitUntil extends ProtocolAction {
return true;
}

//timeMs, retryInterval, callback = function(r) {return r}
//timeMs, retryInterval, message, callback = function(r) {return r}
async command(conditionFn, ...args) {
let callback = function(r) {return r};
let message;
let timeMs = this.settings.globals.waitForConditionTimeout;
let retryInterval = this.settings.globals.waitForConditionPollInterval;

switch (args.length) {
case 2:
case 3:
timeMs = WaitUntil.isParamTypeValid(args[0], 'number') ? args[0] : timeMs;
if (args.length >= 3 && isString(args[2]) && args[2]) {
timeMs = WaitUntil.isParamTypeValid(args[0], 'number') ? args[0] : timeMs;
retryInterval = WaitUntil.isParamTypeValid(args[1], 'number') ? args[0] : timeMs;
message = args[2];
callback = isFunction(args[3]) ? args[3] : callback;
} else {
switch (args.length) {
case 2:
case 3:
timeMs = WaitUntil.isParamTypeValid(args[0], 'number') ? args[0] : timeMs;

if (isFunction(args[1]) && isUndefined(args[2])) {
callback = args[1];
} else {
retryInterval = WaitUntil.isParamTypeValid(args[1], 'number') ? args[1] : retryInterval;
callback = !isUndefined(args[2]) && WaitUntil.isParamTypeValid(args[2], 'function') ? args[2] : callback;
}
if (isFunction(args[1]) && isUndefined(args[2])) {
callback = args[1];
} else {
retryInterval = WaitUntil.isParamTypeValid(args[1], 'number') ? args[1] : retryInterval;
callback = !isUndefined(args[2]) && WaitUntil.isParamTypeValid(args[2], 'function') ? args[2] : callback;
}

break;
break;

case 1:
if (isFunction(args[0])) {
callback = args[0];
} else if (isNumber(args[0])) {
timeMs = args[0];
}
break;
case 1:
if (isFunction(args[0])) {
callback = args[0];
} else if (isNumber(args[0])) {
timeMs = args[0];
}
break;
}
}

const result = await this.transportActions.wait(() => {
return conditionFn.bind(this.api);
}, timeMs, undefined, retryInterval);
}, timeMs, message, retryInterval);

if (result && result.error instanceof Error) {
await callback(result);
Expand Down
8 changes: 5 additions & 3 deletions lib/utils/logger/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,11 @@ class Logger {
if (stack){
stack = '\tat' + stack.split(/ {4}at/g).slice(1).join('\tat');

content.push(colors.brown('\n Error location :'));
content.push(beautifyStackTrace(stack, true, modulepath));

const beautified = beautifyStackTrace(stack, true, modulepath);
if (beautified) {
content.push(colors.brown('\n Error location:'));
content.push(beautified);
}

if (alwaysDisplayError(errorObj)) {
content.push(colors.brown(' Stack Trace :'));
Expand Down
68 changes: 64 additions & 4 deletions test/src/api/commands/client/testWaitUntil.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('.waitUntil()', function () {
let tries = 0;
let startTime = new Date().valueOf();
let timeDiff;
const maxTimeout = 300;
const maxTimeout = 100;
const client = this.client.api;
let result;

Expand All @@ -116,7 +116,7 @@ describe('.waitUntil()', function () {
tries++;

return false;
}, maxTimeout, 150, function(response) {
}, maxTimeout, 50, function(response) {
timeDiff = new Date().valueOf() - startTime;
result = response;
});
Expand All @@ -134,11 +134,71 @@ describe('.waitUntil()', function () {
});
});

it('client.waitUntil() function failure with custom timeout, interval, message, and callback', function (done) {
let tries = 0;
let startTime = new Date().valueOf();
let timeDiff;
const maxTimeout = 100;
const client = this.client.api;
let result;

this.client.api.waitUntil(function () {
assert.deepStrictEqual(this.options, client.options);
tries++;

return false;
}, maxTimeout, 50, 'custom error message', function(response) {
timeDiff = new Date().valueOf() - startTime;
result = response;
});

this.client.start(err => {
try {
assert.ok(timeDiff <= maxTimeout+100, `Expected lower than ${maxTimeout}, but got ${timeDiff}`);
assert.strictEqual(result.status, -1);
assert.ok(err instanceof Error);
const messageParts = err.message.split('\n');
assert.strictEqual(messageParts[0], 'Error while running "waitUntil" command: [TimeoutError] custom error message');
assert.ok(messageParts[1].startsWith('Wait timed out after'));

done();
} catch (err) {
done(err);
}
});
});

it('client.waitUntil() function failure with custom timeout, interval, message', function (done) {
let tries = 0;
const maxTimeout = 100;
const client = this.client.api;

this.client.api.waitUntil(function () {
assert.deepStrictEqual(this.options, client.options);
tries++;

return false;
}, maxTimeout, 50, 'custom error message');

this.client.start(err => {
try {
assert.ok(err instanceof Error);
const messageParts = err.message.split('\n');
assert.strictEqual(messageParts[0], 'Error while running "waitUntil" command: [TimeoutError] custom error message');
assert.ok(messageParts[1].startsWith('Wait timed out after'));

done();
} catch (err) {
done(err);
}
});
});

it('client.waitUntil() function failure with custom timeout and default interval', function (done) {
let tries = 0;
let startTime = new Date().valueOf();
let timeDiff;
const maxTimeout = 300;
const maxTimeout = 100;
const client = this.client.api;
let result;

Expand All @@ -157,7 +217,7 @@ describe('.waitUntil()', function () {
assert.ok(err instanceof Error);
assert.ok(timeDiff <= maxTimeout+100, `Expected lower than ${maxTimeout}, but got ${timeDiff}`);
assert.strictEqual(result.status, -1);
assert.strictEqual(tries, 7);
assert.strictEqual(tries, 3);
done();
} catch (err) {
done(err);
Expand Down

0 comments on commit 4b79d79

Please sign in to comment.