@wdio/sync
Advanced tools
Comparing version 5.11.11 to 5.11.13
@@ -8,12 +8,3 @@ "use strict"; | ||
const STACK_START = /^\s+at /; | ||
const STACKTRACE_FILTER = [// exclude @wdio/sync from stack traces | ||
'node_modules/@wdio/sync/', // exclude webdriverio stack traces | ||
'node_modules/webdriverio/build/', // exclude Request emit | ||
' (events.js:', ' (domain.js:', // other excludes | ||
'(internal/process/next_tick.js', 'new Promise (<anonymous>)', 'Generator.next (<anonymous>)', '__awaiter (']; | ||
/** | ||
* filter stack array | ||
* @param {string} stackRow | ||
* @returns {boolean} | ||
*/ | ||
const STACKTRACE_FILTER = ['node_modules/@wdio/sync/', 'node_modules/webdriverio/build/', ' (events.js:', ' (domain.js:', '(internal/process/next_tick.js', 'new Promise (<anonymous>)', 'Generator.next (<anonymous>)', '__awaiter (']; | ||
@@ -20,0 +11,0 @@ const STACKTRACE_FILTER_FN = stackRow => { |
@@ -15,24 +15,8 @@ "use strict"; | ||
const log = (0, _logger.default)('@wdio/sync'); | ||
/** | ||
* Helper method to execute a row of hooks with certain parameters. | ||
* It will return with a reject promise due to a design decision to not let hooks/service intefer the | ||
* actual test process. | ||
* | ||
* @param {Function|Function[]} hooks list of hooks | ||
* @param {Object[]} args list of parameter for hook functions | ||
* @return {Promise} promise that gets resolved once all hooks finished running | ||
*/ | ||
function executeHooksWithArgs(hooks = [], args) { | ||
/** | ||
* make sure hooks are an array of functions | ||
*/ | ||
if (typeof hooks === 'function') { | ||
hooks = [hooks]; | ||
} | ||
/** | ||
* make sure args is an array since we are calling apply | ||
*/ | ||
if (!Array.isArray(args)) { | ||
@@ -62,7 +46,3 @@ args = [args]; | ||
}; | ||
/** | ||
* after command hooks require additional Fiber environment | ||
*/ | ||
return (0, _fibers.default)(execHook).run(); | ||
@@ -69,0 +49,0 @@ })); |
@@ -51,14 +51,4 @@ "use strict"; | ||
const log = (0, _logger.default)('@wdio/sync'); | ||
/** | ||
* execute test or hook synchronously | ||
* @param {Function} fn spec or hook method | ||
* @param {Number} repeatTest number of retries | ||
* @return {Promise} that gets resolved once test/hook is done or was retried enough | ||
*/ | ||
const executeSync = function (fn, repeatTest = 0, args = []) { | ||
/** | ||
* if a new hook gets executed we can assume that all commands should have finised | ||
* with exception of timeouts where `commandIsRunning` will never be reset but here | ||
*/ | ||
return new Promise((resolve, reject) => { | ||
@@ -72,7 +62,3 @@ try { | ||
} | ||
/** | ||
* no need to modify stack if no stack available | ||
*/ | ||
if (!e.stack) { | ||
@@ -87,10 +73,3 @@ return reject(e); | ||
}; | ||
/** | ||
* execute test or hook asynchronously | ||
* @param {Function} fn spec or hook method | ||
* @param {Number} repeatTest number of retries | ||
* @return {Promise} that gets resolved once test/hook is done or was retried enough | ||
*/ | ||
exports.executeSync = executeSync; | ||
@@ -100,7 +79,2 @@ | ||
let result, error; | ||
/** | ||
* if a new hook gets executed we can assume that all commands should have finised | ||
* with exception of timeouts where `commandIsRunning` will never be reset but here | ||
*/ | ||
// commandIsRunning = false | ||
@@ -112,8 +86,3 @@ try { | ||
} | ||
/** | ||
* handle errors that get thrown directly and are not cause by | ||
* rejected promises | ||
*/ | ||
if (error) { | ||
@@ -126,15 +95,7 @@ if (repeatTest) { | ||
} | ||
/** | ||
* if we don't retry just return result | ||
*/ | ||
if (repeatTest === 0 || !result || typeof result.catch !== 'function') { | ||
return new Promise(resolve => resolve(result)); | ||
} | ||
/** | ||
* handle promise response | ||
*/ | ||
return result.catch(e => { | ||
@@ -149,15 +110,3 @@ if (repeatTest) { | ||
}; | ||
/** | ||
* runs a hook within fibers context (if function name is not async) | ||
* it also executes before/after hook hook | ||
* | ||
* @param {Function} hookFn function that was passed to the framework hook | ||
* @param {Function} origFn original framework hook function | ||
* @param {Function} before before hook hook | ||
* @param {Function} after after hook hook | ||
* @param {Number} repeatTest number of retries if hook fails | ||
* @return {Function} wrapped framework hook function | ||
*/ | ||
exports.executeAsync = executeAsync; | ||
@@ -169,10 +118,4 @@ | ||
return origFn(function (...hookArgs) { | ||
// Print errors encountered in beforeHook and afterHook to console, but | ||
// don't propagate them to avoid failing the test. However, errors in | ||
// framework hook functions should fail the test, so propagate those. | ||
return (0, _executeHooksWithArgs.default)(before).catch(hookError('beforeHook')).then(() => { | ||
/** | ||
* user wants handle async command using promises, no need to wrap in fiber context | ||
*/ | ||
if (hookFn.name === 'async') { | ||
if (hookFn.constructor && hookFn.constructor.name === 'AsyncFunction' || hookFn.name === 'async') { | ||
return executeAsync.call(this, hookFn, repeatTest, (0, _utils.filterSpecArgs)(hookArgs)); | ||
@@ -187,17 +130,5 @@ } | ||
}; | ||
/** | ||
* runs a spec function (test function) within the fibers context | ||
* @param {string} specTitle test description | ||
* @param {Function} specFn test function that got passed in from the user | ||
* @param {Function} origFn original framework test function | ||
* @param {Number} repeatTest number of retries if test fails | ||
* @return {Function} wrapped test function | ||
*/ | ||
const runSpec = function (specTitle, specFn, origFn, repeatTest = 0) { | ||
/** | ||
* user wants handle async command using promises, no need to wrap in fiber context | ||
*/ | ||
if (specFn.name === 'async') { | ||
if (specFn.constructor && specFn.constructor.name === 'AsyncFunction' || specFn.name === 'async') { | ||
return origFn(specTitle, function async(...specArgs) { | ||
@@ -212,28 +143,9 @@ return executeAsync.call(this, specFn, repeatTest, (0, _utils.filterSpecArgs)(specArgs)); | ||
}; | ||
/** | ||
* run hook or spec via executeSync | ||
*/ | ||
function runSync(fn, repeatTest = 0, args = []) { | ||
return (resolve, reject) => (0, _fibers.default)(() => executeSync.call(this, fn, repeatTest, args).then(() => resolve(), reject)).run(); | ||
} | ||
/** | ||
* wraps hooks and test function of a framework within a fiber context | ||
* @param {String} fnName spec function that is being overwritten | ||
* @param {Function} origFn original framework function | ||
* @param {String[]} testInterfaceFnNames command that runs specs, e.g. `it`, `it.only` or `fit` | ||
* @param {Function} before before hook hook | ||
* @param {Function} after after hook hook | ||
* @return {Function} wrapped test/hook function | ||
*/ | ||
const wrapTestFunction = function (fnName, origFn, testInterfaceFnNames, before, after) { | ||
return function (...specArguments) { | ||
/** | ||
* Variadic arguments: | ||
* [title, fn], [title], [fn] | ||
* [title, fn, retryCnt], [title, retryCnt], [fn, retryCnt] | ||
*/ | ||
let retryCnt = typeof specArguments[specArguments.length - 1] === 'number' ? specArguments.pop() : 0; | ||
@@ -245,6 +157,2 @@ const specFn = typeof specArguments[0] === 'function' ? specArguments.shift() : typeof specArguments[1] === 'function' ? specArguments.pop() : undefined; | ||
if (specFn) return runSpec(specTitle, specFn, origFn, retryCnt); | ||
/** | ||
* if specFn is undefined we are dealing with a pending function | ||
*/ | ||
return origFn(specTitle); | ||
@@ -256,21 +164,6 @@ } | ||
}; | ||
/** | ||
* Wraps global test function like `it` so that commands can run synchronouse | ||
* | ||
* The scope parameter is used in the qunit framework since all functions are bound to global.QUnit instead of global | ||
* | ||
* @param {String[]} testInterfaceFnNames command that runs specs, e.g. `it`, `it.only` or `fit` | ||
* @param {Function} before before hook hook | ||
* @param {Function} after after hook hook | ||
* @param {String} fnName test interface command to wrap, e.g. `beforeEach` | ||
* @param {Object} scope the scope to run command from, defaults to global | ||
*/ | ||
const runTestInFiberContext = function (testInterfaceFnNames, before, after, fnName, scope = global) { | ||
const origFn = scope[fnName]; | ||
scope[fnName] = wrapTestFunction(fnName, origFn, testInterfaceFnNames, before, after); | ||
/** | ||
* support it.skip for the Mocha framework | ||
*/ | ||
@@ -280,7 +173,3 @@ if (typeof origFn.skip === 'function') { | ||
} | ||
/** | ||
* wrap it.only for the Mocha framework | ||
*/ | ||
if (typeof origFn.only === 'function') { | ||
@@ -287,0 +176,0 @@ const origOnlyFn = origFn.only; |
@@ -12,7 +12,2 @@ "use strict"; | ||
/** | ||
* global function to wrap callbacks into Fiber context | ||
* @param {Function} fn function to wrap around | ||
* @return {Function} wrapped around function | ||
*/ | ||
function runFnInFiberContext(fn) { | ||
@@ -19,0 +14,0 @@ return function (...args) { |
@@ -12,7 +12,2 @@ "use strict"; | ||
/** | ||
* global function to wrap callbacks into Fiber context | ||
* @param {Function} fn function to wrap around | ||
* @return {Function} wrapped around function | ||
*/ | ||
function runFnInFiberContextWithCallback(fn, done) { | ||
@@ -19,0 +14,0 @@ return function (...args) { |
@@ -11,8 +11,2 @@ "use strict"; | ||
/** | ||
* Cleanup stack traces, merge and remove duplicates | ||
* @param {Error|*} commandError Error object or anything else including undefined | ||
* @param {Error} savedError Error with root stack trace | ||
* @returns {Error} | ||
*/ | ||
function sanitizeErrorMessage(commandError, savedError) { | ||
@@ -36,3 +30,3 @@ let name, stack, message; | ||
err.name = name; | ||
err.stack = savedError.stack; // merge stack traces if Error has stack trace | ||
err.stack = savedError.stack; | ||
@@ -43,6 +37,4 @@ if (stack) { | ||
let stackArr = err.stack.split('\n'); // filter stack trace | ||
stackArr = stackArr.filter(_constants.STACKTRACE_FILTER_FN); // remove duplicates from stack traces | ||
let stackArr = err.stack.split('\n'); | ||
stackArr = stackArr.filter(_constants.STACKTRACE_FILTER_FN); | ||
err.stack = stackArr.reduce((acc, currentValue) => { | ||
@@ -53,10 +45,5 @@ return acc.includes(currentValue) ? acc : `${acc}\n${currentValue}`; | ||
} | ||
/** | ||
* filter out arguments passed to specFn & hookFn, don't allow callbacks | ||
* as there is no need for user to call e.g. `done()` | ||
*/ | ||
function filterSpecArgs(args) { | ||
return args.filter(arg => typeof arg !== 'function'); | ||
} |
@@ -16,18 +16,5 @@ "use strict"; | ||
/** | ||
* wraps a function into a Fiber ready context to enable sync execution and hooks | ||
* @param {Function} fn function to be executed | ||
* @param {String} commandName name of that function | ||
* @param {Function[]} beforeCommand method to be executed before calling the actual function | ||
* @param {Function[]} afterCommand method to be executed after calling the actual function | ||
* @return {Function} actual wrapped function | ||
*/ | ||
function wrapCommand(commandName, fn) { | ||
return function wrapCommandFn(...args) { | ||
// save error for getting full stack in case of failure | ||
// should be before any async calls | ||
const stackError = new Error(); | ||
/** | ||
* Avoid running some functions in Future that are not in Fiber. | ||
*/ | ||
@@ -38,8 +25,3 @@ if (this._NOT_FIBER === true) { | ||
} | ||
/** | ||
* all named nested functions run in parent Fiber context | ||
* except of debug and waitUntil | ||
*/ | ||
this._NOT_FIBER = fn.name !== '' && fn.name !== 'debug' && commandName !== 'waitUntil'; | ||
@@ -55,14 +37,6 @@ const future = new _future.default(); | ||
} catch (e) { | ||
/** | ||
* in case some 3rd party lib rejects without bundling into an error | ||
*/ | ||
if (typeof e === 'string') { | ||
throw new Error(e); | ||
} | ||
/** | ||
* in case we run commands where no fiber function was used | ||
* e.g. when we call deleteSession | ||
*/ | ||
if (e.message.includes('Can\'t wait without a fiber')) { | ||
@@ -77,7 +51,3 @@ return result; | ||
} | ||
/** | ||
* helper method that runs the command with before/afterCommand hook | ||
*/ | ||
async function runCommandWithHooks(commandName, fn, stackError, ...args) { | ||
@@ -110,19 +80,7 @@ await (0, _executeHooksWithArgs.default)(this.options.beforeCommand, [commandName, args]); | ||
} | ||
/** | ||
* isNotInFiber | ||
* if element or its parent has element id then we are in parent's Fiber | ||
* @param {object} context browser or element | ||
* @param {string} fnName function name | ||
*/ | ||
function isNotInFiber(context, fnName) { | ||
return fnName !== '' && !!(context.elementId || context.parent && context.parent.elementId); | ||
} | ||
/** | ||
* set `_NOT_FIBER` to `false` for element and its parents | ||
* @param {object} context browser or element | ||
*/ | ||
function inFiber(context) { | ||
@@ -129,0 +87,0 @@ context._NOT_FIBER = false; |
{ | ||
"name": "@wdio/sync", | ||
"version": "5.11.11", | ||
"version": "5.11.13", | ||
"description": "A WebdriverIO plugin. Helper module to run WebdriverIO commands synchronously", | ||
@@ -44,3 +44,3 @@ "author": "Christian Bromann <christian@saucelabs.com>", | ||
}, | ||
"gitHead": "edf3ebf2f7ed4cbe2c041926c0c24ffbe19e320b" | ||
"gitHead": "840579acb9ba9de6d020e7fe9d227941524cc2f5" | ||
} |
@@ -142,10 +142,2 @@ /// <reference types="node"/> | ||
afterTest?(test: Test): void; | ||
// cucumber specific hooks | ||
beforeFeature?(uri: any, feature: any): void; | ||
beforeScenario?(uri: any, feature: any, scenario: any): void; | ||
beforeStep?(uri: any, feature: any, scenario: any, step: any): void; | ||
afterFeature?(uri: any, feature: any, scenario: any, step: any, result: any): void; | ||
afterScenario?(uri: any, feature: any, scenario: any, result: {status: string, duration: number}): void; | ||
afterStep?(uri: any, feature: any): void; | ||
} | ||
@@ -169,2 +161,4 @@ type _HooksArray = { | ||
interface Element { | ||
"element-6066-11e4-a52e-4f735466cecf"?: string; | ||
ELEMENT?: string; | ||
selector: string; | ||
@@ -171,0 +165,0 @@ elementId: string; |
23880
673