froth-webdriverio-framework 6.0.71 → 6.0.73

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.
@@ -3,243 +3,248 @@
3
3
  ========================================================= */
4
4
 
5
5
  const DEFAULT_HEADERS = (token) => ({
6
- 'Authorization': `Bearer ${token}`,
7
- 'Content-Type': 'application/json'
6
+ 'Authorization': `Bearer ${token}`,
7
+ 'Content-Type': 'application/json'
8
8
  });
9
9
 
10
10
  /* ===================== HELPERS ===================== */
11
11
 
12
12
  function isValidId(id) {
13
- return id !== null && id !== undefined && id !== 0;
13
+ return id !== null && id !== undefined && id !== 0;
14
14
  }
15
15
 
16
16
  async function handleResponse(response, context) {
17
- if (response.ok) {
18
- return response.json();
19
- }
17
+ if (response.ok) {
18
+ return response.json();
19
+ }
20
20
 
21
- if (response.status === 401) {
22
- console.error(`🔒 Unauthorized (401) in ${context}`);
23
- return null;
24
- }
21
+ if (response.status === 401) {
22
+ console.error(`🔒 Unauthorized (401) in ${context}`);
23
+ return null;
24
+ }
25
25
 
26
- const errorText = await response.text();
27
- console.error(`❌ ${context} failed [${response.status}]: ${errorText}`);
28
- return null;
26
+ const errorText = await response.text();
27
+ console.error(`❌ ${context} failed [${response.status}]: ${errorText}`);
28
+ return null;
29
29
  }
30
30
 
31
31
  /* ===================== GET EXECUTION ===================== */
32
32
 
33
33
  async function getExecuitonDetails(frothUrl, token, id) {
34
- if (!isValidId(id)) {
35
- console.error('❌ Invalid execution ID');
36
- return null;
37
- }
34
+ if (!isValidId(id)) {
35
+ console.error('❌ Invalid execution ID');
36
+ return null;
37
+ }
38
38
 
39
- const url = `${frothUrl}/api/test-execution-retrieve/${id}/`;
40
- console.log('GET:', url);
39
+ const url = `${frothUrl}/api/test-execution-retrieve/${id}/`;
40
+ console.log('GET:', url);
41
41
 
42
- try {
43
- const response = await fetch(url, {
44
- method: 'GET',
45
- headers: DEFAULT_HEADERS(token)
46
- });
42
+ try {
43
+ const response = await fetch(url, {
44
+ method: 'GET',
45
+ headers: DEFAULT_HEADERS(token)
46
+ });
47
47
 
48
- const data = await handleResponse(response, 'getExecuitonDetails');
49
- if (!data) return null;
48
+ const data = await handleResponse(response, 'getExecuitonDetails');
49
+ if (!data) return null;
50
50
 
51
- const jsondata = {
52
- automation_suite_id: data?.automation_suite_details?.id ?? null,
53
- test_cycle_id: data?.test_cycle_details?.id ?? null,
54
- app_url: data?.app_details?.app_url ?? null,
55
- browser_stack_local: data?.capability_details?.browser_stack_local ?? null,
56
- mediaurls: data?.media_details?.map(m => m.media_url) ?? []
57
- };
51
+ const jsondata = {
52
+ automation_suite_id: data?.automation_suite_details?.id ?? null,
53
+ test_cycle_id: data?.test_cycle_details?.id ?? null,
54
+ app_url: data?.app_details?.app_url ?? null,
55
+ browser_stack_local: data?.capability_details?.browser_stack_local ?? null,
56
+ mediaurls: data?.media_details?.map(m => m.media_url) ?? []
57
+ };
58
58
 
59
- console.log('✅ Execution details loaded');
60
- return jsondata;
59
+ console.log('✅ Execution details loaded');
60
+ return jsondata;
61
61
 
62
- } catch (error) {
63
- console.error('❌ getExecuitonDetails error:', error.message);
64
- return null;
65
- }
62
+ } catch (error) {
63
+ console.error('❌ getExecuitonDetails error:', error.message);
64
+ return null;
65
+ }
66
66
  }
67
67
 
68
68
  /* ===================== SCRIPT MAPPING ===================== */
69
69
 
70
70
  async function getExecuitonScriptDetails(
71
- frothUrl,
72
- token,
73
- execution_id,
74
- script_id,
75
- script_platform
71
+ frothUrl,
72
+ token,
73
+ execution_id,
74
+ script_id,
75
+ script_platform
76
76
  ) {
77
- if (!isValidId(script_id)) {
78
- console.error('❌ Invalid script ID');
79
- return null;
80
- }
77
+ if (!isValidId(script_id)) {
78
+ console.error('❌ Invalid script ID');
79
+ return null;
80
+ }
81
81
 
82
- const url =
83
- `${frothUrl}/api/execution-script-mapping/` +
84
- `?execution_id=${execution_id}` +
85
- `&automation_script_id=${script_id}` +
86
- `&platform=${script_platform}`;
82
+ const url =
83
+ `${frothUrl}/api/execution-script-mapping/` +
84
+ `?execution_id=${execution_id}` +
85
+ `&automation_script_id=${script_id}` +
86
+ `&platform=${script_platform}`;
87
87
 
88
- console.log('GET:', url);
88
+ console.log('GET:', url);
89
89
 
90
- try {
91
- const response = await fetch(url, {
92
- method: 'GET',
93
- headers: DEFAULT_HEADERS(token)
94
- });
90
+ try {
91
+ const response = await fetch(url, {
92
+ method: 'GET',
93
+ headers: DEFAULT_HEADERS(token)
94
+ });
95
95
 
96
- const data = await handleResponse(response, 'getExecuitonScriptDetails');
97
- if (!data || !data.length) return null;
96
+ const data = await handleResponse(response, 'getExecuitonScriptDetails');
97
+ if (!data || !data.length) return null;
98
98
 
99
- return data[0].id;
99
+ return data[0].id;
100
100
 
101
- } catch (error) {
102
- console.error('❌ getExecuitonScriptDetails error:', error.message);
103
- return null;
104
- }
101
+ } catch (error) {
102
+ console.error('❌ getExecuitonScriptDetails error:', error.message);
103
+ return null;
104
+ }
105
105
  }
106
106
 
107
107
  /* ===================== UPDATE EXECUTION ===================== */
108
108
 
109
109
  async function updateExecuitonDetails(frothUrl, token, id, resultdetails) {
110
- if (!isValidId(id)) {
111
- console.error('❌ Invalid execution ID for update');
112
- return;
113
- }
114
-
115
- if (BUFFER.getItem('FROTH_UPDATE_EXECUTION') === 'TRUE') {
116
- console.log('ℹ️ Execution already updated — skipping');
117
- return;
118
- }
119
-
120
- const url = `${frothUrl}/api/test-execution-update/${id}/`;
121
- const formData = new FormData();
122
-
123
- console.log('PUT:', url);
124
-
125
- try {
126
- formData.append('updated_through_bot', true);
127
-
128
- if (resultdetails.excution_status) {
129
- formData.append('excution_status', resultdetails.excution_status);
110
+ if (!isValidId(id)) {
111
+ console.error('❌ Invalid execution ID for update');
112
+ return;
130
113
  }
131
114
 
132
- if (
133
- resultdetails.excution_time &&
134
- resultdetails.excution_time !== 'NaN:NaN:NaN'
135
- ) {
136
- formData.append('excution_time', resultdetails.excution_time);
115
+ if (BUFFER.getItem('FROTH_UPDATE_EXECUTION') === 'TRUE') {
116
+ console.log('ℹ️ Execution already updated — skipping');
117
+ return;
137
118
  }
138
119
 
139
- if (Array.isArray(resultdetails.comments) && resultdetails.comments.length) {
140
- formData.append('comments', resultdetails.comments.join('<br>'));
141
- }
142
-
143
- const response = await fetch(url, {
144
- method: 'PUT',
145
- headers: { 'Authorization': `Bearer ${token}` },
146
- body: formData
147
- });
148
-
149
- const data = await handleResponse(response, 'updateExecuitonDetails');
150
- if (!data) return;
120
+ const url = `${frothUrl}/api/test-execution-update/${id}/`;
121
+ const formData = new FormData();
151
122
 
152
- BUFFER.setItem('FROTH_UPDATE_EXECUTION', 'TRUE');
153
- console.log('✅ Execution details updated');
123
+ console.log('PUT:', url);
154
124
 
155
- } catch (error) {
156
- console.error('❌ updateExecuitonDetails error:', error.message);
157
- }
125
+ try {
126
+ formData.append('updated_through_bot', true);
127
+
128
+ if (resultdetails.excution_status) {
129
+ formData.append('excution_status', resultdetails.excution_status);
130
+ }
131
+
132
+ if (
133
+ resultdetails.excution_time &&
134
+ resultdetails.excution_time !== 'NaN:NaN:NaN'
135
+ ) {
136
+ formData.append('excution_time', resultdetails.excution_time);
137
+ }
138
+
139
+ if (Array.isArray(resultdetails.comments) && resultdetails.comments.length) {
140
+ formData.append('comments', resultdetails.comments.join('<br>'));
141
+ }
142
+ // ✅ Log actual FormData keys
143
+ console.log('📤 FormData keys sent:');
144
+ for (const [key, value] of formData.entries()) {
145
+ console.log(` ${key}: ${value}`);
146
+ }
147
+ const response = await fetch(url, {
148
+ method: 'PUT',
149
+ headers: { 'Authorization': `Bearer ${token}` },
150
+ body: formData
151
+ });
152
+
153
+
154
+ const data = await handleResponse(response, 'updateExecuitonDetails');
155
+ if (!data) return;
156
+
157
+ BUFFER.setItem('FROTH_UPDATE_EXECUTION', 'TRUE');
158
+ console.log('✅ Execution details updated');
159
+
160
+ } catch (error) {
161
+ console.error('❌ updateExecuitonDetails error:', error.message);
162
+ }
158
163
  }
159
164
 
160
165
  /* ===================== UPDATE CICD / REPORT ===================== */
161
166
 
162
167
  async function update_CICDRUNID_ReportUrl(frothUrl, token, id) {
163
- if (!isValidId(id)) return;
168
+ if (!isValidId(id)) return;
164
169
 
165
- const url = `${frothUrl}/api/test-execution-update/${id}/`;
166
- const formData = new FormData();
170
+ const url = `${frothUrl}/api/test-execution-update/${id}/`;
171
+ const formData = new FormData();
167
172
 
168
- console.log('PUT:', url);
173
+ console.log('PUT:', url);
169
174
 
170
- try {
171
- formData.append('updated_through_bot', true);
172
- formData.append('run_id', process.env.CICD_RUN_ID);
175
+ try {
176
+ formData.append('updated_through_bot', true);
177
+ formData.append('run_id', process.env.CICD_RUN_ID);
173
178
 
174
- const reportUrl = BUFFER.getItem('REPORT_URL');
175
- if (reportUrl) {
176
- formData.append('report_url', reportUrl);
177
- }
179
+ const reportUrl = BUFFER.getItem('REPORT_URL');
180
+ if (reportUrl) {
181
+ formData.append('report_url', reportUrl);
182
+ }
178
183
 
179
- const response = await fetch(url, {
180
- method: 'PUT',
181
- headers: { 'Authorization': `Bearer ${token}` },
182
- body: formData
183
- });
184
+ const response = await fetch(url, {
185
+ method: 'PUT',
186
+ headers: { 'Authorization': `Bearer ${token}` },
187
+ body: formData
188
+ });
184
189
 
185
- await handleResponse(response, 'update_CICDRUNID_ReportUrl');
190
+ await handleResponse(response, 'update_CICDRUNID_ReportUrl');
186
191
 
187
- } catch (error) {
188
- console.error('❌ update_CICDRUNID_ReportUrl error:', error.message);
189
- }
192
+ } catch (error) {
193
+ console.error('❌ update_CICDRUNID_ReportUrl error:', error.message);
194
+ }
190
195
  }
191
196
 
192
197
  /* ===================== UPDATE SCRIPT STATUS ===================== */
193
198
 
194
199
  async function updateScriptExecutionStatus(
195
- frothUrl,
196
- token,
197
- scriptid,
198
- script_platform,
199
- status
200
+ frothUrl,
201
+ token,
202
+ scriptid,
203
+ script_platform,
204
+ status
200
205
  ) {
201
- if (!isValidId(scriptid)) {
202
- console.error('❌ Invalid script ID');
203
- return;
204
- }
205
-
206
- try {
207
- const mappingId = await getExecuitonScriptDetails(
208
- frothUrl,
209
- token,
210
- BUFFER.getItem('FROTH_EXECUTION_ID'),
211
- scriptid,
212
- script_platform
213
- );
214
-
215
- if (!mappingId) return;
216
-
217
- const url = `${frothUrl}/api/script-status-percentage/${mappingId}/`;
218
- const formData = new FormData();
206
+ if (!isValidId(scriptid)) {
207
+ console.error('❌ Invalid script ID');
208
+ return;
209
+ }
219
210
 
220
- console.log('PUT:', url);
211
+ try {
212
+ const mappingId = await getExecuitonScriptDetails(
213
+ frothUrl,
214
+ token,
215
+ BUFFER.getItem('FROTH_EXECUTION_ID'),
216
+ scriptid,
217
+ script_platform
218
+ );
221
219
 
222
- formData.append('script_status', status);
223
- formData.append('updated_through_bot', true);
220
+ if (!mappingId) return;
224
221
 
225
- const response = await fetch(url, {
226
- method: 'PUT',
227
- headers: { 'Authorization': `Bearer ${token}` },
228
- body: formData
229
- });
222
+ const url = `${frothUrl}/api/script-status-percentage/${mappingId}/`;
223
+ const formData = new FormData();
230
224
 
231
- await handleResponse(response, 'updateScriptExecutionStatus');
225
+ console.log('PUT:', url);
232
226
 
233
- } catch (error) {
234
- console.error('❌ updateScriptExecutionStatus error:', error.message);
235
- }
227
+ formData.append('script_status', status);
228
+ formData.append('updated_through_bot', true);
229
+
230
+ const response = await fetch(url, {
231
+ method: 'PUT',
232
+ headers: { 'Authorization': `Bearer ${token}` },
233
+ body: formData
234
+ });
235
+
236
+ await handleResponse(response, 'updateScriptExecutionStatus');
237
+
238
+ } catch (error) {
239
+ console.error('❌ updateScriptExecutionStatus error:', error.message);
240
+ }
236
241
  }
237
242
 
238
243
  /* ===================== EXPORTS ===================== */
239
244
 
240
245
  module.exports = {
241
- getExecuitonDetails,
242
- updateExecuitonDetails,
243
- updateScriptExecutionStatus,
244
- update_CICDRUNID_ReportUrl
246
+ getExecuitonDetails,
247
+ updateExecuitonDetails,
248
+ updateScriptExecutionStatus,
249
+ update_CICDRUNID_ReportUrl
245
250
  };
@@ -216,13 +216,13 @@ const commonHooks = {
216
216
  },
217
217
 
218
218
  /* ==== AFTER SESSION ==== */
219
- afterSession: async (config, capabilities, specs,exitCode) => {
219
+ afterSession: async (config, capabilities, specs, exitCode) => {
220
220
  console.log('==== AFTER SESSION ====');
221
221
  const endTime = Date.now();
222
222
  if (!suiteStartTime) suiteStartTime = endTime;
223
223
 
224
224
  const totalTime = Math.max(endTime - suiteStartTime, totalTestDuration);
225
- // resultdetails.excution_status = exitCode === 0 ? 'PASSED' : 'FAILED';
225
+ // resultdetails.excution_status = exitCode === 0 ? 'PASSED' : 'FAILED';
226
226
  resultdetails.excution_time = msToTime(totalTime);
227
227
 
228
228
  console.log('⏱ Final execution time:', resultdetails.excution_time);
@@ -264,7 +264,30 @@ const commonHooks = {
264
264
  if (exitCode !== 0 && resultdetails.comments.length === 0) {
265
265
  resultdetails.comments.push(`Execution failed with exit code ${exitCode}`);
266
266
  }
267
+ // ✅ Set final status
268
+ resultdetails.excution_status = exitCode === 0 ? 'PASSED' : 'FAILED';
269
+
270
+ // ✅ If execution failed but no comments, add default comment
271
+ if (exitCode !== 0 && resultdetails.comments.length === 0) {
272
+ resultdetails.comments.push(`Execution failed with exit code ${exitCode}`);
273
+ }
274
+
275
+ // ✅ Make sure excution_time is set (if not, fallback)
276
+ if (!resultdetails.excution_time || resultdetails.excution_time === 'NaN:NaN:NaN') {
277
+ const fallbackTime = totalTestDuration || 0;
278
+ resultdetails.excution_time = msToTime(fallbackTime);
279
+ }
280
+
281
+ console.log('📤 Updating DB with final execution details');
282
+ console.log('Status:', resultdetails.excution_status);
283
+ console.log('Duration:', resultdetails.excution_time);
267
284
 
285
+ // await exeDetails.updateExecuitonDetails(
286
+ // BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
287
+ // BUFFER.getItem('FROTH_LOGIN_TOKEN'),
288
+ // BUFFER.getItem('FROTH_EXECUTION_ID'),
289
+ // resultdetails
290
+ // );
268
291
  await safeUpdateExecution();
269
292
  BUFFER.clear();
270
293
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "froth-webdriverio-framework",
3
- "version": "6.0.71",
3
+ "version": "6.0.73",
4
4
  "readme": "WendriverIO Integration with [BrowserStack](https://www.browserstack.com)",
5
5
  "description": "Selenium examples for WebdriverIO and BrowserStack App Automate",
6
6
  "scripts": {