diff --git a/lib/api/protocol/waitUntil.js b/lib/api/protocol/waitUntil.js index 9f44c03793..83b5beba73 100644 --- a/lib/api/protocol/waitUntil.js +++ b/lib/api/protocol/waitUntil.js @@ -26,6 +26,7 @@ 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). @@ -33,7 +34,7 @@ const ProtocolAction = require('./_base-action.js'); * @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() { @@ -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); diff --git a/lib/utils/logger/index.js b/lib/utils/logger/index.js index 349f664ccf..c6b4b1e0f8 100644 --- a/lib/utils/logger/index.js +++ b/lib/utils/logger/index.js @@ -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 :')); diff --git a/test/src/api/commands/client/testWaitUntil.js b/test/src/api/commands/client/testWaitUntil.js index 38e402f678..51583cea85 100644 --- a/test/src/api/commands/client/testWaitUntil.js +++ b/test/src/api/commands/client/testWaitUntil.js @@ -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; @@ -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; }); @@ -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; @@ -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);