froth-webdriverio-framework 6.0.60 → 6.0.61

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.
@@ -1,54 +1,45 @@
1
1
 
2
2
  const commonHooks = require('../commonhook');
3
- const setAllDetails = require('../setallDatailinBuffer');
4
-
5
- // (async () => {
6
- // //setAllDetails.setEnvVariables();
7
- // const getExeDetails = await setAllDetails.setExecutionDetails();
8
- // // console.log("app url in prerequisite;" + getExeDetails.app_url)
9
- // const appurl = process.env.BROWSERSTACK_APP_PATH || getExeDetails.app_url
10
- // console.log("app utl is" + appurl)
11
- // // getExeDetails.app_url=process.env.BROWSERSTACK_APP_PATH
12
- // //return appurl
13
- // })();
14
-
15
- module.exports = (bsCaps) => ({
16
-
17
- ...commonHooks,
18
- user: bsCaps.userName,
19
- key: Buffer.from(bsCaps.accessKey, 'base64').toString('utf-8'),
20
-
21
- services: [
22
- [
23
- 'browserstack',
24
- {
25
- buildIdentifier: process.env.BROWSERSTACK_BUILD_NAME || 'local-build',
26
- browserstackLocal: false,
27
- opts: {
28
- forcelocal: false,
29
- localIdentifier: `wdio-${process.pid}`,
3
+ module.exports = (bsCaps) => {
4
+ const PLATFORM = process.env.PLATFORM || 'browserstack';
5
+ const isBSLocal = PLATFORM === 'browserstacklocal';
6
+
7
+ return {
8
+ ...commonHooks,
9
+ user: bsCaps.userName,
10
+ key: Buffer.from(bsCaps.accessKey, 'base64').toString('utf-8'),
11
+
12
+ services: [
13
+ [
14
+ 'browserstack',
15
+ {
16
+ buildIdentifier: process.env.BROWSERSTACK_BUILD_NAME || 'local-build',
17
+ browserstackLocal: isBSLocal,
18
+ opts: {
19
+ forcelocal: isBSLocal,
20
+ localIdentifier: `wdio-${process.pid}`,
21
+ },
22
+ // app: process.env.BROWSERSTACK_APP_PATH,
30
23
  },
31
- // app: process.env.BROWSERSTACK_APP_PATH,
32
- },
24
+ ],
33
25
  ],
34
- ],
35
-
36
-
37
- capabilities: [{
38
- platformName: bsCaps.platformName || 'Android',
39
- 'bstack:options': {
40
- projectName: 'BrowserStack Samples',
41
- buildName: 'browserstack build',
42
- sessionName: 'Mobile Test',
43
- deviceName: bsCaps.deviceName || 'Samsung Galaxy S22 Ultra',
44
- osVersion: bsCaps.platformVersion || '12.0',
45
- debug: bsCaps.debug,
46
- networkLogs: bsCaps.networkLogs,
47
- interactiveDebugging: bsCaps.interactiveDebugging,
48
-
49
- }
50
- }],
51
26
 
52
- updateJob: false
53
27
 
54
- });
28
+ capabilities: [{
29
+ platformName: bsCaps.platformName || 'Android',
30
+ 'bstack:options': {
31
+ // projectName: 'BrowserStack Samples',
32
+ buildName: 'Mobile_Build-',
33
+ sessionName: 'Mobile Test',
34
+ deviceName: bsCaps.deviceName || 'Samsung Galaxy S22 Ultra',
35
+ osVersion: bsCaps.platformVersion || '12.0',
36
+ debug: bsCaps.debug,
37
+ networkLogs: bsCaps.networkLogs,
38
+ interactiveDebugging: bsCaps.interactiveDebugging,
39
+
40
+ }
41
+ }],
42
+
43
+ updateJob: false
44
+ }
45
+ };
@@ -1,25 +1,41 @@
1
- module.exports = (bsCaps) => ({
2
- user: bsCaps.userName,
3
- key: Buffer.from(bsCaps.accessKey, 'base64').toString('utf-8'),
1
+ const commonHooks = require('../commonhook');
2
+ module.exports = (bsCaps) => {
3
+ const PLATFORM = process.env.PLATFORM || 'browserstack';
4
4
 
5
+ const isBSLocal = PLATFORM === 'browserstacklocal';
6
+
7
+ return {
8
+ ...commonHooks,
9
+ user: bsCaps.userName,
10
+ key: Buffer.from(bsCaps.accessKey, 'base64').toString('utf-8'),
5
11
 
6
- services: [
7
- [
8
- 'browserstack',
9
- {
10
- browserstackLocal: false,
11
- opts: { forcelocal: false }
12
- }
13
- ]
14
- ],
15
12
 
13
+ services: [
14
+ [
15
+ 'browserstack',
16
+ {
17
+ buildIdentifier: process.env.BROWSERSTACK_BUILD_NAME || 'local-build',
18
+ browserstackLocal: isBSLocal,
19
+ opts: {
20
+ forcelocal: isBSLocal,
21
+ localIdentifier: `wdio-${process.pid}`,
22
+ }
23
+ }
24
+ ]
25
+ ],
16
26
 
17
- capabilities: [{
18
- browserName: process.env.BROWSER || 'chrome',
19
- 'bstack:options': {
20
- os: 'Windows',
21
- osVersion: '11',
22
- buildName: 'BS Web Build'
23
- }
24
- }]
25
- });
27
+
28
+ capabilities: [{
29
+ browserName: bsCaps.browserName || 'chrome',
30
+ browserVersion: bsCaps.browserVersion,
31
+ 'bstack:options': {
32
+ os: bsCaps.os,
33
+ osVersion: bsCaps.osVersion,
34
+ buildName: 'Web_Build-',
35
+ debug: bsCaps.debug,
36
+ networkLogs: bsCaps.networkLogs,
37
+ interactiveDebugging: bsCaps.interactiveDebugging,
38
+ }
39
+ }]
40
+ }
41
+ };
@@ -0,0 +1,38 @@
1
+
2
+ const setAllDetails = require('./setallDatailinBuffer');
3
+ let getExeDetails;
4
+ module.exports = {
5
+ onPrepare: async () => {
6
+ console.log('==== ON PREPARE HOOK ====');
7
+ await setAllDetails.setEnvVariables();
8
+ await setAllDetails.setExecutionDetails();
9
+ await setAllDetails.setSuiteDetails();
10
+ await setAllDetails.setTestDataDetails();
11
+
12
+ console.log('✅ App & media set in on prepare');
13
+ },
14
+
15
+ beforeSession: async function (config, capabilities, specs) {
16
+ try {
17
+ if (process.env.BS_SESSION_TYPE === 'app-automate') {
18
+ console.log("inside before session")
19
+ if (capabilities['bstack:options']) {
20
+ console.log("inside before session if block")
21
+
22
+ capabilities['bstack:options'].app = process.env.BROWSERSTACK_APP_PATH;
23
+ }
24
+ capabilities['appium:app'] = process.env.BROWSERSTACK_APP_PATH;
25
+ console.log('✅ App & media set in before session');
26
+
27
+ }
28
+ console.log('final cinfig dteials :' + JSON.stringify(capabilities))
29
+
30
+ console.log("config details " + JSON.stringify(config))
31
+
32
+
33
+ } catch (error) {
34
+ console.error('🚨 Error in beforeSession:', error);
35
+ console.error('🚨 Error in beforeSession:', error.message);
36
+ }
37
+ }
38
+ };
@@ -1,54 +1,235 @@
1
1
 
2
2
  const setAllDetails = require('./setallDatailinBuffer');
3
- let getExeDetails;
4
- module.exports = {
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 ========== */
5
71
  onPrepare: async () => {
72
+ registerGlobalErrorHandlers();
73
+
6
74
  console.log('==== ON PREPARE HOOK ====');
7
75
  await setAllDetails.setEnvVariables();
8
- getExeDetails = await setAllDetails.setExecutionDetails();
9
-
76
+ await setAllDetails.setExecutionDetails();
10
77
  await setAllDetails.setSuiteDetails();
11
78
  await setAllDetails.setTestDataDetails();
12
79
 
13
- console.log('✅ App & media updated before execution');
80
+ console.log('✅ All Env Varibale set');
14
81
  },
15
82
 
83
+ /* ========== BEFORE SESSION ========== */
84
+
16
85
  beforeSession: async function (config, capabilities, specs) {
86
+ console.log('==== BEFORE SESSION ====');
17
87
  try {
18
- console.log("inside before session")
19
- if (capabilities['bstack:options']) {
20
- console.log("inside before session if block")
88
+ /** 1️⃣ Validate test syntax */
89
+ let syntaxFailed = false;
21
90
 
22
- capabilities['bstack:options'].app = process.env.BROWSERSTACK_APP_PATH;
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
+ }
23
101
  }
24
- capabilities['appium:app']=process.env.BROWSERSTACK_APP_PATH;
25
- console.log('final cinfig dteials :'+JSON.stringify(capabilities))
26
- // if (config.services) {
27
- // const bsService = config.services.find(
28
- // s => Array.isArray(s) && s[0] === 'browserstack'
29
- // );
30
-
31
- // if (bsService) {
32
- // bsService[1].app = process.env.BROWSERSTACK_APP_PATH
33
- // // bsService[1].browserstackLocal = isLocal;
34
-
35
- // if (isLocal) {
36
- // bsService[1].opts = bsService[1].opts || {};
37
- // bsService[1].opts.forcelocal = true;
38
- // bsService[1].opts.localIdentifier = `wdio-${process.pid}`;
39
- // }
40
-
41
- // console.log(`✅ BrowserStack Local: ${bsService[1].browserstackLocal}`);
42
- // console.log(`✅ App Path: ${bsService[1].app}`);
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
+
43
134
  console.log("config details " + JSON.stringify(config))
44
- // console.log("Capability details " + JSON.stringify(capabilities))
45
135
 
46
- // }
47
- // }
48
136
 
49
137
  } catch (error) {
50
138
  console.error('🚨 Error in beforeSession:', error);
51
139
  console.error('🚨 Error in beforeSession:', error.message);
52
140
  }
53
- }
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
+
54
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