Skip to content

Commit

Permalink
Timeout operation priority according to the source (#3127)
Browse files Browse the repository at this point in the history
* give set step timeout operation priority according to the source of the operation

* fix javadoc

* renamve stepTimeout force parameter to overrideTimeLimitsInCode

* rename timeout source to timeout order, rename step totalTimeout to timeout

* update def and doc

* update comments and jsdoc

* use overrideStepLimits for force override

* introduce constants for timeout orders
  • Loading branch information
nikocanvacom committed Nov 16, 2021
1 parent 4dfb575 commit 9f0ca05
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 14 deletions.
8 changes: 4 additions & 4 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -579,9 +579,9 @@ Run tests with plugin enabled:
#### Configuration:
- `retries` - number of retries (by default 5),
- `retries` - number of retries (by default 3),
- `when` - function, when to perform a retry (accepts error as parameter)
- `factor` - The exponential factor to use. Default is 2.
- `factor` - The exponential factor to use. Default is 1.5.
- `minTimeout` - The number of milliseconds before starting the first retry. Default is 1000.
- `maxTimeout` - The maximum number of milliseconds between two retries. Default is Infinity.
- `randomize` - Randomizes the timeouts by multiplying with a factor between 1 to 2. Default is false.
Expand Down Expand Up @@ -898,7 +898,7 @@ Run tests with plugin enabled:
#### Configuration:
- `timeout` - global step timeout, default 150 seconds
- `force` - whether to use timeouts set in plugin config to override step timeouts set in code with I.limitTime(x).action(...), default false
- `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with I.limitTime(x).action(...), default false
- `noTimeoutSteps` - an array of steps with no timeout. Default:
- `amOnPage`
Expand All @@ -915,7 +915,7 @@ Run tests with plugin enabled:
plugins: {
stepTimeout: {
enabled: true,
force: true,
overrideStepLimits: true,
noTimeoutSteps: [
'scroll*', // ignore all scroll steps
/Cookie/, // ignore all steps with a Cookie in it (by regexp)
Expand Down
4 changes: 2 additions & 2 deletions lib/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Actor {

event.dispatcher.prependOnceListener(event.step.before, (step) => {
output.log(`Timeout to ${step}: ${timeout}s`);
step.totalTimeout = timeout * 1000;
step.setTimeout(timeout * 1000, Step.TIMEOUT_ORDER.codeLimitTime);
});

return this;
Expand Down Expand Up @@ -132,7 +132,7 @@ function recordStep(step, args) {
step.startTime = Date.now();
}
return val = step.run(...args);
}, false, undefined, step.totalTimeout);
}, false, undefined, step.getTimeout());

event.emit(event.step.after, step);

Expand Down
5 changes: 3 additions & 2 deletions lib/listener/timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const output = require('../output');
const recorder = require('../recorder');
const Config = require('../config');
const { timeouts } = require('../store');
const TIMEOUT_ORDER = require('../step').TIMEOUT_ORDER;

module.exports = function () {
let timeout;
Expand Down Expand Up @@ -49,9 +50,9 @@ module.exports = function () {
if (typeof timeout !== 'number') return;

if (timeout < 0) {
step.totalTimeout = 0.01;
step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite);
} else {
step.totalTimeout = timeout;
step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite);
}
});

Expand Down
9 changes: 5 additions & 4 deletions lib/plugin/stepTimeout.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const event = require('../event');
const TIMEOUT_ORDER = require('../step').TIMEOUT_ORDER;

const defaultConfig = {
timeout: 150,
force: false,
overrideStepLimits: false,
noTimeoutSteps: [
'amOnPage',
'wait*',
Expand Down Expand Up @@ -33,7 +34,7 @@ const defaultConfig = {
* #### Configuration:
*
* * `timeout` - global step timeout, default 150 seconds
* * `force` - whether to use timeouts set in plugin config to override step timeouts set in code with I.limitTime(x).action(...), default false
* * `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with I.limitTime(x).action(...), default false
* * `noTimeoutSteps` - an array of steps with no timeout. Default:
* * `amOnPage`
* * `wait*`
Expand All @@ -49,7 +50,7 @@ const defaultConfig = {
* plugins: {
* stepTimeout: {
* enabled: true,
* force: true,
* overrideStepLimits: true,
* noTimeoutSteps: [
* 'scroll*', // ignore all scroll steps
* /Cookie/, // ignore all steps with a Cookie in it (by regexp)
Expand Down Expand Up @@ -85,6 +86,6 @@ module.exports = (config) => {
}
}
stepTimeout = stepTimeout === undefined ? config.timeout : stepTimeout;
step.totalTimeout = stepTimeout * 1000;
step.setTimeout(stepTimeout * 1000, config.overrideStepLimits ? TIMEOUT_ORDER.stepTimeoutHard : TIMEOUT_ORDER.stepTimeoutSoft);
});
};
59 changes: 57 additions & 2 deletions lib/step.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ const STACK_LINE = 4;
* @param {string} name
*/
class Step {
static get TIMEOUT_ORDER() {
return {
/**
* timeouts set with order below zero only override timeouts of higher order if their value is smaller
*/
testOrSuite: -5,
/**
* 0-9 - designated for override of timeouts set from code, 5 is used by stepTimeout plugin when stepTimeout.config.overrideStepLimits=true
*/
stepTimeoutHard: 5,
/**
* 10-19 - designated for timeouts set from code, 15 is order of I.setTimeout(t) operation
*/
codeLimitTime: 15,
/**
* 20-29 - designated for timeout settings which could be overriden in tests code, 25 is used by stepTimeout plugin when stepTimeout.config.overrideStepLimits=false
*/
stepTimeoutSoft: 25,
};
}

constructor(helper, name) {
/** @member {string} */
this.actor = 'I'; // I = actor
Expand All @@ -38,8 +59,40 @@ class Step {
this.metaStep = undefined;
/** @member {string} */
this.stack = '';
/** @member {number} */
this.totalTimeout = undefined;

const timeouts = new Map();
/**
* @method
* @returns {number|undefined}
*/
this.getTimeout = function () {
let totalTimeout;
// iterate over all timeouts starting from highest values of order
new Map([...timeouts.entries()].sort().reverse()).forEach((timeout, order) => {
if (timeout !== undefined && (
// when orders >= 0 - timeout value overrides those set with higher order elements
order >= 0

// when `order < 0 && totalTimeout === undefined` - timeout is used when nothing is set by elements with higher order
|| totalTimeout === undefined

// when `order < 0` - timeout overrides higher values of timeout or 'no timeout' (totalTimeout === 0) set by elements with higher order
|| timeout > 0 && (timeout < totalTimeout || totalTimeout === 0)
)) {
totalTimeout = timeout;
}
});
return totalTimeout;
};
/**
* @method
* @param {number} timeout - timeout in milliseconds or 0 if no timeout
* @param {number} order - order defines the priority of timeout, timeouts set with lower order override those set with higher order.
* When order below 0 value of timeout only override if new value is lower
*/
this.setTimeout = function (timeout, order) {
timeouts.set(order, timeout);
};

this.setTrace();
}
Expand Down Expand Up @@ -231,6 +284,8 @@ class MetaStep extends Step {
}
}

Step.TIMEOUTS = {};

/** @type {Class<MetaStep>} */
Step.MetaStep = MetaStep;

Expand Down

0 comments on commit 9f0ca05

Please sign in to comment.