1 |
|
2 | "use strict";
|
3 |
|
4 | const { sessionType } = require('../commons/constants');
|
5 | const perfLogger = require('../commons/performance-logger');
|
6 | const MemoryFS = require('memory-fs');
|
7 | const mfs = new MemoryFS();
|
8 | const AbortController = require("abort-controller");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | const runningStepsAbortControllersRegistry = new Map();
|
14 |
|
15 |
|
16 |
|
17 | let stepsProxy = undefined;
|
18 |
|
19 | module.exports.run = (driver, remoteStep, projectData, userData) => {
|
20 | const { step, context} = remoteStep.data;
|
21 | return module.exports.execute(step, context, driver, userData.loginData);
|
22 |
|
23 | }
|
24 |
|
25 |
|
26 | module.exports.execute = async function execute(step, context, driver, loginData, frameManager, source = 'cli') {
|
27 | const abortController = new AbortController();
|
28 | const { signal: abortSignal } = abortController;
|
29 |
|
30 | runningStepsAbortControllersRegistry.set(context.stepResultId, abortController);
|
31 |
|
32 | try {
|
33 | perfLogger.log('before seleniumTestPlayer require');
|
34 | const SeleniumTestPlayer = require('../player/seleniumTestPlayer');
|
35 | const { compileFunctionsLibrary } = require('../agent/routers/codim/service');
|
36 |
|
37 | const { functionName } = step;
|
38 | const userParamsData = {};
|
39 |
|
40 | const shouldMonitorPerformance = false;
|
41 | const player = new SeleniumTestPlayer(
|
42 | context.id,
|
43 | userParamsData,
|
44 | shouldMonitorPerformance,
|
45 | sessionType.CODEFUL,
|
46 | driver
|
47 | );
|
48 |
|
49 | stepsProxy = player.sessionPlayer.codeSessionPlayer.proxy;
|
50 |
|
51 |
|
52 | const bypassWebpack = step.bypassWebpack ? { testim: stepsProxy.wrappedSteps() } : false;
|
53 |
|
54 | perfLogger.log('before compileFunctionsLibrary', {bypassWebpack: Boolean(step.bypassWebpack) });
|
55 | let code;
|
56 | try {
|
57 | code = await compileFunctionsLibrary({ fileSystem: mfs, bypassWebpack }, abortSignal);
|
58 | } catch (e) {
|
59 | return { success: false, shouldRetry: false, reason: 'Unable to compile functions library. ' + e.message, extraInfo: e.stack };
|
60 | }
|
61 |
|
62 | if (typeof globalThis === 'undefined') {
|
63 | global.globalThis = process;
|
64 | }
|
65 | let hybridFunction;
|
66 | if (!bypassWebpack) {
|
67 | global.globalThis.__testim = stepsProxy.wrappedSteps();
|
68 |
|
69 |
|
70 | (0, eval)(code);
|
71 | hybridFunction = globalThis.tdk[functionName];
|
72 | } else {
|
73 | hybridFunction = code[functionName];
|
74 | }
|
75 |
|
76 | perfLogger.log('after hybridFunction obtain and eval');
|
77 | if (!hybridFunction) {
|
78 | return {
|
79 | success: false,
|
80 | shouldRetry: false,
|
81 | reason: `Could not find function '${functionName}' locally. Please make sure you have a functions.js file with a '${functionName}' function defined`,
|
82 | extraInfo: Object.keys(globalThis.tdk)
|
83 | };
|
84 | }
|
85 |
|
86 | if (hybridFunction.type === 'selenium') {
|
87 | const seleniumPlayback = require('./seleniumHybridStepPlayback').execute;
|
88 | return await seleniumPlayback(player, hybridFunction, step, context, source, abortSignal);
|
89 | }
|
90 | if (hybridFunction.type === 'puppeteer') {
|
91 | if (!player.driver.cdpUrl) {
|
92 | return { success: false, shouldRetry: false, reason: 'running puppeteer code requires the remote debugging protocol to be open. Please contact Testim support.'}
|
93 | }
|
94 | perfLogger.log('before puppeteerPlayback');
|
95 | const puppeteerPlayback = require('./puppeteerHybridStepPlayback').execute;
|
96 | try {
|
97 | return await puppeteerPlayback(player, hybridFunction, step, context, source, abortSignal);
|
98 | } finally {
|
99 | perfLogger.log('after puppeteerPlayback');
|
100 | }
|
101 | }
|
102 |
|
103 | if (hybridFunction.type === 'playwright') {
|
104 | if (!player.driver.cdpUrl) {
|
105 | return { success: false, shouldRetry: false, reason: 'running playwright code requires the remote debugging protocol to be open. Please contact Testim support.'}
|
106 | }
|
107 | const playwrightPlayback = require('./playwrightHybridStepPlayback').execute;
|
108 | return await playwrightPlayback(player, hybridFunction, step, context, source, abortSignal);
|
109 | }
|
110 |
|
111 | if (hybridFunction.type === 'tdk' || !hybridFunction.type) {
|
112 | const tdkPlayback = require('./tdkHybridStepPlayback').execute;
|
113 | perfLogger.log('before tdkPlayback');
|
114 | try {
|
115 | return await tdkPlayback(player, hybridFunction, context, loginData, frameManager, step, source, abortSignal);
|
116 | } finally {
|
117 | perfLogger.log('after tdkPlayback');
|
118 | }
|
119 | }
|
120 |
|
121 | return { success: false, shouldRetry: false, reason: 'unknown hybrid format ' + hybridFunction.type };
|
122 | } finally {
|
123 | runningStepsAbortControllersRegistry.delete(context.stepResultId);
|
124 | }
|
125 | }
|
126 |
|
127 | module.exports.abort = function abort(stepResultId) {
|
128 | const abortController = runningStepsAbortControllersRegistry.get(stepResultId);
|
129 |
|
130 | if (abortController) {
|
131 | abortController.abort();
|
132 | } else {
|
133 | throw new Error("No such stepResultId");
|
134 | }
|
135 | }
|