@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,201 @@
1
+ const { compare } = require("../utils/assert-utils");
2
+ const { Logger } = require("../utils/logger");
3
+
4
+ class ConsoleLogUtils {
5
+
6
+ constructor(caller, blacklistedLogs, consoleLogManager) {
7
+ this.caller = caller;
8
+ this.blacklistedLogs = blacklistedLogs;
9
+ this.consoleLogManager = consoleLogManager;
10
+ }
11
+
12
+ setCaller(caller) {
13
+ this.caller = caller;
14
+ }
15
+
16
+ setBlacklistedLogs(blacklistedLogs) {
17
+ this.blacklistedLogs = blacklistedLogs;
18
+ }
19
+
20
+ checkConsoleLogEnabled(logLabel) {
21
+ if(!this.consoleLogManager?.enabled) {
22
+ if(logLabel) {
23
+ (new Logger(this.caller, this.blacklistedLogs)).failureLog(logLabel);
24
+ }
25
+ throw { message: 'Console logs tracing is not enabled! Enable it under Project preferences.' };
26
+ }
27
+ }
28
+
29
+ get_console_logs_matching_text(searchText) {
30
+ const logLabel = `Get Console Logs matching text - ${searchText}`;
31
+ const logger = new Logger(this.caller, this.blacklistedLogs);
32
+ logger.startLog(logLabel);
33
+ this.checkConsoleLogEnabled(logLabel);
34
+ let logs = this.queryLogs({
35
+ searchText: searchText,
36
+ });
37
+ logger.endLog(logLabel);
38
+ return logs || [];
39
+ }
40
+
41
+ get_last_console_log_matching(logType, url) {
42
+ const logLabel = `Get Last Console Log matching log type - ${logType} and sourceUrl - ${url}`;
43
+ const logger = new Logger(this.caller, this.blacklistedLogs);
44
+ logger.startLog(logLabel);
45
+ this.checkConsoleLogEnabled(logLabel);
46
+ let logs = this.queryLogs({
47
+ limit: 1,
48
+ sourceUrl: url,
49
+ logTypes: [method],
50
+ });
51
+ if(!logs?.length) {
52
+ return undefined;
53
+ }
54
+ logger.endLog(logLabel);
55
+ return logs[0];
56
+ }
57
+
58
+ get_last_n_console_logs_matching(n, logType, url) {
59
+ const logLabel = `Get Last ${n} Console Logs matching logType - ${logType} and sourceUrl - ${url}`;
60
+ const logger = new Logger(this.caller, this.blacklistedLogs);
61
+ logger.startLog(logLabel);
62
+ this.checkConsoleLogEnabled(logLabel);
63
+ let logs = this.queryLogs({
64
+ limit: n,
65
+ sourceUrl: url,
66
+ logTypes: [logType],
67
+ });
68
+ logger.endLog(logLabel);
69
+ return logs || [];
70
+ }
71
+
72
+ get_all_console_logs() {
73
+ const logLabel = `Get All Console Logs`;
74
+ const logger = new Logger(this.caller, this.blacklistedLogs);
75
+ logger.startLog(logLabel);
76
+ this.checkConsoleLogEnabled(logLabel);
77
+ let logs = this.queryLogs({});
78
+ logger.endLog(logLabel);
79
+ return logs;
80
+ }
81
+
82
+ get_last_n_console_logs(n) {
83
+ const logLabel = `Get Last ${n} Console Logs`;
84
+ const logger = new Logger(this.caller, this.blacklistedLogs);
85
+ logger.startLog(logLabel);
86
+ this.checkConsoleLogEnabled(logLabel);
87
+ let logs = this.queryLogs({limit: n});
88
+ logger.endLog(logLabel);
89
+ return logs;
90
+ }
91
+
92
+ query_console_logs(query) {
93
+ const logLabel = `Query Console Logs`;
94
+ const logger = new Logger(this.caller, this.blacklistedLogs);
95
+ logger.startLog(logLabel);
96
+ this.checkConsoleLogEnabled(logLabel);
97
+ let logs = this.queryLogs(query);
98
+ logger.endLog(logLabel);
99
+ return logs;
100
+ }
101
+
102
+ //Private Fn
103
+ queryLogs(query) {
104
+ let logs = this.consoleLogManager?.consoleLogs;
105
+ if(query?.sourceUrl) {
106
+ if(query.urlComparator) {
107
+ logs = logs.filter(log => compare(log.sourceUrl, query.urlComparator, query.sourceUrl))
108
+ } else {
109
+ let regex;
110
+ try {
111
+ regex = new RegExp(query.sourceUrl);
112
+ } catch(_ex) {};
113
+ const check = regex
114
+ ? (log) => regex.test(log.sourceUrl) || log.sourceUrl?.includes(query.sourceUrl)
115
+ : (log) => log.sourceUrl?.includes(query.sourceUrl)
116
+ logs = logs.filter(check);
117
+ }
118
+ }
119
+ if(query?.logTypes?.length) {
120
+ logs = logs.filter(log => query.logTypes.some(logType => log.type === logType));
121
+ }
122
+ if(query?.searchText) {
123
+ logs = logs.filter(log => compare(log.text?.toLowerCase(), query.textComparator || 'contains', query.searchText.toLowerCase()));
124
+ }
125
+ if(query?.limit && query.limit > 0) {
126
+ logs = logs.slice(-1 * query.limit);
127
+ }
128
+ return logs
129
+ }
130
+
131
+ print_all_console_logs() {
132
+ const logs = this.consoleLogManager?.consoleLogs;
133
+ this.checkConsoleLogEnabled();
134
+ const title = `###### All console logs: (${logs?.length || 0}) ######`;
135
+ const logger = new Logger(this.caller, this.blacklistedLogs);
136
+ logger.log(undefined, title);
137
+ this.print_console_logs(logs);
138
+ }
139
+
140
+ print_console_logs(consoleLog, index) {
141
+ const logger = new Logger(this.caller, this.blacklistedLogs);
142
+ if(Array.isArray(consoleLog)) {
143
+ consoleLog?.forEach((log, i) => this.print_console_logs(log, i));
144
+ return;
145
+ } else if(!consoleLog || typeof consoleLog !== "object") {
146
+ logger.log(undefined, 'Invalid console log!!');
147
+ return;
148
+ }
149
+ const title = index == null
150
+ ? "---------------------------------CONSOLE LOG---------------------------------"
151
+ : `-- ${index + 1} -------------------------------------------------------------------------`
152
+ logger.log(undefined, title);
153
+ let content = JSON.stringify(consoleLog, undefined, 4);
154
+ content.split('\n').forEach(line => logger.log(undefined, line));
155
+ logger.log(undefined, "_______________________________________________________________________________");
156
+ }
157
+
158
+ console_log_or_last_in_array(consoleLog, logLabel) {
159
+ const logger = new Logger(this.caller, this.blacklistedLogs);
160
+ if(!consoleLog) {
161
+ logger.failureLog(logLabel);
162
+ throw { message: 'Invalid console log object!' };
163
+ }
164
+ if(Array.isArray(consoleLog)) {
165
+ if(!consoleLog?.length) {
166
+ logger.failureLog(logLabel);
167
+ throw { message: 'Console logs is empty!' };
168
+ }
169
+ let log = consoleLog.at(-1);
170
+ if(!log) {
171
+ logger.failureLog(logLabel);
172
+ throw { message: 'Invalid console logs!' };
173
+ }
174
+ return log;
175
+ }
176
+ return consoleLog;
177
+ }
178
+
179
+ get_console_log_source_url(consoleLog) {
180
+ const logLabel = `Get Console Log Source Url`;
181
+ const logger = new Logger(this.caller, this.blacklistedLogs);
182
+ logger.startLog(logLabel);
183
+ this.checkConsoleLogEnabled(logLabel);
184
+ let log = this.console_log_or_last_in_array(consoleLog, logLabel)
185
+ logger.endLog(logLabel);
186
+ return log.sourceUrl;
187
+ }
188
+
189
+ get_console_log_text(consoleLog) {
190
+ const logLabel = `Get Console Log Text`;
191
+ const logger = new Logger(this.caller, this.blacklistedLogs);
192
+ logger.startLog(logLabel);
193
+ this.checkConsoleLogEnabled(logLabel);
194
+ let log = this.console_log_or_last_in_array(consoleLog, logLabel)
195
+ logger.endLog(logLabel);
196
+ return log.text;
197
+ }
198
+
199
+ }
200
+
201
+ exports.ConsoleLogUtils = ConsoleLogUtils;
@@ -0,0 +1,23 @@
1
+ const mysql = require('mysql2/promise');
2
+
3
+ class MySQLService {
4
+
5
+ async executeQuery(dbConfig, query, params, paramValues) {
6
+ const pool = mysql.createPool({
7
+ host: dbConfig.host,
8
+ user: dbConfig.username,
9
+ password: dbConfig.password,
10
+ port: dbConfig.port,
11
+ database: dbConfig.database,
12
+ });
13
+
14
+ for (let i = 0; i < params.length; i++) {
15
+ query = query.replace("@" + params[i].name, paramValues[i]);
16
+ }
17
+
18
+ const [rows, columnData] = await pool.query(query);
19
+ return rows;
20
+ }
21
+ }
22
+
23
+ exports.MySQLService = MySQLService;
@@ -0,0 +1,32 @@
1
+ const neo4j = require('neo4j-driver');
2
+
3
+ class Neo4jService {
4
+ async executeQuery(dbConfig, query, params, paramValues) {
5
+ const uri = `bolt://${dbConfig.host}:${dbConfig.port}`;
6
+
7
+ const driver = neo4j.driver(
8
+ uri,
9
+ neo4j.auth.basic(dbConfig.username, dbConfig.password)
10
+ );
11
+
12
+ const session = driver.session({
13
+ database: dbConfig.database || 'neo4j'
14
+ });
15
+
16
+ const queryParams = {};
17
+ for (let i = 0; i < params.length; i++) {
18
+ queryParams[params[i].name] = paramValues[i];
19
+ }
20
+
21
+ try {
22
+ const result = await session.run(query, queryParams);
23
+ const records = result.records.map(record => record.toObject());
24
+ return records;
25
+ } finally {
26
+ await session.close();
27
+ await driver.close();
28
+ }
29
+ }
30
+ }
31
+
32
+ exports.Neo4jService = Neo4jService;
@@ -0,0 +1,48 @@
1
+ const oracledb = require('oracledb');
2
+
3
+ class OracleService {
4
+
5
+ async executeQuery(dbConfig, query, params, paramValues) {
6
+ let connection;
7
+
8
+ try {
9
+ // Create connection
10
+ connection = await oracledb.getConnection({
11
+ user: dbConfig.username,
12
+ password: dbConfig.password,
13
+ connectString: `${dbConfig.host}:${dbConfig.port}/${dbConfig.service_name}`
14
+ });
15
+
16
+ // Build bind parameters object
17
+ const bindParams = {};
18
+ for (let i = 0; i < params.length; i++) {
19
+ bindParams[params[i].name] = paramValues[i];
20
+ }
21
+
22
+ // Execute query with bind parameters
23
+ const result = await connection.execute(query, bindParams, {
24
+ outFormat: oracledb.OUT_FORMAT_OBJECT, // Return rows as objects
25
+ autoCommit: true
26
+ });
27
+
28
+ return result.rows;
29
+ }
30
+ catch (err) {
31
+ throw {
32
+ message: `${err.message}`
33
+ };
34
+ }
35
+ finally {
36
+ // Always close the connection
37
+ if (connection) {
38
+ try {
39
+ await connection.close();
40
+ } catch (err) {
41
+ console.error('Error closing connection:', err);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ exports.OracleService = OracleService;
@@ -0,0 +1,29 @@
1
+ const { Pool } = require('pg');
2
+
3
+ class PostgreSQLService {
4
+
5
+ async executeQuery(dbConfig, query, params, paramValues) {
6
+ const pool = new Pool({
7
+ host: dbConfig.host,
8
+ user: dbConfig.username,
9
+ password: dbConfig.password,
10
+ port: dbConfig.port,
11
+ database: dbConfig.database,
12
+ });
13
+
14
+ // Replace named parameters with positional placeholders
15
+ for (let i = 0; i < params.length; i++) {
16
+ query = query.replace("@" + params[i].name, paramValues[i]);
17
+ }
18
+
19
+ const client = await pool.connect();
20
+ try {
21
+ const result = await client.query(query);
22
+ return result.rows;
23
+ } finally {
24
+ client.release();
25
+ }
26
+ }
27
+ }
28
+
29
+ exports.PostgreSQLService = PostgreSQLService;
@@ -0,0 +1,86 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const { Logger } = require('../utils/logger');
4
+
5
+ const DOWNLOADS_FOLDER = 'downloads';
6
+
7
+ class DownloadsManager {
8
+
9
+ constructor(downloadsConfig, page) {
10
+ this.downloads = [];
11
+ this.overwriteFile = !!downloadsConfig?.overwriteFile;
12
+ this.handleDownloads(page);
13
+ }
14
+
15
+ setCaller(caller) {
16
+ this.caller = caller;
17
+ }
18
+
19
+ handleDownloads(page) {
20
+ if(!page) {
21
+ return;
22
+ }
23
+
24
+ function getUniqueFilePath(directory, fileName, overwriteFile) {
25
+ if (!fs.existsSync(directory)) {
26
+ fs.mkdirSync(directory);
27
+ }
28
+
29
+ const ext = path.extname(fileName);
30
+ let uniqueFilePath = path.join(directory, fileName);
31
+
32
+ if(overwriteFile) {
33
+ return uniqueFilePath;
34
+ }
35
+
36
+ const baseName = path.basename(fileName, ext);
37
+ let counter = 1;
38
+ while (fs.existsSync(uniqueFilePath)) {
39
+ uniqueFilePath = path.join(directory, `${baseName} (${counter})${ext}`);
40
+ counter++;
41
+ }
42
+
43
+ return uniqueFilePath;
44
+ }
45
+
46
+ const handleDownload = async (download) => {
47
+ const fileName = download.suggestedFilename();
48
+ const filePath = getUniqueFilePath(DOWNLOADS_FOLDER, fileName, this.overwriteFile);
49
+ const logMessage = `Downloading file ${fileName}`;
50
+ const logger = new Logger(this.caller);
51
+ logger.startLog(logMessage);
52
+ try {
53
+ let doDownload = async () => {
54
+ fs.writeFileSync(filePath, "");
55
+ await download.saveAs(filePath);
56
+ logger.log(undefined, `Downloaded file saved at ${filePath}`);
57
+ logger.endLog(logMessage);
58
+ };
59
+ const promise = doDownload();
60
+ this.downloads.push({
61
+ fileName: fileName,
62
+ filePath: filePath,
63
+ promise: promise,
64
+ timestamp: Date.now(),
65
+ });
66
+ await promise;
67
+ } catch (ex) {
68
+ if(ex?.message?.includes('context or browser has been closed')) {
69
+ logger.log(undefined, 'Browser closed before download is complete!')
70
+ } else {
71
+ logger.log(undefined, `${ex}`);
72
+ }
73
+ logger.failureLog(logMessage);
74
+ }
75
+ };
76
+
77
+ page.on('download', handleDownload);
78
+
79
+ page.context().on('page', async (newPage) => {
80
+ newPage.on('download', handleDownload);
81
+ });
82
+ }
83
+
84
+ };
85
+
86
+ exports.DownloadsManager = DownloadsManager;
@@ -0,0 +1,113 @@
1
+ const { sleep } = require("../utils/common-utils");
2
+ const { Logger } = require("../utils/logger");
3
+
4
+ class DownloadsUtils {
5
+
6
+ constructor(caller, blacklistedLogs, downloadsManager) {
7
+ this.caller = caller;
8
+ this.blacklistedLogs = blacklistedLogs;
9
+ this.downloadsManager = downloadsManager;
10
+ }
11
+
12
+ setCaller(caller) {
13
+ this.caller = caller;
14
+ }
15
+
16
+ setBlacklistedLogs(blacklistedLogs) {
17
+ this.blacklistedLogs = blacklistedLogs;
18
+ }
19
+
20
+ async wait_for_downloads_complete_ms(timeout) {
21
+ await this.wait_for_downloads_complete(timeout);
22
+ }
23
+
24
+ async wait_for_downloads_complete(timeout) {
25
+ const logLabel = timeout ?
26
+ `Wait for downloads to complete within ${timeout} ms`
27
+ : `Wait for downloads to complete`;
28
+ const logger = new Logger(this.caller, this.blacklistedLogs);
29
+ logger.startLog(logLabel);
30
+
31
+ let maxTries = timeout ? timeout / 1000 : 30;
32
+ let count = 0;
33
+ let latestDownloads = [];
34
+
35
+ while(!latestDownloads?.length && count < maxTries) {
36
+ //Filters all downloads in the last 5s
37
+ latestDownloads = this.downloadsManager.downloads
38
+ ?.filter(download => download?.timestamp && (Date.now() - download.timestamp <= 5 * 1000));
39
+ count += 1;
40
+ console.log(`No new downloads. Retrying... #${count}`);
41
+ await sleep(1000);
42
+ }
43
+
44
+ if(!latestDownloads?.length) {
45
+ logger.log(logLabel, `No new download has started in the last ${count}s... You can ignore if the download was triggered earlier!`)
46
+ logger.endLog(logLabel);
47
+ return;
48
+ }
49
+
50
+ const promises = latestDownloads
51
+ ?.map(download => download?.promise)
52
+ ?.filter(promise => !!promise);
53
+ await Promise.all(promises);
54
+ logger.endLog(logLabel);
55
+ }
56
+
57
+ async get_last_downloaded_file() {
58
+ const logLabel = `Get last downloaded file`;
59
+ const logger = new Logger(this.caller, this.blacklistedLogs);
60
+ logger.startLog(logLabel);
61
+ if(!this.downloadsManager?.downloads?.length) {
62
+ logger.failureLog(logLabel)
63
+ throw { message: 'No downloads present!' };
64
+ }
65
+ const download = this.downloadsManager.downloads.at(-1);
66
+ await download.promise;
67
+ logger.endLog(logLabel);
68
+ return download.filePath;
69
+ }
70
+
71
+ async get_last_downloaded_file_name_match(searchTerm) {
72
+ const logLabel = `Get last downloaded file with name matching ${searchTerm}`;
73
+ const logger = new Logger(this.caller, this.blacklistedLogs);
74
+ logger.startLog(logLabel);
75
+ if(!this.downloadsManager?.downloads?.length) {
76
+ logger.failureLog(logLabel)
77
+ throw { message: 'No downloads present!' };
78
+ }
79
+ let regex;
80
+ try {
81
+ regex = new RegExp(searchTerm);
82
+ } catch(_ex) {};
83
+ const check = regex
84
+ ? (download) => regex.test(download.fileName) || download.fileName?.includes(searchTerm)
85
+ : (download) => download.fileName?.includes(searchTerm);
86
+ const download = this.downloadsManager.downloads.reverse().find(check);
87
+ if(!download) {
88
+ logger.failureLog(logLabel)
89
+ throw { message: 'There are no downloads matching given searchTerm!' };
90
+ }
91
+ await download.promise;
92
+ logger.endLog(logLabel);
93
+ return download.filePath;
94
+ }
95
+
96
+ async get_all_downloaded_files() {
97
+ const logLabel = `Get all downloaded files`;
98
+ const logger = new Logger(this.caller, this.blacklistedLogs);
99
+ logger.startLog(logLabel);
100
+ if(!this.downloadsManager?.downloads?.length) {
101
+ logger.failureLog(logLabel)
102
+ throw { message: 'No downloads present!' };
103
+ }
104
+ const downloads = this.downloadsManager.downloads
105
+ .filter(download => !!download?.promise && !!download.filePath);
106
+ await Promise.all(downloads.map(download => download.promise));
107
+ logger.endLog(logLabel);
108
+ return downloads.map(download => download.filePath);
109
+ }
110
+
111
+ }
112
+
113
+ exports.DownloadsUtils = DownloadsUtils;
@@ -0,0 +1,68 @@
1
+ const { chromium } = require('@playwright/test');
2
+ const { openBrowser, importGetHooks } = require('./hooks/hook-utils');
3
+ const { startAppiumServers } = require('./mobile/appium/appium-manager');
4
+ const { FileUtils } = require('./library/file/file-utils');
5
+ const path = require('path');
6
+ const { getAutohealPath } = require('./utils/autoheal-utils');
7
+
8
+ async function globalSetup(config) {
9
+ const packageInfo = require('.././package.json');
10
+ console.log('Engine version : ', packageInfo?.version);
11
+
12
+ await new FileUtils().writeJSONContent(getAutohealPath(), {});
13
+
14
+ let playwrightConfig;
15
+ if(config?.configFile) {
16
+ playwrightConfig = require(config.configFile);
17
+ }
18
+
19
+ if(playwrightConfig?.customConfig?.testType === 'web' ) {
20
+ const channels = config.projects.map(project => project.use.channel).filter(c => !!c);
21
+ for (let i = 0; i < channels.length; i++) {
22
+ const channel = channels[i];
23
+ try {
24
+ const browser = await chromium.launch({ channel: channel });
25
+ await browser.close();
26
+ } catch(ex) {
27
+ console.log(`[[TPP]] Error launching ${channel} !!! Make sure browser is installed. :: [ERROR]`);
28
+ throw {message: `Browser ${channel} not installed!`};
29
+ }
30
+ }
31
+ if(playwrightConfig?.customConfig?.chromeExtension) {
32
+ console.log(`[[TPP_PRINT_ONLY]] 🌐 Only Chromium Browser will be used as Chrome Extension is enabled!`);
33
+ }
34
+ }
35
+
36
+ //TODO move to separate hook for mobile
37
+ //Start Appium
38
+
39
+ if(playwrightConfig?.customConfig?.testType === 'mobile'
40
+ && !playwrightConfig.customConfig.mobileConfig?.deviceCloud
41
+ ) {
42
+ console.log(`[[TPP_PRINT_ONLY]] 📱 Mobile setup :: [BEGIN]`);
43
+ await startAppiumServers(playwrightConfig.customConfig.mobileConfig.appiumStartScript, playwrightConfig.workers || 1);
44
+ console.log(`[[TPP_PRINT_ONLY]] 📱 Mobile setup :: [END]`);
45
+ }
46
+
47
+ let getHooks = importGetHooks();
48
+ if(!getHooks) return;
49
+
50
+ const actions = await openBrowser();
51
+ const hooks = getHooks(actions);
52
+ if(!hooks?.find(hook => hook?.beforeAll)) return;
53
+
54
+ let exception;
55
+ try {
56
+ actions.setCaller('', 'BeforeAll');
57
+ actions.testStartLog();
58
+ for (let i = 0; i < hooks.length; i++) {
59
+ const hook = hooks[i];
60
+ hook?.beforeAll && await hook.beforeAll();
61
+ }
62
+ } catch(ex) {
63
+ exception = ex;
64
+ }
65
+ await actions.handleResult(exception);
66
+ }
67
+
68
+ exports.default = globalSetup;
@@ -0,0 +1,57 @@
1
+ const { generateCombinedA11yReport } = require('./accessibility/combined-a11y-report');
2
+ const { openBrowser, importGetHooks } = require('./hooks/hook-utils');
3
+ const { FileUtils } = require('./library/file/file-utils');
4
+ const { stopAppiumServers, resetAppiumConfig } = require('./mobile/appium/appium-manager');
5
+ const { getAutohealPath } = require('./utils/autoheal-utils');
6
+ const { resetTokenFile } = require("./utils/token-utils");
7
+
8
+
9
+ async function globalTeardown(config) {
10
+ resetTokenFile();
11
+ generateCombinedA11yReport();
12
+
13
+ await new FileUtils().deleteFile(getAutohealPath());
14
+ //TODO move to separate hook for mobile
15
+ //Stop Appium
16
+ let playwrightConfig;
17
+ if(config?.configFile) {
18
+ playwrightConfig = require(config.configFile);
19
+ }
20
+ if(playwrightConfig.customConfig?.testType === 'mobile'
21
+ && !playwrightConfig.customConfig?.mobileConfig?.deviceCloud
22
+ ) {
23
+ console.log(`[[TPP_PRINT_ONLY]] Mobile teardown :: [BEGIN]`);
24
+ await stopAppiumServers();
25
+ resetAppiumConfig();
26
+ console.log(`[[TPP_PRINT_ONLY]] Mobile teardown :: [END]`);
27
+ }
28
+
29
+ let getHooks = importGetHooks();
30
+ if(!getHooks) return;
31
+
32
+ const actions = await openBrowser();
33
+ const hooks = getHooks(actions);
34
+ if(!hooks?.find(hook => hook?.afterAll)) {
35
+ await closBrowser();
36
+ return;
37
+ }
38
+
39
+ let exception;
40
+ try {
41
+ actions.setCaller('', 'AfterAll');
42
+ actions.testStartLog();
43
+ for (let i = 0; i < hooks.length; i++) {
44
+ const hook = hooks[i];
45
+ hook?.afterAll && await hook.afterAll();
46
+ }
47
+ } catch(ex) {
48
+ exception = ex;
49
+ }
50
+ await actions.handleResult(exception);
51
+ }
52
+
53
+ async function closBrowser(action) {
54
+ await action?.page?.context()?.browser()?.close();
55
+ }
56
+
57
+ exports.default = globalTeardown;