froth-webdriverio-framework 7.0.118 → 7.0.119-dev1.0
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.
- package/froth_api_calls/browsersatckSessionInfo.js +69 -0
- package/froth_api_calls/getexecutionDetails.js +10 -10
- package/froth_common_actions/assert.js +1 -1
- package/froth_common_actions/dbValidator.js +77 -8
- package/froth_configs/base.config.js +3 -0
- package/froth_configs/commonhook.js +58 -45
- package/froth_configs/local/web.config.js +56 -6
- package/froth_configs/wdio.common.conf.js +1 -1
- package/package.json +12 -18
- package/log/key-metrics.json +0 -0
- package/log/key-metrics.json.lock +0 -0
- package/log/sdk-cli.log +0 -2186
- package/log/sdk-debug-utility.log +0 -0
|
@@ -64,8 +64,10 @@ async function getBSSessionDetails(sessionType, bsUsername, bsPassword) {
|
|
|
64
64
|
|
|
65
65
|
BUFFER.setItem("REPORT_URL", publicUrl);
|
|
66
66
|
BUFFER.setItem("FROTH_TOTAL_DURATION", duration);
|
|
67
|
+
BUFFER.setItem("BS_BUILD_HASH_ID", hashId);
|
|
67
68
|
|
|
68
69
|
console.log(`Public URL: ${publicUrl}`);
|
|
70
|
+
console.log(`Build Hash ID: ${hashId}`);
|
|
69
71
|
} else if (response.status === 401) {
|
|
70
72
|
console.error("Unauthorized: token expired to login Browserstack");
|
|
71
73
|
} else {
|
|
@@ -160,11 +162,78 @@ async function escapeForBrowserStack(message) {
|
|
|
160
162
|
.replace(/\r/g, "\\r");
|
|
161
163
|
}
|
|
162
164
|
|
|
165
|
+
/* ===================== BROWSERSTACK REPORT API ===================== */
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Updates BrowserStack report details in Froth TestOps database
|
|
169
|
+
* @param {string} frothUrl - Froth TestOps API base URL
|
|
170
|
+
* @param {string} token - Authentication token
|
|
171
|
+
* @param {string} bsBuildId - BrowserStack build ID (e.g., "frothtestops-coderepo_1286_20260211")
|
|
172
|
+
* @param {number} executionId - Test execution ID
|
|
173
|
+
* @param {string} status - BrowserStack status: "in_progress" (updates public URL only) or "completed"
|
|
174
|
+
*/
|
|
175
|
+
async function updateBrowserStackReport(frothUrl, token, bsBuildId, executionId, status) {
|
|
176
|
+
if (!frothUrl || !token || !bsBuildId || !executionId || !status) {
|
|
177
|
+
console.error('❌ Missing required parameters for updateBrowserStackReport');
|
|
178
|
+
console.error(`frothUrl: ${frothUrl}, token: ${!!token}, bsBuildId: ${bsBuildId}, executionId: ${executionId}, status: ${status}`);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const validStatuses = ['in_progress', 'completed'];
|
|
183
|
+
if (!validStatuses.includes(status)) {
|
|
184
|
+
console.error(`❌ Invalid browserstack_status: ${status}. Must be one of: ${validStatuses.join(', ')}`);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
163
187
|
|
|
188
|
+
const url = `${frothUrl}/api/download-browserstack-report/`;
|
|
189
|
+
console.log(`📤 Updating BrowserStack report [${status}]:`, url);
|
|
164
190
|
|
|
191
|
+
const payload = {
|
|
192
|
+
BS_BUILD_ID: bsBuildId,
|
|
193
|
+
execution_id: executionId,
|
|
194
|
+
browserstack_status: status
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const response = await fetch(url, {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
headers: {
|
|
201
|
+
'Authorization': `Bearer ${token}`,
|
|
202
|
+
'Content-Type': 'application/json'
|
|
203
|
+
},
|
|
204
|
+
body: JSON.stringify(payload)
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const contentType = response.headers.get('content-type') || '';
|
|
208
|
+
let data;
|
|
209
|
+
if (contentType.includes('application/json')) {
|
|
210
|
+
data = await response.json();
|
|
211
|
+
} else {
|
|
212
|
+
data = await response.text();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log('📥 Response in updateBrowserStackReport:', data);
|
|
216
|
+
|
|
217
|
+
if (response.ok) {
|
|
218
|
+
console.log(`✅ BrowserStack report updated successfully [${status}]`);
|
|
219
|
+
return data;
|
|
220
|
+
} else if (response.status === 401) {
|
|
221
|
+
console.error('🔒 Unauthorized (401) - Token may be expired');
|
|
222
|
+
return null;
|
|
223
|
+
} else {
|
|
224
|
+
console.error(`❌ Failed to update BrowserStack report [${response.status}]:`, data);
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('❌ updateBrowserStackReport error:', error.message);
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
165
233
|
|
|
166
234
|
module.exports = {
|
|
167
235
|
getBSSessionDetails,
|
|
168
236
|
getBSBuildDetails,
|
|
169
237
|
amend2Browserstack,
|
|
238
|
+
updateBrowserStackReport,
|
|
170
239
|
};
|
|
@@ -17,7 +17,9 @@ function isValidId(id) {
|
|
|
17
17
|
async function handleResponse(response, context) {
|
|
18
18
|
|
|
19
19
|
if (response.ok) {
|
|
20
|
-
|
|
20
|
+
const data = await response.json();
|
|
21
|
+
console.log('📥 Response in', context, ':', data);
|
|
22
|
+
return data;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
if (response.status === 401) {
|
|
@@ -139,12 +141,12 @@ async function updateExecuitonDetails(frothUrl, token, id, resultdetails) {
|
|
|
139
141
|
formData.append('excution_status', resultdetails.excution_status);
|
|
140
142
|
}
|
|
141
143
|
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
) {
|
|
146
|
-
|
|
147
|
-
}
|
|
144
|
+
// if (
|
|
145
|
+
// resultdetails.excution_time &&
|
|
146
|
+
// resultdetails.excution_time !== 'NaN:NaN:NaN'
|
|
147
|
+
// ) {
|
|
148
|
+
// formData.append('excution_time', resultdetails.excution_time);
|
|
149
|
+
// }
|
|
148
150
|
|
|
149
151
|
if (resultdetails.comments === null)
|
|
150
152
|
console.log("Comments is null")
|
|
@@ -170,9 +172,7 @@ async function updateExecuitonDetails(frothUrl, token, id, resultdetails) {
|
|
|
170
172
|
data = await response.text();
|
|
171
173
|
}
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
// console.log('📤 API Response Headers:', Array.from(response.headers.entries()));
|
|
175
|
-
// console.log('📤 API Response Body:', data);
|
|
175
|
+
console.log('📥 Response from updateExecuitonDetails:', data);
|
|
176
176
|
|
|
177
177
|
if (!response.ok) {
|
|
178
178
|
console.error(`❌ Failed to update execution details, status ${response.status}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Function to verify text in Android app
|
|
2
|
-
|
|
2
|
+
const assert = require('assert');
|
|
3
3
|
const amendToBrowserstack = require("../froth_api_calls/browsersatckSessionInfo").amend2Browserstack;
|
|
4
4
|
|
|
5
5
|
async function assertText(elementSelector, expectedText) {
|
|
@@ -75,7 +75,70 @@ async function validateDbFields(actualData, expectedData, context = 'DB Validati
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// -----------------------------
|
|
78
|
-
//
|
|
78
|
+
// NULLABLE VALIDATION (allow null/empty)
|
|
79
|
+
// -----------------------------
|
|
80
|
+
if (typeof expectedConfig === "object" && expectedConfig.type === "nullable") {
|
|
81
|
+
const isNullOrEmpty = actual === null || actual === undefined || actual === "" || actual === "null";
|
|
82
|
+
status = isNullOrEmpty ? "PASS" : "PASS"; // Always pass - just validates field exists
|
|
83
|
+
results.push({
|
|
84
|
+
key,
|
|
85
|
+
actual,
|
|
86
|
+
expected: "(nullable - any value allowed)",
|
|
87
|
+
status
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// -----------------------------
|
|
93
|
+
// NUMBER WITH TOLERANCE
|
|
94
|
+
// -----------------------------
|
|
95
|
+
if (typeof expectedConfig === "object" && expectedConfig.type === "number") {
|
|
96
|
+
expected = expectedConfig.value;
|
|
97
|
+
const tolerance = expectedConfig.tolerance || 0;
|
|
98
|
+
|
|
99
|
+
const actualNum = parseFloat(actual);
|
|
100
|
+
const expectedNum = parseFloat(expected);
|
|
101
|
+
|
|
102
|
+
if (isNaN(actualNum) || isNaN(expectedNum)) {
|
|
103
|
+
status = "FAIL";
|
|
104
|
+
} else {
|
|
105
|
+
const diff = Math.abs(actualNum - expectedNum);
|
|
106
|
+
status = diff <= tolerance ? "PASS" : "FAIL";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
results.push({
|
|
110
|
+
key,
|
|
111
|
+
actual,
|
|
112
|
+
expected: `${expected} (±${tolerance})`,
|
|
113
|
+
status
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (status === "FAIL") allPassed = false;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// -----------------------------
|
|
121
|
+
// PARTIAL STRING MATCH
|
|
122
|
+
// -----------------------------
|
|
123
|
+
if (typeof expectedConfig === "object" && expectedConfig.type === "partial") {
|
|
124
|
+
const substring = expectedConfig.contains;
|
|
125
|
+
const actualStr = String(actual || "");
|
|
126
|
+
|
|
127
|
+
status = actualStr.includes(substring) ? "PASS" : "FAIL";
|
|
128
|
+
|
|
129
|
+
results.push({
|
|
130
|
+
key,
|
|
131
|
+
actual,
|
|
132
|
+
expected: `(contains "${substring}")`,
|
|
133
|
+
status
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (status === "FAIL") allPassed = false;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// -----------------------------
|
|
141
|
+
// TIMESTAMP VALIDATION
|
|
79
142
|
// -----------------------------
|
|
80
143
|
if (typeof expectedConfig === "object" && expectedConfig.type === "timestamp") {
|
|
81
144
|
expected = expectedConfig.value;
|
|
@@ -124,13 +187,13 @@ async function validateDbFields(actualData, expectedData, context = 'DB Validati
|
|
|
124
187
|
// -----------------------------
|
|
125
188
|
// BROWSERSTACK LOGGING
|
|
126
189
|
// -----------------------------
|
|
127
|
-
// const chunkSize = 800;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
190
|
+
// const chunkSize = 800;
|
|
191
|
+
const combined = results
|
|
192
|
+
.map(r => `${r.key} => Expected: ${r.expected}, Actual: ${r.actual}, Status: ${r.status}`)
|
|
193
|
+
.join(" | ");
|
|
131
194
|
|
|
132
|
-
// const chunks = combined.match(new RegExp(`.{1,${chunkSize}}`, "g")) || [];
|
|
133
|
-
// for (const c of chunks) await amendBrowserStackLog(c, "info");
|
|
195
|
+
// const chunks = combined.match(new RegExp(`.{1,${chunkSize}}`, "g")) || [];
|
|
196
|
+
// for (const c of chunks) await amendBrowserStackLog(c, "info");
|
|
134
197
|
|
|
135
198
|
await amendBrowserStackLog(combined, "info");
|
|
136
199
|
// -----------------------------
|
|
@@ -147,4 +210,10 @@ async function validateDbFields(actualData, expectedData, context = 'DB Validati
|
|
|
147
210
|
module.exports = {
|
|
148
211
|
parseTimestamp,
|
|
149
212
|
validateDbFields
|
|
150
|
-
};
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// async function main(){
|
|
216
|
+
|
|
217
|
+
// }
|
|
218
|
+
|
|
219
|
+
// main()
|
|
@@ -4,6 +4,9 @@ console.log('====>SUITE_FILE:', SUITE_FILE);
|
|
|
4
4
|
const { LocalStorage } = require('node-localstorage');
|
|
5
5
|
global.BUFFER = new LocalStorage('./buffer_storage');
|
|
6
6
|
|
|
7
|
+
// Make Util globally available across all test files
|
|
8
|
+
global.Util = require('../froth_common_actions/Utils');
|
|
9
|
+
|
|
7
10
|
module.exports = {
|
|
8
11
|
specs: require(SUITE_FILE).tests,
|
|
9
12
|
exclude: [],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
const setAllDetails = require('./setallDatailinBuffer');
|
|
3
3
|
const exeDetails = require('../froth_api_calls/getexecutionDetails');
|
|
4
|
-
const { getBSSessionDetails } = require('../froth_api_calls/browsersatckSessionInfo');
|
|
4
|
+
const { getBSSessionDetails, updateBrowserStackReport } = require('../froth_api_calls/browsersatckSessionInfo');
|
|
5
5
|
let globalErrorHandled = false;
|
|
6
6
|
let suiteStartTime = 0;
|
|
7
7
|
let totalTestDuration = 0;
|
|
@@ -14,7 +14,7 @@ let executionUpdated = false;
|
|
|
14
14
|
const resultdetails = {
|
|
15
15
|
comments: [],
|
|
16
16
|
excution_status: null,
|
|
17
|
-
|
|
17
|
+
// excution_time: null
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/* ----------------- GLOBAL ERROR HANDLERS ----------------- */
|
|
@@ -187,37 +187,49 @@ const commonHooks = {
|
|
|
187
187
|
suiteStartTime = Date.now();
|
|
188
188
|
|
|
189
189
|
if (process.env.PLATFORM === 'browserstack' || process.env.PLATFORM === 'browserstacklocal') {
|
|
190
|
-
await getBSSessionDetails(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
);
|
|
190
|
+
// await getBSSessionDetails(
|
|
191
|
+
// process.env.BS_SESSION_TYPE,
|
|
192
|
+
// process.env.BROWSERSTACK_USERNAME,
|
|
193
|
+
// process.env.BROWSERSTACK_ACCESS_KEY
|
|
194
|
+
// );
|
|
195
|
+
|
|
196
|
+
// Update BrowserStack report with in_progress status
|
|
197
|
+
const buildName = process.env.FROTH_TESTOPS_BUILD_NAME;
|
|
198
|
+
if (buildName) {
|
|
199
|
+
await updateBrowserStackReport(
|
|
200
|
+
BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
|
|
201
|
+
BUFFER.getItem('FROTH_LOGIN_TOKEN'),
|
|
202
|
+
buildName,
|
|
203
|
+
BUFFER.getItem('FROTH_EXECUTION_ID'),
|
|
204
|
+
'in_progress'
|
|
205
|
+
);
|
|
206
|
+
}
|
|
195
207
|
}
|
|
196
208
|
|
|
197
|
-
await exeDetails.update_CICDRUNID_ReportUrl(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
);
|
|
209
|
+
// await exeDetails.update_CICDRUNID_ReportUrl(
|
|
210
|
+
// BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
|
|
211
|
+
// BUFFER.getItem('FROTH_LOGIN_TOKEN'),
|
|
212
|
+
// BUFFER.getItem('FROTH_EXECUTION_ID')
|
|
213
|
+
// );
|
|
202
214
|
},
|
|
203
215
|
/* ========== BEFORE TEST ========== */
|
|
204
216
|
beforeTest: async (test) => {
|
|
205
217
|
console.log(`▶️ START TEST: ${test.title}`);
|
|
206
218
|
|
|
207
|
-
//
|
|
208
|
-
const fileName = path.basename(test.file);
|
|
209
|
-
const suiteDetails = JSON.parse(BUFFER.getItem('FROTHE_SUITE_DETAILS'));
|
|
210
|
-
const script = suiteDetails.find(s => s.scriptName === fileName.replace('.js', ''));
|
|
211
|
-
|
|
212
|
-
if (script) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
219
|
+
// Update script status to IN_PROGRESS
|
|
220
|
+
// const fileName = path.basename(test.file);
|
|
221
|
+
// const suiteDetails = JSON.parse(BUFFER.getItem('FROTHE_SUITE_DETAILS'));
|
|
222
|
+
// const script = suiteDetails.find(s => s.scriptName === fileName.replace('.js', ''));
|
|
223
|
+
|
|
224
|
+
// if (script) {
|
|
225
|
+
// await exeDetails.updateScriptExecutionStatus(
|
|
226
|
+
// BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
|
|
227
|
+
// BUFFER.getItem('FROTH_LOGIN_TOKEN'),
|
|
228
|
+
// script.scriptId,
|
|
229
|
+
// script.platform.toLowerCase(),
|
|
230
|
+
// 'IN_PROGRESS'
|
|
231
|
+
// );
|
|
232
|
+
// }
|
|
221
233
|
},
|
|
222
234
|
|
|
223
235
|
/* ========== AFTER TEST ========== */
|
|
@@ -273,7 +285,7 @@ const commonHooks = {
|
|
|
273
285
|
console.log('⏱ ==== Execution time calculation ==== ');
|
|
274
286
|
const endTime = Date.now();
|
|
275
287
|
const totalTime = endTime - suiteStartTime; // Full WDIO+CI elapsed time
|
|
276
|
-
|
|
288
|
+
// resultdetails.excution_time = await msToTime(totalTime);
|
|
277
289
|
|
|
278
290
|
console.log("Exit code after session===>" + exitCode)
|
|
279
291
|
if (exitCode === undefined || exitCode === null) {
|
|
@@ -284,9 +296,24 @@ const commonHooks = {
|
|
|
284
296
|
console.log('Comments being sent:', resultdetails.comments);
|
|
285
297
|
//resultdetails.comments.push(BUFFER.getItem('ALL_COMMENTS'))
|
|
286
298
|
console.log('⏱ Final execution time (ms):', totalTime);
|
|
287
|
-
|
|
299
|
+
// console.log('⏱ Final execution time (hh:mm:ss):', resultdetails.excution_time);
|
|
288
300
|
await safeUpdateExecution();
|
|
289
301
|
|
|
302
|
+
// Update BrowserStack report with completed status
|
|
303
|
+
if (process.env.PLATFORM === 'browserstack' || process.env.PLATFORM === 'browserstacklocal') {
|
|
304
|
+
const buildName = process.env.FROTH_TESTOPS_BUILD_NAME;
|
|
305
|
+
if (buildName) {
|
|
306
|
+
await updateBrowserStackReport(
|
|
307
|
+
BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
|
|
308
|
+
BUFFER.getItem('FROTH_LOGIN_TOKEN'),
|
|
309
|
+
buildName,
|
|
310
|
+
BUFFER.getItem('FROTH_EXECUTION_ID'),
|
|
311
|
+
'completed'
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
}
|
|
316
|
+
|
|
290
317
|
|
|
291
318
|
},
|
|
292
319
|
|
|
@@ -306,28 +333,14 @@ const commonHooks = {
|
|
|
306
333
|
);
|
|
307
334
|
}
|
|
308
335
|
|
|
309
|
-
// Mark all scripts as SKIPPED if error causes all scripts to be skipped
|
|
310
|
-
try {
|
|
311
|
-
const suiteDetails = JSON.parse(BUFFER.getItem('FROTHE_SUITE_DETAILS'));
|
|
312
|
-
for (const script of suiteDetails) {
|
|
313
|
-
await exeDetails.updateScriptExecutionStatus(
|
|
314
|
-
BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
|
|
315
|
-
BUFFER.getItem('FROTH_LOGIN_TOKEN'),
|
|
316
|
-
script.scriptId,
|
|
317
|
-
script.platform.toLowerCase(),
|
|
318
|
-
'SKIPPED'
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
} catch (e) {
|
|
322
|
-
console.error('Failed to mark scripts as SKIPPED:', e.message);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
336
|
await safeUpdateExecution();
|
|
326
337
|
},
|
|
327
338
|
/* ========== ON COMPLETE ========== */
|
|
328
339
|
onComplete: async (exitCode, _, __, results) => {
|
|
329
340
|
console.log('==== ON COMPLETE ====');
|
|
330
341
|
console.log(`Total: ${results.total || 0}, Passed: ${results.passed || 0}, Failed: ${results.failed || 0}`);
|
|
342
|
+
//console.log("Exit code onComplete===>" + exitCode)
|
|
343
|
+
|
|
331
344
|
if (exitCode === undefined || exitCode === null) {
|
|
332
345
|
exitCode = 1 // treat as failure
|
|
333
346
|
}
|
|
@@ -385,7 +398,7 @@ async function validateSyntax(specs) {
|
|
|
385
398
|
let syntaxFailed = false;
|
|
386
399
|
|
|
387
400
|
for (const fileUrl of specs) {
|
|
388
|
-
console.log("file path ",
|
|
401
|
+
console.log("file path ",fileUrl)
|
|
389
402
|
const filePath = url.fileURLToPath(fileUrl);
|
|
390
403
|
const code = fs.readFileSync(filePath, 'utf8');
|
|
391
404
|
|
|
@@ -1,8 +1,58 @@
|
|
|
1
|
-
module.exports = () =>
|
|
2
|
-
|
|
1
|
+
module.exports = (bsCaps) => {
|
|
2
|
+
const browserName = (bsCaps.browserName || 'chrome').toLowerCase();
|
|
3
|
+
//const browserVersion = bsCaps.browserVersion;
|
|
3
4
|
|
|
5
|
+
// Map browser names to their WebdriverIO services
|
|
6
|
+
const browserServiceMap = {
|
|
7
|
+
chrome: 'chromedriver',
|
|
8
|
+
firefox: 'geckodriver',
|
|
9
|
+
edge: 'edgedriver',
|
|
10
|
+
ie: 'iedriver',
|
|
11
|
+
'internet explorer': 'iedriver',
|
|
12
|
+
safari: 'safaridriver'
|
|
13
|
+
};
|
|
4
14
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
15
|
+
const service = browserServiceMap[browserName] || 'chromedriver';
|
|
16
|
+
|
|
17
|
+
const config = {
|
|
18
|
+
services: [service]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Add browser-specific capabilities
|
|
22
|
+
if (browserName === 'chrome') {
|
|
23
|
+
config.capabilities = [{
|
|
24
|
+
browserName: 'chrome',
|
|
25
|
+
'goog:chromeOptions': {
|
|
26
|
+
// args: browserVersion ? [`--version=${browserVersion}`] : []
|
|
27
|
+
}
|
|
28
|
+
}];
|
|
29
|
+
} else if (browserName === 'firefox') {
|
|
30
|
+
config.capabilities = [{
|
|
31
|
+
browserName: 'firefox',
|
|
32
|
+
'moz:firefoxOptions': {
|
|
33
|
+
// Add Firefox-specific options if needed
|
|
34
|
+
}
|
|
35
|
+
}];
|
|
36
|
+
} else if (browserName === 'edge') {
|
|
37
|
+
config.capabilities = [{
|
|
38
|
+
browserName: 'MicrosoftEdge'
|
|
39
|
+
}];
|
|
40
|
+
} else if (browserName === 'safari') {
|
|
41
|
+
config.capabilities = [{
|
|
42
|
+
browserName: 'safari'
|
|
43
|
+
}];
|
|
44
|
+
} else if (browserName === 'ie' || browserName === 'internet explorer') {
|
|
45
|
+
config.capabilities = [{
|
|
46
|
+
browserName: 'internet explorer'
|
|
47
|
+
}];
|
|
48
|
+
} else {
|
|
49
|
+
// Default to Chrome for unsupported browsers
|
|
50
|
+
config.capabilities = [{
|
|
51
|
+
browserName: 'chrome'
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(`🌐 Local execution configured for: ${browserName}${browserVersion ? ` (v${browserVersion})` : ''} using service: ${service}`);
|
|
56
|
+
|
|
57
|
+
return config;
|
|
58
|
+
};
|
|
@@ -22,7 +22,7 @@ try {
|
|
|
22
22
|
process.env.BROWSERSTACK_ACCESS_KEY = Buffer.from(bsCaps.accessKey, 'base64').toString('utf-8')
|
|
23
23
|
// Merge chrome-specific options if applicable
|
|
24
24
|
|
|
25
|
-
} catch (
|
|
25
|
+
} catch (err) {
|
|
26
26
|
console.error('❌ Failed to load capability YAML:', err.message);
|
|
27
27
|
process.exit(1);
|
|
28
28
|
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
"
|
|
3
|
-
"version": "7.0.118",
|
|
1
|
+
{ "name": "froth-webdriverio-framework",
|
|
2
|
+
"version": "7.0.119-dev1.0",
|
|
4
3
|
"readme": "WebdriverIO Integration",
|
|
5
4
|
"description": "WebdriverIO and BrowserStack App Automate",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
|
|
8
7
|
"scripts": {
|
|
9
|
-
"wdio:ios": "npx wdio ./ios.conf.js",
|
|
10
|
-
"wdio:android": "npx wdio ./android.conf.js",
|
|
11
|
-
"wdio:web": "npx wdio ./web.conf.js",
|
|
12
|
-
"wdio:webbs": "npx wdio ./web.conf.bs.js",
|
|
13
|
-
"wdio:ios:local": "npx wdio ./ios.local.conf.js",
|
|
14
|
-
"android:generate-allure-report": "allure generate ./mobile/androidReports/allure-results --clean && allure open",
|
|
15
|
-
"ios:generate-allure-report": "allure generate ./mobile/iosReports/allure-results --clean && allure open",
|
|
16
|
-
"web:generate-allure-report": "allure generate ./webReports/allure-results --clean && allure open",
|
|
17
8
|
"lint": "eslint ."
|
|
18
9
|
},
|
|
19
10
|
"repository": {
|
|
@@ -26,16 +17,17 @@
|
|
|
26
17
|
"appium"
|
|
27
18
|
],
|
|
28
19
|
"dependencies": {
|
|
29
|
-
|
|
30
|
-
"@wdio/
|
|
31
|
-
"@wdio/
|
|
32
|
-
"@wdio/
|
|
33
|
-
"@wdio/
|
|
20
|
+
|
|
21
|
+
"@wdio/appium-service": "9.23.0",
|
|
22
|
+
"@wdio/browserstack-service": "9.23.0",
|
|
23
|
+
"@wdio/cli": "9.23.0",
|
|
24
|
+
"@wdio/local-runner": "9.23.0",
|
|
25
|
+
"@wdio/mocha-framework": "9.23.0",
|
|
34
26
|
"@wdio/spec-reporter": "^9.20.0",
|
|
35
27
|
"appium": "^3.1.2",
|
|
36
28
|
"appium-uiautomator2-driver": "^6.7.8",
|
|
37
29
|
"assert": "^2.1.0",
|
|
38
|
-
"axios": "
|
|
30
|
+
"axios": "1.14.0",
|
|
39
31
|
"browserstack-local": "^1.5.8",
|
|
40
32
|
"chai": "^6.2.2",
|
|
41
33
|
"crypto-js": "^4.2.0",
|
|
@@ -52,6 +44,8 @@
|
|
|
52
44
|
"randexp": "^0.5.3",
|
|
53
45
|
"ts-node": "^10.9.2",
|
|
54
46
|
"typescript": "^5.9.3",
|
|
47
|
+
|
|
55
48
|
"vm": "^0.1.0"
|
|
49
|
+
|
|
56
50
|
}
|
|
57
|
-
}
|
|
51
|
+
}
|
package/log/key-metrics.json
DELETED
|
File without changes
|
|
File without changes
|