UNPKG

5.41 kBJavaScriptView Raw
1'use strict';
2
3const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
4const perfLogger = require('../commons/performance-logger');
5const { guid } = require('../utils');
6const { getArgumentsFromContext } = require('../codim/hybrid-utils');
7const { AbortError } = require("../commons/AbortError");
8
9module.exports.execute = async function executeTdkFunction(player, hybridFunction, context, loginData, frameManager, step, source, abortSignal) {
10 function onAbort() {
11 player.sessionPlayer.stopPlaying();
12 }
13
14 abortSignal.addEventListener("abort", onAbort);
15
16 function getLocator(arg) {
17 if (step.parameterValues) { // tdk is all grown up and can run real locators
18 const locateStep = step.parameterValues.find(param => param.type === 'locate' && param.id === arg.locatorId);
19 return { elementLocator: locateStep.elementLocator , id: locateStep.id, name: 'Hybrid Step Locator' };
20 }
21 if (!arg.locatedElement.shadowPath) {
22 return arg; // wat
23 }
24 // fallback to selector, this should never happen in practice except when there was
25 // no locator to begin with (like if we expose reverse-hybrid to TDK)
26 return arg.locatedElement.shadowPath[0];
27 }
28 const args = await getArgumentsFromContext(step, context, getLocator);
29 const fn = hybridFunction.bind(null, ...args);
30
31 // assign same framemanager
32 const testId = guid();
33 const executionId = guid(); // we don't use the same execution ID to not associate the run with the suite and trigger bugs in features like "rerun by failed run id"
34 const resultId = context.testResultId; // this isn't the TDK result id - it's the _parent_ result ID tdk nests under.
35 const baseUrl = context.config.baseUrl;
36 const userData = _.cloneDeep(context); // the context contains everything needed as userData except login data
37 userData.loginData = loginData;
38 const version = sessionPlayerInit.manifestVersion || 'runner';
39 const isLocalRun = false;
40 const overrideTestConfigId = null;
41 const branch = 'master'; // With TDK - branches are meaningless
42 const testName = `Execute TDK Function '${step.functionName}'`;
43 const ignoreNavigation = true;
44
45
46 const codeTest = {
47 fn,
48 bypassSetup: true, // don't setup and resize according to the TestConfig when starting
49 isBeforeOrAfterTest: true, // not a full test - don't perform "must contain assertions" validation
50 name: testName,
51 sourceCode: fn.toString(),
52 sourceName: fn.name,
53 testId,
54 resultId: guid() // we don't want to reuse the resultId of the parent for the child - we need a new resultId
55 };
56 const onlyLocalReporting = typeof hybridFunction.results === 'boolean' && !hybridFunction.results;
57 try {
58 perfLogger.log('tdkHybridStepPlayback before addAllTabs');
59 if (frameManager) { // we have a frameManager we can reuse
60 player.sessionPlayer.playbackAutUtils.frameManager = player.sessionPlayer.frameManager = frameManager;
61 } else {
62 // otherwise, we have to tell the session player about them tabs
63 //TODO(benji) call getEditorUrl?
64 await player.addAllTabs(null, { loadInfo: true, checkForMainTab: true, takeScreenshots: !onlyLocalReporting }, [player.driver.initialUrl]);
65 }
66 player.sessionPlayer.playbackManager.dontAssociateChildResult = true; // don't associate child result to this test result.
67 player.sessionPlayer.playbackManager.onlyLocalReporting = onlyLocalReporting;
68 perfLogger.log('tdkHybridStepPlayback before playTestByCode');
69 const testResult = await new Promise((resolve, reject) => {
70 if (source === 'agent') {
71 resolveOnTestResultAndNotAssetsUploaded(player, resolve);
72 }
73 function onAbort() {
74 reject(new AbortError());
75 abortSignal.removeEventListener("abort", onAbort);
76 }
77
78 abortSignal.addEventListener("abort", onAbort);
79
80 player.sessionPlayer.playTestByCode(testId, executionId, resultId, baseUrl, userData, version, resolve, isLocalRun, overrideTestConfigId, branch, [codeTest], testName, ignoreNavigation).catch(reject);
81
82 });
83 perfLogger.log('tdkHybridStepPlayback after playTestByCode');
84 // testResult.status?
85 return { success: testResult.success, shouldRetry: false, resultInfo: { testId, executionId, resultId: codeTest.resultId } };
86 } catch (e) {
87 return { success: false, error: e, shouldRetry: false }
88 } finally {
89 abortSignal.removeEventListener("abort", onAbort);
90 }
91};
92
93function resolveOnTestResultAndNotAssetsUploaded(player, resolve) {
94 const { commonConstants } = require('../commons/getSessionPlayerRequire');
95 player.sessionPlayer.playbackManager.on(commonConstants.playback.START, ({testResult}) => {
96 let runnerStatus = testResult.runnerStatus;
97 Object.defineProperty(testResult, 'runnerStatus', {
98 get() { return runnerStatus },
99 set(value) {
100 runnerStatus = value;
101 if (value === 'FINISHED') {
102 // resolve as soon as the runner is finished, before assets are uploaded
103 resolve(testResult);
104 }
105 }
106 });
107 });
108}