@devassure/tpp-engine 0.0.0-stage → 1.8.1

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.
Files changed (69) hide show
  1. package/DEV_README.md +19 -0
  2. package/README.md +6 -3
  3. package/index.js +121 -0
  4. package/package.json +30 -4
  5. package/src/accessibility/combined-a11y-report.js +208 -0
  6. package/src/accessibility/tpp-a11y.js +81 -0
  7. package/src/actions.js +3201 -0
  8. package/src/api/api-auth.js +18 -0
  9. package/src/api/api-service.js +289 -0
  10. package/src/app-config.json +7 -0
  11. package/src/autoheal-actions.js +309 -0
  12. package/src/console-log/console-log-manager.js +39 -0
  13. package/src/console-log/console-log-utils.js +201 -0
  14. package/src/database/mysql/mysql-service.js +23 -0
  15. package/src/database/neo4j/neo4j-service.js +32 -0
  16. package/src/database/oracle/oracle-service.js +48 -0
  17. package/src/database/pg/pg-service.js +29 -0
  18. package/src/downloads/downloads-manager.js +86 -0
  19. package/src/downloads/downloads-utils.js +113 -0
  20. package/src/globalsetup.js +68 -0
  21. package/src/globalteardown.js +57 -0
  22. package/src/hooks/each-hook.js +45 -0
  23. package/src/hooks/hook-utils.js +21 -0
  24. package/src/library/authenticator/authenticator-utils.js +43 -0
  25. package/src/library/csv/csv-utils.js +297 -0
  26. package/src/library/date/date-utils.js +168 -0
  27. package/src/library/emailTesting/TokenConfig.js +46 -0
  28. package/src/library/emailTesting/emailTesting-utils.js +527 -0
  29. package/src/library/excel/excel-utils.js +922 -0
  30. package/src/library/file/file-action-utils.js +129 -0
  31. package/src/library/file/file-utils.js +127 -0
  32. package/src/library/json/json-utils.js +104 -0
  33. package/src/library/math/math-utils.js +283 -0
  34. package/src/library/softAssert/softAssert-utils.js +154 -0
  35. package/src/library/table/table-utils.js +92 -0
  36. package/src/library/text/text-utils.js +45 -0
  37. package/src/library/tpp-library.js +81 -0
  38. package/src/library/web/slider-utils.js +66 -0
  39. package/src/mobile/appium/appium-manager.js +158 -0
  40. package/src/mobile/device-cloud/browserstack-service.js +44 -0
  41. package/src/mobile/device-cloud/commands/browserstack-commands.js +20 -0
  42. package/src/mobile/device-cloud/commands/device-cloud-commands.js +17 -0
  43. package/src/mobile/device-cloud/device-cloud-service.js +29 -0
  44. package/src/mobile/device-cloud/pcloudy-service.js +65 -0
  45. package/src/mobile/mobile-actions.js +1568 -0
  46. package/src/mobile/recorder-utils/css-selector-generator.js +2 -0
  47. package/src/mobile/recorder-utils/finder.js +752 -0
  48. package/src/mobile/recorder-utils/mobile-recorder.js +266 -0
  49. package/src/mobile/web-driver-utils.js +110 -0
  50. package/src/models/tpp-element.js +58 -0
  51. package/src/models/tpp-mobile-element.js +50 -0
  52. package/src/network-log/network-log-manager.js +96 -0
  53. package/src/network-log/network-log-utils.js +361 -0
  54. package/src/types/elements.types.js +24 -0
  55. package/src/utils/ai-utils.js +48 -0
  56. package/src/utils/assert-utils.js +50 -0
  57. package/src/utils/autoheal-utils.js +9 -0
  58. package/src/utils/common-utils.js +120 -0
  59. package/src/utils/cookie-utils.js +70 -0
  60. package/src/utils/json-utils.js +10 -0
  61. package/src/utils/log-utils.js +10 -0
  62. package/src/utils/logger.js +76 -0
  63. package/src/utils/screenshot-utils.js +42 -0
  64. package/src/utils/token-utils.js +18 -0
  65. package/src/utils/vectordb-utils.js +125 -0
  66. package/src/visual-test/tpp-visual-test.js +122 -0
  67. package/src/web/web-executor-agent.js +149 -0
  68. package/src/web/web-executor-data-fetch.js +353 -0
  69. package/test-excel-utils.js +570 -0
@@ -0,0 +1,361 @@
1
+ const { compare } = require("../utils/assert-utils");
2
+ const { Logger } = require("../utils/logger");
3
+
4
+ class NetworkLogUtils {
5
+
6
+ constructor(caller, blacklistedLogs, networkLogManager) {
7
+ this.caller = caller;
8
+ this.blacklistedLogs = blacklistedLogs;
9
+ this.networkLogManager = networkLogManager;
10
+ }
11
+
12
+ setCaller(caller) {
13
+ this.caller = caller;
14
+ }
15
+
16
+ setBlacklistedLogs(blacklistedLogs) {
17
+ this.blacklistedLogs = blacklistedLogs;
18
+ }
19
+
20
+ checkNetworkLogEnabled(logLabel) {
21
+ if(!this.networkLogManager?.enabled) {
22
+ if(logLabel) {
23
+ (new Logger(this.caller, this.blacklistedLogs)).failureLog(logLabel);
24
+ }
25
+ throw { message: 'Network logs tracing is not enabled! Enable it under Project preferences.' };
26
+ }
27
+ }
28
+
29
+ get_last_network_log_matching(method, url) {
30
+ const logLabel = `Get Last Network Log matching method - ${method} and urlRegex - ${url}`;
31
+ const logger = new Logger(this.caller, this.blacklistedLogs);
32
+ logger.startLog(logLabel);
33
+ this.checkNetworkLogEnabled(logLabel);
34
+ let logs = this.queryLogs({
35
+ limit: 1,
36
+ url: url,
37
+ methods: [method],
38
+ });
39
+ if(!logs?.length) {
40
+ logger.failureLog(logLabel);
41
+ throw { message: 'No network log recorded!' };
42
+ }
43
+ logger.endLog(logLabel);
44
+ return logs[0];
45
+ }
46
+
47
+ get_last_n_network_logs_matching(n, method, url) {
48
+ const logLabel = `Get Last ${n} Network Logs matching method - ${method} and urlRegex - ${url}`;
49
+ const logger = new Logger(this.caller, this.blacklistedLogs);
50
+ logger.startLog(logLabel);
51
+ this.checkNetworkLogEnabled(logLabel);
52
+ let logs = this.queryLogs({
53
+ limit: n,
54
+ url: url,
55
+ methods: [method],
56
+ });
57
+ logger.endLog(logLabel);
58
+ return logs;
59
+ }
60
+
61
+ get_all_network_logs() {
62
+ const logLabel = `Get All Network Logs`;
63
+ const logger = new Logger(this.caller, this.blacklistedLogs);
64
+ logger.startLog(logLabel);
65
+ this.checkNetworkLogEnabled(logLabel);
66
+ let logs = this.queryLogs({});
67
+ logger.endLog(logLabel);
68
+ return logs;
69
+ }
70
+
71
+ get_last_n_network_logs(n) {
72
+ const logLabel = `Get Last ${n} Network Logs`;
73
+ const logger = new Logger(this.caller, this.blacklistedLogs);
74
+ logger.startLog(logLabel);
75
+ this.checkNetworkLogEnabled(logLabel);
76
+ let logs = this.queryLogs({limit: n});
77
+ logger.endLog(logLabel);
78
+ return logs;
79
+ }
80
+
81
+ query_netwrok_logs(query) {
82
+ const logLabel = `Query Network Logs`;
83
+ const logger = new Logger(this.caller, this.blacklistedLogs);
84
+ logger.startLog(logLabel);
85
+ this.checkNetworkLogEnabled(logLabel);
86
+ let logs = this.queryLogs(query);
87
+ logger.endLog(logLabel);
88
+ return logs;
89
+ }
90
+
91
+ //Private Fn
92
+ queryLogs(query) {
93
+ let logs = this.networkLogManager?.networkLogs;
94
+ if(query?.url) {
95
+ if(query.urlComparator) {
96
+ logs = logs.filter(log => compare(log.url, query.urlComparator, query.url))
97
+ } else {
98
+ let regex;
99
+ try {
100
+ regex = new RegExp(query.url);
101
+ } catch(_ex) {};
102
+ const check = regex
103
+ ? (log) => regex.test(log.url) || log.url?.includes(query.url)
104
+ : (log) => log.url?.includes(query.url)
105
+ logs = logs.filter(check);
106
+ }
107
+ }
108
+ if(query?.methods?.length) {
109
+ logs = logs.filter(log => query.methods.some(method => log.method === method));
110
+ }
111
+ if(query?.status) {
112
+ logs = logs.filter(log => compare(log.status, query.statusComparator || '==', query.status));
113
+ }
114
+ if(query?.limit && query.limit > 0) {
115
+ logs = logs.slice(-1 * query.limit);
116
+ }
117
+ return logs
118
+ }
119
+
120
+ verify_last_network_log_status(comparator, status) {
121
+ const logLabel = `Verify Last Network Log Status ${comparator} ${status}`;
122
+ const logger = new Logger(this.caller, this.blacklistedLogs);
123
+ logger.startLog(logLabel);
124
+ this.checkNetworkLogEnabled(logLabel);
125
+ let logs = this.queryLogs({limit: 1});
126
+ if(!logs?.length) {
127
+ logger.failureLog(logLabel);
128
+ throw { message: 'No network log recorded!' };
129
+ }
130
+ if(!compare(logs[0].status, comparator, status)) {
131
+ logger.failureLog(logLabel);
132
+ throw {
133
+ message: `Status is not as expected. actual: ${logs[0].status} ---- comparator: ${comparator} ---- expected: ${status}`,
134
+ };
135
+ }
136
+ logger.endLog(logLabel);
137
+ return logs;
138
+ }
139
+
140
+ print_all_network_logs() {
141
+ const logs = this.networkLogManager?.networkLogs;
142
+ this.checkNetworkLogEnabled();
143
+ const title = `###### All network logs: (${logs?.length || 0}) ######`;
144
+ const logger = new Logger(this.caller, this.blacklistedLogs);
145
+ logger.log(undefined, title);
146
+ this.print_network_logs(logs);
147
+ }
148
+
149
+ print_network_logs(networkLog, index) {
150
+ const logger = new Logger(this.caller, this.blacklistedLogs);
151
+ if(Array.isArray(networkLog)) {
152
+ networkLog?.forEach((log, i) => this.print_network_logs(log, i));
153
+ return;
154
+ } else if(!networkLog || typeof networkLog !== "object") {
155
+ logger.log(undefined, 'Invalid network log!!');
156
+ return;
157
+ }
158
+ const title = index == null
159
+ ? "---------------------------------NETWORK LOG---------------------------------"
160
+ : `-- ${index + 1} -------------------------------------------------------------------------`
161
+ logger.log(undefined, title);
162
+ let content = JSON.stringify(networkLog, undefined, 4);
163
+ content.split('\n').forEach(line => logger.log(undefined, line));
164
+ logger.log(undefined, "_______________________________________________________________________________");
165
+ }
166
+
167
+ network_log_or_last_in_array(networkLog, logLabel) {
168
+ const logger = new Logger(this.caller, this.blacklistedLogs);
169
+ if(!networkLog) {
170
+ logger.failureLog(logLabel);
171
+ throw { message: 'Invalid network log object!' };
172
+ }
173
+ if(Array.isArray(networkLog)) {
174
+ if(!networkLog?.length) {
175
+ logger.failureLog(logLabel);
176
+ throw { message: 'Network logs is empty!' };
177
+ }
178
+ let log = networkLog.at(-1);
179
+ if(!log) {
180
+ logger.failureLog(logLabel);
181
+ throw { message: 'Invalid network logs!' };
182
+ }
183
+ return log;
184
+ }
185
+ return networkLog;
186
+ }
187
+
188
+ get_network_log_method(networkLog) {
189
+ const logLabel = `Get Network Log method`;
190
+ const logger = new Logger(this.caller, this.blacklistedLogs);
191
+ logger.startLog(logLabel);
192
+ this.checkNetworkLogEnabled(logLabel);
193
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
194
+ logger.endLog(logLabel);
195
+ return log.method;
196
+ }
197
+
198
+ get_network_log_status(networkLog) {
199
+ const logLabel = `Get Network Log status`;
200
+ const logger = new Logger(this.caller, this.blacklistedLogs);
201
+ logger.startLog(logLabel);
202
+ this.checkNetworkLogEnabled(logLabel);
203
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
204
+ logger.endLog(logLabel);
205
+ return log.status;
206
+ }
207
+
208
+ get_network_log_url(networkLog) {
209
+ const logLabel = `Get Network Log URL`;
210
+ const logger = new Logger(this.caller, this.blacklistedLogs);
211
+ logger.startLog(logLabel);
212
+ this.checkNetworkLogEnabled(logLabel);
213
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
214
+ logger.endLog(logLabel);
215
+ return log.url;
216
+ }
217
+
218
+ get_network_log_request_headers(networkLog) {
219
+ const logLabel = `Get Network Log request headers`;
220
+ const logger = new Logger(this.caller, this.blacklistedLogs);
221
+ logger.startLog(logLabel);
222
+ this.checkNetworkLogEnabled(logLabel);
223
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
224
+ logger.endLog(logLabel);
225
+ return log.headers;
226
+ }
227
+
228
+ get_network_log_response_headers(networkLog) {
229
+ const logLabel = `Get Network Log response headers`;
230
+ const logger = new Logger(this.caller, this.blacklistedLogs);
231
+ logger.startLog(logLabel);
232
+ this.checkNetworkLogEnabled(logLabel);
233
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
234
+ logger.endLog(logLabel);
235
+ return log.responseHeaders;
236
+ }
237
+
238
+ get_network_log_request_payload(networkLog) {
239
+ const logLabel = `Get Network Log request payload`;
240
+ const logger = new Logger(this.caller, this.blacklistedLogs);
241
+ logger.startLog(logLabel);
242
+ this.checkNetworkLogEnabled(logLabel);
243
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
244
+ logger.endLog(logLabel);
245
+ return log.requestPayload || '';
246
+ }
247
+
248
+ get_network_log_response_body(networkLog) {
249
+ const logLabel = `Get Network Log response body`;
250
+ const logger = new Logger(this.caller, this.blacklistedLogs);
251
+ logger.startLog(logLabel);
252
+ this.checkNetworkLogEnabled(logLabel);
253
+ let log = this.network_log_or_last_in_array(networkLog, logLabel)
254
+ logger.endLog(logLabel);
255
+ return log.responseBody || '';
256
+ }
257
+
258
+ get_all_web_socket_request_logs() {
259
+ const logLabel = `Get All Web Socket Request Logs`;
260
+ const logger = new Logger(this.caller, this.blacklistedLogs);
261
+ logger.startLog(logLabel);
262
+ this.checkNetworkLogEnabled(logLabel);
263
+ let logs = this.networkLogManager?.webSocketRequestLogs;
264
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp);
265
+ logger.endLog(logLabel);
266
+ return logs;
267
+ }
268
+
269
+ get_all_web_socket_response_logs() {
270
+ const logLabel = `Get All Web Socket Response Logs`;
271
+ const logger = new Logger(this.caller, this.blacklistedLogs);
272
+ logger.startLog(logLabel);
273
+ this.checkNetworkLogEnabled(logLabel);
274
+ let logs = this.networkLogManager?.webSocketResponseLogs;
275
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp);
276
+ logger.endLog(logLabel);
277
+ return logs;
278
+ }
279
+
280
+ get_all_open_web_sockets() {
281
+ const logLabel = `Get All Open Web Sockets`;
282
+ const logger = new Logger(this.caller, this.blacklistedLogs);
283
+ logger.startLog(logLabel);
284
+ this.checkNetworkLogEnabled(logLabel);
285
+ let logs = this.networkLogManager?.openWebSockets;
286
+ logger.endLog(logLabel);
287
+ return logs;
288
+ }
289
+
290
+ get_all_closed_web_sockets() {
291
+ const logLabel = `Get All Closed Web Sockets`;
292
+ const logger = new Logger(this.caller, this.blacklistedLogs);
293
+ logger.startLog(logLabel);
294
+ this.checkNetworkLogEnabled(logLabel);
295
+ let logs = this.networkLogManager?.closedWebSockets;
296
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp);
297
+ logger.endLog(logLabel);
298
+ return logs;
299
+ }
300
+
301
+ get_all_web_socket_requests_matching(url) {
302
+ const logLabel = `Get All Web Socket Requests Matching URL - ${url}`;
303
+ const logger = new Logger(this.caller, this.blacklistedLogs);
304
+ logger.startLog(logLabel);
305
+ this.checkNetworkLogEnabled(logLabel);
306
+ let logs = this.networkLogManager?.webSocketRequestLogs.filter(log => this.isUrlMatching(log.url, url));
307
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp);
308
+ logger.endLog(logLabel);
309
+ return logs;
310
+ }
311
+
312
+ get_all_web_socket_responses_matching(url) {
313
+ const logLabel = `Get All Web Socket Responses Matching URL - ${url}`;
314
+ const logger = new Logger(this.caller, this.blacklistedLogs);
315
+ logger.startLog(logLabel);
316
+ this.checkNetworkLogEnabled(logLabel);
317
+ let logs = this.networkLogManager?.webSocketResponseLogs.filter(log => this.isUrlMatching(log.url, url));
318
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp);
319
+ logger.endLog(logLabel);
320
+ return logs;
321
+ }
322
+
323
+ get_last_n_web_socket_requests_matching(n, url) {
324
+ const logLabel = `Get Last ${n} Web Socket Requests Matching URL - ${url}`;
325
+ const logger = new Logger(this.caller, this.blacklistedLogs);
326
+ logger.startLog(logLabel);
327
+ this.checkNetworkLogEnabled(logLabel);
328
+ let logs = this.networkLogManager?.webSocketRequestLogs?.filter(log => this.isUrlMatching(log.url, url));
329
+ // Sort ascending by timestamp, then take the last n elements
330
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp)?.slice(-n);
331
+ logger.endLog(logLabel);
332
+ return logs;
333
+ }
334
+
335
+ //get last n logs based on timestamp and return in ascending order of timestamp
336
+ get_last_n_web_socket_responses_matching(n, url) {
337
+ const logLabel = `Get Last ${n} Web Socket Responses Matching URL - ${url}`;
338
+ const logger = new Logger(this.caller, this.blacklistedLogs);
339
+ logger.startLog(logLabel);
340
+ this.checkNetworkLogEnabled(logLabel);
341
+ let logs = this.networkLogManager?.webSocketResponseLogs?.filter(log => this.isUrlMatching(log.url, url));
342
+ // Sort ascending by timestamp, then take the last n elements
343
+ logs = logs?.sort((a, b) => a.timestamp - b.timestamp)?.slice(-n);
344
+ logger.endLog(logLabel);
345
+ return logs;
346
+ }
347
+
348
+ isUrlMatching(url, urlRegex) {
349
+ let regex;
350
+ try {
351
+ regex = new RegExp(urlRegex);
352
+ } catch(_ex) {};
353
+ const check = regex
354
+ ? regex.test(url) || url?.includes(urlRegex)
355
+ : url?.includes(urlRegex)
356
+ return check;
357
+ }
358
+
359
+ }
360
+
361
+ exports.NetworkLogUtils = NetworkLogUtils;
@@ -0,0 +1,24 @@
1
+ const ElementType = { //Optional for information and logs only
2
+ section: 'Section',
3
+ button:'Button',
4
+ input: 'Input',
5
+ checkBox: 'Check Box',
6
+ radio: 'Radio Button',
7
+ switch: 'Switch',
8
+ link: 'Link',
9
+ text: 'Text',
10
+ nav: 'Nav',
11
+ };
12
+
13
+ const LocatorType = {
14
+ name: 'name',
15
+ id: 'id',
16
+ role: 'role',
17
+ text: 'text',
18
+ className: 'className',
19
+ css: 'CSS',
20
+ xpath: 'XPATH',
21
+ };
22
+
23
+ exports.ElementType = ElementType;
24
+ exports.LocatorType = LocatorType;
@@ -0,0 +1,48 @@
1
+ const TokenConfig = require("../library/emailTesting/TokenConfig");
2
+ const config = require("../app-config.json");
3
+ const WebSocket = require('ws');
4
+
5
+ const AI_ENDPOINTS = {
6
+ AUTOHEAL: "/api/v1/ws/locator_fallback",
7
+ }
8
+
9
+ const BASE_SOCKET_URL = config.aiCoreUrl;
10
+
11
+ const aiWebSocketCall = async (
12
+ path,
13
+ token,
14
+ request,
15
+ ) => {
16
+ const url = new URL(path, BASE_SOCKET_URL).toString();
17
+
18
+ return new Promise((resolve, reject) => {
19
+ let socket = new WebSocket(url);
20
+
21
+ socket.onopen = (_event) => {
22
+ socket.send(JSON.stringify({ token: token.access_token, type: token.token_type }));
23
+ socket.send((JSON.stringify({ data: request })));
24
+ };
25
+
26
+ socket.onmessage = (messageEvent) => {
27
+ const response = JSON.parse(messageEvent.data || '{}');
28
+ if(response.message !== 'ping') {
29
+ socket.close();
30
+ resolve(response);
31
+ }
32
+ }
33
+
34
+ socket.onerror = (ev) => {
35
+ socket.close();
36
+ reject(ev)
37
+ }
38
+
39
+ socket.onclose = () => {
40
+ resolve(() => {});
41
+ }
42
+ })
43
+ }
44
+
45
+ module.exports = {
46
+ AI_ENDPOINTS,
47
+ aiWebSocketCall
48
+ };
@@ -0,0 +1,50 @@
1
+ const compare = (lhs, comparator, rhs) => {
2
+ switch(comparator) {
3
+ case "equals":
4
+ case "==": return lhs == rhs;
5
+ case "equals_ignore_case": {
6
+ if(lhs == rhs) return true;
7
+ if(typeof lhs !== "string" || typeof rhs !== "string") return false;
8
+ return lhs?.toLowerCase() === rhs?.toLowerCase();
9
+ };
10
+ case "regex_match": {
11
+ if(lhs == rhs) return true;
12
+ if(typeof lhs !== "string" || typeof rhs !== "string") return false;
13
+ try {
14
+ const pattern = new RegExp(rhs);
15
+ return pattern.test(lhs);
16
+ } catch (e) {
17
+ throw {message: `Invalid regex pattern: ${e.message}`};
18
+ }
19
+ };
20
+ case "regex_not_match": {
21
+ if(lhs == rhs) return false;
22
+ if(typeof lhs !== "string" || typeof rhs !== "string") return true;
23
+ try {
24
+ const pattern = new RegExp(rhs);
25
+ return !pattern.test(lhs);
26
+ } catch (e) {
27
+ throw {message: `Invalid regex pattern: ${e.message}`};
28
+ }
29
+ };
30
+ case "not_equals":
31
+ case "!=": return lhs != rhs;
32
+ case "contains": {
33
+ if(lhs == rhs) return true;
34
+ if(typeof lhs !== "string" || typeof rhs !== "string") return false;
35
+ return lhs?.includes(rhs);
36
+ }
37
+ case "contains_ignore_case": {
38
+ if(lhs == rhs) return true;
39
+ if(typeof lhs !== "string" || typeof rhs !== "string") return false;
40
+ return lhs?.toLowerCase()?.includes(rhs?.toLowerCase());
41
+ }
42
+ case ">": return lhs > rhs;
43
+ case "<": return lhs < rhs;
44
+ case ">=": return lhs >= rhs;
45
+ case "<=": return lhs <= rhs;
46
+ default: return false;
47
+ }
48
+ };
49
+
50
+ exports.compare = compare;
@@ -0,0 +1,9 @@
1
+ const path = require('path');
2
+
3
+ const getAutohealPath = () => {
4
+ return path.join(process.cwd(), 'fallback.json');
5
+ }
6
+
7
+ module.exports = {
8
+ getAutohealPath
9
+ }
@@ -0,0 +1,120 @@
1
+ const isNumber = (str) => {
2
+ if(typeof str === "number") return true;
3
+ if(typeof str !== "string") return false;
4
+ str = str.trim();
5
+ if (str === '') return false;
6
+ return !isNaN(str);
7
+ }
8
+
9
+ const getBoolean = (str) => {
10
+ if(!str) return false;
11
+ if(str == true) return true;
12
+ if(typeof str !== "string") return false;
13
+ return str.toLowerCase() !== 'false' && str.toLowerCase() !== 'no';
14
+ }
15
+
16
+ const getAnyElements = (arr, n, ignore) => {
17
+ // Shuffling the array using Fisher-Yates (Knuth) shuffle algorithm
18
+ if(n > arr.length && !ignore) {
19
+ return {
20
+ success: false,
21
+ error: `${n} - count is greater than total size - ${arr.length}`,
22
+ }
23
+ }
24
+ let shuffled = arr.slice();
25
+ for (let i = shuffled.length - 1; i > 0; i--) {
26
+ const j = Math.floor(Math.random() * (i + 1));
27
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
28
+ }
29
+ return {
30
+ success: true,
31
+ data: shuffled.slice(0, n),
32
+ };
33
+ }
34
+
35
+ const getFirstElements = (arr, n, ignore) => {
36
+ if(n > arr.length && !ignore) {
37
+ return {
38
+ success: false,
39
+ error: `${n} - count is greater than total size - ${arr.length}`,
40
+ }
41
+ }
42
+ return {
43
+ success: true,
44
+ data: arr.slice(0, n),
45
+ };
46
+ }
47
+
48
+ const getLastElements = (arr, n, ignore) => {
49
+ if(n > arr.length && !ignore) {
50
+ return {
51
+ success: false,
52
+ error: `${n} - count is greater than total size - ${arr.length}`,
53
+ }
54
+ }
55
+ return {
56
+ success: true,
57
+ data: arr.slice(-n),
58
+ };
59
+ }
60
+
61
+ const getElementsInRange = (arr, range, ignore) => {
62
+ // Split the range string into x and y
63
+ let [x, y] = range.split('-').map(Number);
64
+
65
+ // Ensure x and y are valid indices
66
+ if (isNaN(x) || isNaN(y) || x < 0 || y < 0 || x > y) {
67
+ let message = x > y
68
+ ? 'Start is greater than End!'
69
+ : `Invalid range ${range}. Total size = ${arr.length}`;
70
+ return {success: false, error: message};
71
+ }
72
+ // Ensure x and y are within range
73
+ if ((x >= arr.length || y >= arr.length) && !ignore) {
74
+ return {success: false, error: `Invalid range ${range}. Total size = ${arr.length}`};
75
+ }
76
+
77
+ // Use slice to get elements from x to y (inclusive)
78
+ return {success: true, data: arr.slice(x, y + 1)};
79
+ }
80
+
81
+ const getElementsAtIndices = (arr, indices, ignore) => {
82
+ // Split the indices string into an array of index values
83
+ let indexArray = indices.split(',').map(Number);
84
+
85
+ // Ensure all indices are valid
86
+ for (let index of indexArray) {
87
+ if (isNaN(index) || index < 0) {
88
+ return {success: false, error: `Invalid index: ${index}`};
89
+ }
90
+ if (index >= arr.length && !ignore) {
91
+ return {success: false, error: `Invalid index: ${index}. Total size = ${arr.length}`};
92
+ }
93
+ }
94
+ if(ignore) indexArray = indexArray.filter(i => i < arr.length);
95
+
96
+ return {success: true, data: indexArray.map(index => arr[index])};
97
+ }
98
+
99
+ function generateRandomString(length = 6) {
100
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
101
+ let result = '';
102
+ for (let i = 0; i < length; i++) {
103
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
104
+ }
105
+ return result;
106
+ }
107
+
108
+ function sleep(millis) {
109
+ return new Promise((resolve) => setTimeout(resolve, millis));
110
+ }
111
+
112
+ exports.isNumber = isNumber;
113
+ exports.getAnyElements = getAnyElements;
114
+ exports.getElementsInRange = getElementsInRange;
115
+ exports.getElementsAtIndices = getElementsAtIndices;
116
+ exports.getLastElements = getLastElements;
117
+ exports.getFirstElements = getFirstElements;
118
+ exports.getBoolean = getBoolean;
119
+ exports.generateRandomString = generateRandomString;
120
+ exports.sleep = sleep;
@@ -0,0 +1,70 @@
1
+ const fs = require('fs');
2
+ const { sleep } = require('./common-utils');
3
+
4
+ const STORAGE_STATES_DIR = 'storage-states'
5
+
6
+ const writeStorageStateToFile = async (page, label) => {
7
+ const state = await page?.context()?.storageState();
8
+ if(!fs.existsSync(STORAGE_STATES_DIR)) {
9
+ fs.mkdirSync(STORAGE_STATES_DIR);
10
+ }
11
+ fs.writeFileSync(`${STORAGE_STATES_DIR}/${label}.json`, JSON.stringify(state, null, 4));
12
+ }
13
+
14
+ const loadStorageStateFromFile = async (page, label, logger, logLabel, remoteBrowserPort, customConfig) => {
15
+ const dynamicDataFile = `${STORAGE_STATES_DIR}/${label}.json`;
16
+ let state = undefined;
17
+ if(fs.existsSync(dynamicDataFile)) {
18
+ const content = fs.readFileSync(dynamicDataFile, {encoding: 'utf-8'});
19
+ try {
20
+ state = content ? JSON.parse(content) : undefined;
21
+ } catch (ex) {
22
+ logger.log(logLabel, `Invalid JSON content in cookie file ${label}.json`);
23
+ return undefined;
24
+ }
25
+ } else {
26
+ const staticCookieFile = `${STORAGE_STATES_DIR}/_STATIC_COOKIES.json`;
27
+ if(fs.existsSync(staticCookieFile)) {
28
+ const content = fs.readFileSync(staticCookieFile, {encoding: 'utf-8'});
29
+ try {
30
+ const staticCookies = state = content ? JSON.parse(content) : undefined;
31
+ state = staticCookies && staticCookies[label];
32
+ } catch (ex) {
33
+ logger.log(logLabel, `Invalid JSON content in cookie file ${label}`);
34
+ return undefined;
35
+ }
36
+ }
37
+ }
38
+ if(state) {
39
+ if(remoteBrowserPort) {
40
+ const browser = page?.context()?.browser();
41
+ const commandData = JSON.stringify({storageState: state, returnData: {fileName: label}});
42
+ console.log(`[[TPP]] [[TPP Remote-Execution COMMAND set_storage_state]] ${commandData}`);
43
+ await sleep(7000);
44
+ const newPage = browser.contexts()?.at(-1)?.pages()?.at(0);
45
+ return newPage;
46
+ }
47
+ const browser = page?.context()?.browser();
48
+ await page.close();
49
+ const viewport = page.viewportSize() || { width: 1280, height: 1024 };
50
+
51
+ let recordProp = {};
52
+ const recordVideo = customConfig?.advancedRunConfig?.recordVideo;
53
+ if(!!recordVideo?.trim() && recordVideo !== 'OFF') {
54
+ recordProp = {recordVideo: {dir: 'tpp_temp_videos'}};
55
+ }
56
+
57
+ const newContext = await browser?.newContext({
58
+ storageState: state,
59
+ viewport: viewport,
60
+ ...recordProp,
61
+ });
62
+ const newPage = await newContext?.newPage();
63
+ if(!newPage) return undefined;
64
+ return newPage;
65
+ }
66
+ return undefined;
67
+ }
68
+
69
+ exports.writeStorageStateToFile = writeStorageStateToFile;
70
+ exports.loadStorageStateFromFile = loadStorageStateFromFile;
@@ -0,0 +1,10 @@
1
+ const extractValue = (json, key) => {
2
+ const keys = key.split('.');
3
+ let value = json;
4
+ for (let i = 0; i < keys.length; i++) {
5
+ value = value[keys[i]];
6
+ }
7
+ return value;
8
+ };
9
+
10
+ exports.extractValue = extractValue;