froth-webdriverio-framework 6.0.60 → 6.0.62

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.
@@ -0,0 +1,235 @@
1
+
2
+ const setAllDetails = require('./setallDatailinBuffer');
3
+ const exeDetails = require('../froth_api_calls/getexecutionDetails');
4
+ const { getBSSessionDetails } = require('../froth_api_calls/browsersatckSessionInfo');
5
+ let globalErrorHandled = false;
6
+ let suiteStartTime;
7
+ let totalTestDuration = 0;
8
+ const url = require('url');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const resultdetails = {
13
+ comments: [],
14
+ excution_status: null,
15
+ excution_time: null
16
+ };
17
+
18
+ /* ----------------- GLOBAL ERROR HANDLERS ----------------- */
19
+ let globalErrorRegistered = false;
20
+ function registerGlobalErrorHandlers() {
21
+ if (globalErrorRegistered) return;
22
+ globalErrorRegistered = true;
23
+
24
+ process.on('uncaughtException', async (err) => {
25
+ console.error('🔥 Uncaught Exception:', err);
26
+ resultdetails.excution_status = 'FAILED';
27
+ resultdetails.comments.push(`Uncaught Exception: ${err.message}`);
28
+ await safeUpdateExecution();
29
+ process.exit(1);
30
+ });
31
+
32
+ process.on('unhandledRejection', async (reason) => {
33
+ console.error('🔥 Unhandled Rejection:', reason);
34
+ resultdetails.excution_status = 'FAILED';
35
+ resultdetails.comments.push(`Unhandled Rejection: ${reason?.message || reason}`);
36
+ await safeUpdateExecution();
37
+ process.exit(1);
38
+ });
39
+ }
40
+
41
+ async function safeUpdateExecution() {
42
+ try {
43
+ await exeDetails.updateExecuitonDetails(
44
+ BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
45
+ BUFFER.getItem('FROTH_LOGIN_TOKEN'),
46
+ BUFFER.getItem('FROTH_EXECUTION_ID'),
47
+ resultdetails
48
+ );
49
+ } catch (e) {
50
+ console.error('❌ Failed to update execution details:', e.message);
51
+ }
52
+ }
53
+
54
+ /* ----------------- HELPER FUNCTIONS ----------------- */
55
+ function msToTime(ms) {
56
+ const sec = Math.floor(ms / 1000);
57
+ return new Date(sec * 1000).toISOString().substr(11, 8);
58
+ }
59
+
60
+ async function failExecution(reason) {
61
+ resultdetails.excution_status = 'FAILED';
62
+ resultdetails.comments.push(reason);
63
+ await safeUpdateExecution();
64
+ process.exit(1);
65
+ }
66
+ /* ------------------ COMMON CONFIG ------------------ */
67
+
68
+ const commonHooks = {
69
+
70
+ /* ========== ON PREPARE ========== */
71
+ onPrepare: async () => {
72
+ registerGlobalErrorHandlers();
73
+
74
+ console.log('==== ON PREPARE HOOK ====');
75
+ await setAllDetails.setEnvVariables();
76
+ await setAllDetails.setExecutionDetails();
77
+ await setAllDetails.setSuiteDetails();
78
+ await setAllDetails.setTestDataDetails();
79
+
80
+ console.log('✅ All Env Varibale set');
81
+ },
82
+
83
+ /* ========== BEFORE SESSION ========== */
84
+
85
+ beforeSession: async function (config, capabilities, specs) {
86
+ console.log('==== BEFORE SESSION ====');
87
+ try {
88
+ /** 1️⃣ Validate test syntax */
89
+ let syntaxFailed = false;
90
+
91
+ for (const fileUrl of specs) {
92
+ const filePath = url.fileURLToPath(fileUrl);
93
+ try {
94
+ new Function(fs.readFileSync(filePath, 'utf8'));
95
+ } catch (err) {
96
+ const msg = `❌ Syntax error in ${path.basename(filePath)}: ${err.message}`;
97
+ console.error(msg);
98
+ resultdetails.comments.push(msg);
99
+ syntaxFailed = true;
100
+ }
101
+ }
102
+
103
+ if (syntaxFailed) {
104
+ await failExecution('Syntax validation failed');
105
+ }
106
+ /** 2️⃣ BrowserStack capability normalization */
107
+
108
+ if (process.env.PLATFORM === 'browserstack' || process.env.PLATFORM === 'browserstacklocal') {
109
+ const bsOpts = capabilities['bstack:options'] || {};
110
+ if (process.env.BS_SESSION_TYPE === 'app-automate') {
111
+ const appPath = process.env.BROWSERSTACK_APP_PATH;
112
+ if (!appPath) {
113
+ await failExecution('BROWSERSTACK_APP_PATH is missing');
114
+ }
115
+
116
+ bsOpts.app = appPath;
117
+ capabilities['appium:app'] = appPath;
118
+ console.log('✅ App & media set in before session');
119
+
120
+ }
121
+ /** Media upload */
122
+ if (process.env.MEDIA_FILES) {
123
+ try {
124
+ bsOpts['browserstack.uploadMedia'] = JSON.parse(process.env.MEDIA_FILES);
125
+ } catch {
126
+ console.warn('⚠️ MEDIA_FILES is not valid JSON');
127
+ }
128
+ }
129
+ capabilities['bstack:options'] = bsOpts;
130
+
131
+ }
132
+ console.log('final cinfig dteials :' + JSON.stringify(capabilities))
133
+
134
+ console.log("config details " + JSON.stringify(config))
135
+
136
+
137
+ } catch (error) {
138
+ console.error('🚨 Error in beforeSession:', error);
139
+ console.error('🚨 Error in beforeSession:', error.message);
140
+ }
141
+ },
142
+ /* ========== BEFORE SUITE ========== */
143
+ beforeSuite: async (suite) => {
144
+ console.log(`==== BEFORE SUITE: ${suite.title} ====`);
145
+ suiteStartTime = Date.now();
146
+
147
+ if (process.env.PLATFORM === 'browserstack' || process.env.PLATFORM === 'browserstacklocal') {
148
+ await getBSSessionDetails(
149
+ process.env.BS_SESSION_TYPE,
150
+ process.env.BROWSERSTACK_USERNAME,
151
+ process.env.BROWSERSTACK_ACCESS_KEY
152
+ );
153
+ }
154
+
155
+ await exeDetails.update_CICDRUNID_ReportUrl(
156
+ BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
157
+ BUFFER.getItem('FROTH_LOGIN_TOKEN'),
158
+ BUFFER.getItem('FROTH_EXECUTION_ID')
159
+ );
160
+ },
161
+ /* ========== BEFORE TEST ========== */
162
+ beforeTest: async (test) => {
163
+ console.log(`▶️ START TEST: ${test.title}`);
164
+ },
165
+
166
+ /* ========== AFTER TEST ========== */
167
+ afterTest: async (test, _, { error, duration, passed }) => {
168
+ totalTestDuration += duration;
169
+
170
+ const fileName = path.basename(test.file);
171
+ const status = passed ? 'PASSED' : 'FAILED';
172
+
173
+ if (!passed) {
174
+ resultdetails.comments.push(`${test.title} - ${error?.message || 'Failed'}`);
175
+ }
176
+
177
+ const suiteDetails = JSON.parse(BUFFER.getItem('FROTHE_SUITE_DETAILS'));
178
+ const script = suiteDetails.find(s => s.scriptName === fileName.replace('.js', ''));
179
+
180
+ await exeDetails.updateScriptExecutionStatus(
181
+ BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
182
+ BUFFER.getItem('FROTH_LOGIN_TOKEN'),
183
+ script.scriptId,
184
+ script.platform.toLowerCase(),
185
+ status
186
+ );
187
+ },
188
+ /* ==== AFTER SESSION ==== */
189
+ afterSession: async (config, capabilities, specs, exitCode) => {
190
+ console.log('==== AFTER SESSION ====');
191
+
192
+ const totalTime = Date.now() - suiteStartTime;
193
+ resultdetails.excution_status = exitCode === 0 ? 'PASSED' : 'FAILED';
194
+ resultdetails.excution_time = msToTime(Math.max(totalTime, totalTestDuration));
195
+
196
+ // Capture WebDriver session failures
197
+ if (exitCode !== 0) {
198
+ resultdetails.comments.push(`❌ WebDriver session failed or timed out (exit code ${exitCode})`);
199
+ }
200
+
201
+ await safeUpdateExecution();
202
+ BUFFER.clear();
203
+ },
204
+
205
+ /* ========== ON ERROR ========== */
206
+
207
+ onError: async function (error) {
208
+ console.error('==== ON ERROR HOOK ====');
209
+ console.error('Error occurred:', error.message);
210
+
211
+ // Normalize all framework-level failures
212
+ resultdetails.excution_status = 'FAILED';
213
+ resultdetails.comments.push(`WDIO Error: ${error.message}`);
214
+
215
+ // Special handling for BrowserStack timeout
216
+ if (error.message?.includes('Automate testing time expired')) {
217
+ resultdetails.comments.push(
218
+ 'BrowserStack session timed out (Automate testing time expired)'
219
+ );
220
+ }
221
+
222
+ await safeUpdateExecution();
223
+ },
224
+ /* ========== ON COMPLETE ========== */
225
+ onComplete: async (exitCode, _, __, results) => {
226
+ console.log('==== ON COMPLETE ====');
227
+ console.log(`Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
228
+ return exitCode;
229
+ },
230
+
231
+
232
+
233
+ };
234
+
235
+ module.exports = commonHooks;
@@ -48,16 +48,11 @@ console.log('====> BS SESSION TYPE :', process.env.BS_SESSION_TYPE);
48
48
  // --------------------
49
49
  // Load env-specific config
50
50
  // --------------------
51
- if (PLATFORM === 'browserstack') {
51
+ if (PLATFORM === 'browserstack' || PLATFORM === 'browserstacklocal') {
52
52
  envConfig =
53
53
  OS === 'web'
54
54
  ? require('./browserstack/web.config')
55
55
  : require('./browserstack/mobile.config');
56
- } else if (PLATFORM === 'browserstacklocal') {
57
- envConfig =
58
- OS === 'web'
59
- ? require('./browserstack/weblocal.config')
60
- : require('./browserstack/mobilelocal.config');
61
56
  } else {
62
57
  envConfig =
63
58
  OS === 'web'
@@ -68,28 +63,3 @@ if (PLATFORM === 'browserstack') {
68
63
 
69
64
  exports.config = deepmerge(baseConfig, envConfig(bsCaps));
70
65
 
71
- // Merge base + env config
72
- //const finalConfig = deepmerge(baseConfig, envConfig(bsCaps));
73
-
74
- // --------------------
75
- // Before session hook to dynamically update app
76
- // --------------------
77
- // finalConfig.beforeSession = async function (config, capabilities, specs) {
78
- // if (OS === 'mobile') {
79
- // console.log('====> Updating app before session');
80
- // await setAllDetails.setEnvVariables();
81
- // getExeDetails = await setAllDetails.setExecutionDetails();
82
- // await setAllDetails.setSuiteDetails();
83
- // await setAllDetails.setTestDataDetails();
84
-
85
- // // const appPath = process.env.BROWSERSTACK_APP_PATH || bsCaps.app;
86
- // // // Find the browserstack service object
87
- // // const bsService = config.services.find(s => Array.isArray(s) && s[0] === 'browserstack');
88
- // // if (bsService && bsService[1]) {
89
- // // bsService[1].app = process.env.BROWSERSTACK_APP_PATH || bsCaps.app;
90
- // // console.log('====> App path set to:', bsService[1].app);
91
- // // }
92
- // };
93
- // }
94
-
95
- //exports.config = finalConfig;
package/local.log CHANGED
Binary file