@testim/testim-cli 3.241.0 → 3.242.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.241.0",
3
+ "version": "3.242.0",
4
4
  "description": "Command line interface for running Testing on your CI",
5
5
  "author": "Oren Rubin",
6
6
  "contributors": [{
@@ -47,8 +47,8 @@
47
47
  "multer": "1.4.4"
48
48
  },
49
49
  "dependencies": {
50
- "@applitools/eyes-sdk-core": "13.2.0",
51
- "@applitools/visual-grid-client": "15.11.0",
50
+ "@applitools/eyes-sdk-core": "13.6.23",
51
+ "@applitools/visual-grid-client": "15.12.34",
52
52
  "@testim/coralogix-logger": "1.1.27-beta.1",
53
53
  "@testim/webdriverio": "0.0.5",
54
54
  "abort-controller": "3.0.0",
@@ -1,12 +1,11 @@
1
- "use strict";
2
- var COMMUNICATION_BUFFER_TIME = 1000;
1
+ 'use strict';
2
+
3
3
  const _ = require('lodash');
4
- const logger = require('../../commons/logger').getLogger('playback-timeout-calculator');
5
4
 
6
- let warnedAboutDebugger = false;
5
+ const COMMUNICATION_BUFFER_TIME = 1000;
6
+ const UI_VERIFICATION_STEPS = ['simple-ui-verification', 'wait-for-simple-ui-verification'];
7
7
 
8
8
  class PlaybackTimeoutCalculator {
9
-
10
9
  constructor(isDebuggerConnected) {
11
10
  this.resetStepVariables();
12
11
  this.resetRetryVariables();
@@ -18,13 +17,13 @@ class PlaybackTimeoutCalculator {
18
17
  this.totalStepTime = totalStepTime || 0;
19
18
  this.totalStepTimesReport = [];
20
19
  this.currentRetryTimesReport = {};
21
- var now = Date.now();
20
+ const now = Date.now();
22
21
  this.currentRetryStart = now;
23
22
  this.lastUpdateTime = now;
24
23
  }
25
24
 
26
25
  resetRetryVariables() {
27
- var now = Date.now();
26
+ const now = Date.now();
28
27
  this.currentRetryStart = now;
29
28
  this.lastUpdateTime = now;
30
29
  this.totalStepTimesReport.push(this.currentRetryTimesReport);
@@ -32,7 +31,7 @@ class PlaybackTimeoutCalculator {
32
31
  }
33
32
 
34
33
  initStepRun(stepPlayback) {
35
- var getRetryTimeoutSuggestions = (totalStepTime) => {
34
+ const getRetryTimeoutSuggestions = (totalStepTime) => {
36
35
  const timeToPlayStep = this.getTotalStepTimeLeftToPlay(stepPlayback, totalStepTime);
37
36
  const MINIMAL_RETRY_TIME = 5000;
38
37
  if (timeToPlayStep <= MINIMAL_RETRY_TIME) {
@@ -42,7 +41,7 @@ class PlaybackTimeoutCalculator {
42
41
  };
43
42
  stepPlayback.setStartTimestamp();
44
43
  const totalStepTime = this.getTotalStepRunTime(stepPlayback);
45
- var currentRetryTimes = ["simple-ui-verification", "wait-for-simple-ui-verification", "custom-validation"].includes(stepPlayback.stepType) ? [totalStepTime] : getRetryTimeoutSuggestions(totalStepTime);
44
+ const currentRetryTimes = [...UI_VERIFICATION_STEPS, 'custom-validation'].includes(stepPlayback.stepType) ? [totalStepTime] : getRetryTimeoutSuggestions(totalStepTime);
46
45
  this.resetStepVariables(totalStepTime, currentRetryTimes);
47
46
  stepPlayback.context.data.maxTotalStepTime = totalStepTime;
48
47
  }
@@ -57,9 +56,12 @@ class PlaybackTimeoutCalculator {
57
56
  }
58
57
 
59
58
  getTotalStepRunTime(stepPlayback) {
60
- return (stepPlayback.step.useStepTimeout && stepPlayback.step.stepTimeout) ?
61
- stepPlayback.step.stepTimeout :
62
- stepPlayback.context.config.stepTimeout;
59
+ const HALF_HOUR_IN_MS = 30 * 60 * 1000;
60
+ let fallbackTimeout = stepPlayback.context.config.stepTimeout;
61
+ if (UI_VERIFICATION_STEPS.includes(stepPlayback.stepType)) {
62
+ fallbackTimeout = stepPlayback.context.config.applitoolsStepTimeout || HALF_HOUR_IN_MS;
63
+ }
64
+ return (stepPlayback.step.useStepTimeout && stepPlayback.step.stepTimeout) ? stepPlayback.step.stepTimeout : fallbackTimeout;
63
65
  }
64
66
  getTotalStepTimeLeftToPlay(stepPlayback, totalStepTime = this.totalStepTime) {
65
67
  const playTimeSoFar = Date.now() - stepPlayback.startTimestamp;
@@ -71,7 +73,7 @@ class PlaybackTimeoutCalculator {
71
73
  this.getTotalStepTimeLeftToPlay(stepPlayback);
72
74
  }
73
75
  getTotalCurrentRetryTimeLeft(stepPlayback) {
74
- var totalRetryTime = Date.now() - this.currentRetryStart;
76
+ const totalRetryTime = Date.now() - this.currentRetryStart;
75
77
  return this.getCurrentRetryTime(stepPlayback) - totalRetryTime + COMMUNICATION_BUFFER_TIME;
76
78
  }
77
79
  getTabTimeout(stepPlayback) {
@@ -97,7 +99,6 @@ class PlaybackTimeoutCalculator {
97
99
  }
98
100
 
99
101
  return (stepPlayback.step.events.length * timePerEvent) + buffer;
100
-
101
102
  }
102
103
 
103
104
  getActionTimeout(stepPlayback) {
@@ -108,10 +109,10 @@ class PlaybackTimeoutCalculator {
108
109
  const actionType = stepPlayback.step.type;
109
110
  const MIN_ACTION_PLAYBACK_TIME = 30000;
110
111
 
111
- var actionTime;
112
- if (actionType === "sleep") {
112
+ let actionTime;
113
+ if (actionType === 'sleep') {
113
114
  actionTime = stepPlayback.step.durationMS + SLEEP_ERROR_MARGIN_MS;
114
- } else if (actionType === "android-scroll") {
115
+ } else if (actionType === 'android-scroll') {
115
116
  actionTime = Math.max(this.calcAndroidScrollTimeout(stepPlayback), MIN_ACTION_PLAYBACK_TIME);
116
117
  } else {
117
118
  actionTime = Math.max(this.getTotalStepTimeLeftToPlay(stepPlayback), MIN_ACTION_PLAYBACK_TIME);
@@ -120,34 +121,34 @@ class PlaybackTimeoutCalculator {
120
121
  }
121
122
 
122
123
  setStepPhaseTime(phase) {
123
- var now = Date.now();
124
- var totalTime = now - this.lastUpdateTime;
124
+ const now = Date.now();
125
+ const totalTime = now - this.lastUpdateTime;
125
126
  this.lastUpdateTime = now;
126
127
  this.currentRetryTimesReport[phase] = totalTime;
127
128
  }
128
129
 
129
130
  reportGetTabTime() {
130
- this.setStepPhaseTime("tab");
131
+ this.setStepPhaseTime('tab');
131
132
  }
132
133
 
133
134
  reportGetFrameTime() {
134
- this.setStepPhaseTime("frame");
135
+ this.setStepPhaseTime('frame');
135
136
  }
136
137
 
137
138
  reportCalcConditionTime() {
138
- this.setStepPhaseTime("condition");
139
+ this.setStepPhaseTime('condition');
139
140
  }
140
141
 
141
142
  reportPreLocateActionsTime() {
142
- this.setStepPhaseTime("pre-locate");
143
+ this.setStepPhaseTime('pre-locate');
143
144
  }
144
145
 
145
146
  reportFindElementsTime() {
146
- this.setStepPhaseTime("locate");
147
+ this.setStepPhaseTime('locate');
147
148
  }
148
149
 
149
150
  reportStepActionTime() {
150
- this.setStepPhaseTime("action");
151
+ this.setStepPhaseTime('action');
151
152
  }
152
153
  }
153
154
 
package/processHandler.js CHANGED
@@ -2,18 +2,18 @@
2
2
 
3
3
  'use strict';
4
4
 
5
+ const Promise = require('bluebird');
5
6
  const logger = require('./commons/logger').getLogger('process-handler');
6
7
 
7
8
  const exitHooks = [];
8
- const Promise = require('bluebird');
9
9
 
10
- module.exports = function (onExit) {
10
+ module.exports = function (onExit, _process = process) {
11
11
  async function cleanup(err) {
12
12
  // give cleanup and socket reports a chance to run
13
13
  await Promise.all(exitHooks.map(x => x())).timeout(10000).catch(() => {});
14
14
  onExit(err);
15
15
  }
16
- process.on('uncaughtException', async (err) => {
16
+ _process.on('uncaughtException', async (err) => {
17
17
  logger.error('Caught exception', { err });
18
18
  console.log('Uncaught exception');
19
19
  if (err.message) {
@@ -25,7 +25,7 @@ module.exports = function (onExit) {
25
25
  await cleanup(err);
26
26
  });
27
27
 
28
- process.on('unhandledRejection', (reason) => {
28
+ _process.on('unhandledRejection', (reason) => {
29
29
  // rollout manages promises incorrectly and generates unhandled rejections from within their code
30
30
  logger.fatal('Caught unhandled promise rejection', reason);
31
31
  //TODO(benji) - this is a pretty shitty way to detect this error since rollout can change their API endpoint
@@ -37,11 +37,11 @@ module.exports = function (onExit) {
37
37
  throw reason;
38
38
  });
39
39
 
40
- process.on('rejectionHandled', () => {
40
+ _process.on('rejectionHandled', () => {
41
41
  logger.error('Caught rejection handled');
42
42
  });
43
43
 
44
- process.once('SIGTERM', () => {
44
+ _process.once('SIGTERM', () => {
45
45
  const msg = 'Runner aborted - SIGTERM event';
46
46
  const err = new Error(msg);
47
47
  logger.error(msg);
@@ -49,7 +49,7 @@ module.exports = function (onExit) {
49
49
  throw err;
50
50
  });
51
51
 
52
- process.once('SIGINT', () => {
52
+ _process.once('SIGINT', () => {
53
53
  const msg = 'Runner aborted - SIGINT event';
54
54
  const err = new Error(msg);
55
55
  logger.error(msg);
@@ -58,12 +58,15 @@ module.exports = function (onExit) {
58
58
  });
59
59
 
60
60
  // One time self-call is expected :(
61
- process.once('exit', (e) => {
61
+ _process.once('exit', (e) => {
62
62
  onExit(e);
63
63
  });
64
64
  };
65
65
 
66
-
67
66
  module.exports.registerExitHook = function (hook) {
68
67
  exitHooks.push(hook);
69
68
  };
69
+
70
+ module.exports.reset = function () {
71
+ exitHooks.splice(0, exitHooks.length);
72
+ };
@@ -0,0 +1,56 @@
1
+
2
+ const { delay } = require('bluebird');
3
+ const EventEmitter = require('events');
4
+ const { expect, sinon } = require('../test/utils/testUtils');
5
+ const processHandler = require('./processHandler');
6
+
7
+
8
+ class Process extends EventEmitter {
9
+ constructor() {
10
+ super();
11
+ this.stdout = new EventEmitter();
12
+ this.stderr = new EventEmitter();
13
+ }
14
+ }
15
+
16
+ describe('testimTunnel', () => {
17
+ let process;
18
+ let onExitMock;
19
+
20
+ beforeEach(() => {
21
+ process = new Process();
22
+ onExitMock = sinon.spy();
23
+ processHandler(onExitMock, process);
24
+ });
25
+
26
+ afterEach(async () => {
27
+ await delay(10);
28
+ expect(onExitMock).to.have.been.calledOnce;
29
+ processHandler.reset();
30
+ });
31
+
32
+
33
+ it('should register a SIGTERM handler', (done) => {
34
+ processHandler.registerExitHook(done);
35
+ expect(() => process.emit('SIGTERM')).to.throw('Runner aborted - SIGTERM event');
36
+ });
37
+ it('should register a SIGINT handler', (done) => {
38
+ processHandler.registerExitHook(done);
39
+ expect(() => process.emit('SIGINT')).to.throw('Runner aborted - SIGINT event');
40
+ });
41
+ it('should register a unhandledRejection handler', () => {
42
+ expect(() => process.emit('unhandledRejection', new Error('reason'))).to.throw('reason');
43
+ onExitMock();
44
+ });
45
+ it('should register a uncaughtException handler', (done) => {
46
+ processHandler.registerExitHook(done);
47
+ expect(() => process.emit('uncaughtException', new Error())).not.to.throw();
48
+ });
49
+ it('should do nothing on rejectionHandled', () => {
50
+ expect(() => process.emit('rejectionHandled')).not.to.throw();
51
+ onExitMock();
52
+ });
53
+ it('should register a exit handler', () => {
54
+ expect(() => process.emit('exit')).not.to.throw();
55
+ });
56
+ });