froth-webdriverio-framework 7.0.116 → 7.0.118

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.
@@ -56,6 +56,7 @@ let amendBrowserStackLog = null;
56
56
  let logJsonDataToTable = null;
57
57
 
58
58
  let extractEmailLinks = null;
59
+ let comparator=null;
59
60
 
60
61
  if (process.env.LOCATION == null || process.env.LOCATION == 'local') {
61
62
  basepath = ".";
@@ -116,7 +117,7 @@ captureLoadNavigation = require(basepath + '/captureNavigationTime').captureLoad
116
117
 
117
118
  amendBrowserStackLog = require(basepath + '/../froth_api_calls/browsersatckSessionInfo').amend2Browserstack;
118
119
  logJsonDataToTable = require(basepath + '/logData').logJsonData2Table;
119
-
120
+ comparator=require(basepath +'/dbValidator').validateDbFields
120
121
  //extractEmailLinks = require(basepath + '/emailParsing');
121
122
  //export the variabels
122
123
  module.exports = {
@@ -163,5 +164,6 @@ module.exports = {
163
164
  captureLoadNavigation,
164
165
  amendBrowserStackLog,
165
166
  logJsonDataToTable,
166
- extractEmailLinks
167
+ extractEmailLinks,
168
+ comparator
167
169
  };
@@ -0,0 +1,150 @@
1
+ const amendBrowserStackLog = require('../froth_api_calls/browsersatckSessionInfo').amend2Browserstack;
2
+
3
+ /**
4
+ * Convert any timestamp string/number to milliseconds.
5
+ * Auto-detects multiple formats.
6
+ */
7
+ async function parseTimestamp(input) {
8
+ if (!input) return NaN;
9
+
10
+ // Case 1: Numeric → Unix timestamp (ms or sec)
11
+ if (!isNaN(input)) {
12
+ const num = Number(input);
13
+
14
+ // If it's in seconds (10 digits), convert to ms
15
+ if (num.toString().length === 10) return num * 1000;
16
+
17
+ // Already ms (13 digits)
18
+ return num;
19
+ }
20
+
21
+ // Case 2: Direct Date() parseable ISO formats
22
+ let parsed = Date.parse(input);
23
+ if (!isNaN(parsed)) return parsed;
24
+
25
+ // Case 3: Common non-ISO formats → manual normalization
26
+ const replacements = [
27
+ { pattern: /\//g, replace: '-' }, // 2025/01/10 -> 2025-01-10
28
+ { pattern: / /g, replace: 'T' } // 2025-01-10 12:30 -> 2025-01-10T12:30
29
+ ];
30
+
31
+ let normalized = input;
32
+ replacements.forEach(r => {
33
+ normalized = normalized.replace(r.pattern, r.replace);
34
+ });
35
+
36
+ parsed = Date.parse(normalized);
37
+ if (!isNaN(parsed)) return parsed;
38
+
39
+ // Case 4: Try reversing DD-MM-YYYY → YYYY-MM-DD
40
+ const dmY = /^(\d{2})-(\d{2})-(\d{4})(.*)$/;
41
+ if (dmY.test(input)) {
42
+ const parts = input.match(dmY);
43
+ normalized = `${parts[3]}-${parts[2]}-${parts[1]}${parts[4]}`;
44
+ parsed = Date.parse(normalized);
45
+ if (!isNaN(parsed)) return parsed;
46
+ }
47
+
48
+ return NaN;
49
+ }
50
+
51
+ /**
52
+ * Main DB validation utility
53
+ */
54
+ async function validateDbFields(actualData, expectedData, context = 'DB Validation') {
55
+ await amendBrowserStackLog(`🔍 START DB VALIDATION: ${context}`, 'info');
56
+
57
+ const results = [];
58
+ let allPassed = true;
59
+
60
+ for (const key of Object.keys(expectedData)) {
61
+
62
+ const expectedConfig = expectedData[key];
63
+ const actual = actualData[key];
64
+ let expected = expectedConfig;
65
+ let status = "PASS";
66
+
67
+ // -----------------------------
68
+ // SKIP DYNAMIC FIELDS
69
+ // -----------------------------
70
+ if (expectedConfig === "*dynamic*") {
71
+ results.push({
72
+ key, actual, expected: "(SKIPPED - dynamic)", status: "SKIPPED"
73
+ });
74
+ continue;
75
+ }
76
+
77
+ // -----------------------------
78
+ // AUTO-DETECT TIMESTAMP VALIDATION
79
+ // -----------------------------
80
+ if (typeof expectedConfig === "object" && expectedConfig.type === "timestamp") {
81
+ expected = expectedConfig.value;
82
+ const tolerance = expectedConfig.toleranceMs || 0;
83
+
84
+ let actualMs = await parseTimestamp(actual);
85
+ let expectedMs = await parseTimestamp(expected);
86
+
87
+ if (isNaN(actualMs) || isNaN(expectedMs)) {
88
+ status = "FAIL";
89
+ results.push({
90
+ key,
91
+ actual,
92
+ expected,
93
+ status: "FAIL - Unrecognized Timestamp Format"
94
+ });
95
+ allPassed = false;
96
+ continue;
97
+ }
98
+
99
+ const diff = Math.abs(actualMs - expectedMs);
100
+ if (diff > tolerance) status = "FAIL";
101
+
102
+ results.push({
103
+ key,
104
+ actual,
105
+ expected: `${expected} (±${tolerance}ms)`,
106
+ status
107
+ });
108
+
109
+ if (status === "FAIL") allPassed = false;
110
+ continue;
111
+ }
112
+
113
+ // -----------------------------
114
+ // NORMAL STRING/NUMBER COMPARISON
115
+ // -----------------------------
116
+ if (String(actual) !== String(expected)) {
117
+ status = "FAIL";
118
+ allPassed = false;
119
+ }
120
+
121
+ results.push({ key, actual, expected, status });
122
+ }
123
+
124
+ // -----------------------------
125
+ // BROWSERSTACK LOGGING
126
+ // -----------------------------
127
+ // const chunkSize = 800;
128
+ // const combined = results
129
+ // .map(r => `${r.key} => Expected: ${r.expected}, Actual: ${r.actual}, Status: ${r.status}`)
130
+ // .join(" | ");
131
+
132
+ // const chunks = combined.match(new RegExp(`.{1,${chunkSize}}`, "g")) || [];
133
+ // for (const c of chunks) await amendBrowserStackLog(c, "info");
134
+
135
+ await amendBrowserStackLog(combined, "info");
136
+ // -----------------------------
137
+ // FINAL RESULT
138
+ // -----------------------------
139
+ await amendBrowserStackLog(
140
+ allPassed ? "✅ DB VALIDATION PASSED" : "❌ DB VALIDATION FAILED",
141
+ allPassed ? "info" : "error"
142
+ );
143
+
144
+ return allPassed;
145
+ }
146
+
147
+ module.exports = {
148
+ parseTimestamp,
149
+ validateDbFields
150
+ };
@@ -204,20 +204,20 @@ const commonHooks = {
204
204
  beforeTest: async (test) => {
205
205
  console.log(`▶️ START TEST: ${test.title}`);
206
206
 
207
- // Update script status to IN_PROGRESS
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
- // await exeDetails.updateScriptExecutionStatus(
214
- // BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
215
- // BUFFER.getItem('FROTH_LOGIN_TOKEN'),
216
- // script.scriptId,
217
- // script.platform.toLowerCase(),
218
- // 'IN_PROGRESS'
219
- // );
220
- // }
207
+ // Get suite details and script info
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
+ await exeDetails.updateScriptExecutionStatus(
214
+ BUFFER.getItem('ORGANISATION_DOMAIN_URL'),
215
+ BUFFER.getItem('FROTH_LOGIN_TOKEN'),
216
+ script.scriptId,
217
+ script.platform.toLowerCase(),
218
+ "IN PROGRESS"
219
+ );
220
+ }
221
221
  },
222
222
 
223
223
  /* ========== AFTER TEST ========== */
@@ -306,6 +306,22 @@ const commonHooks = {
306
306
  );
307
307
  }
308
308
 
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
+
309
325
  await safeUpdateExecution();
310
326
  },
311
327
  /* ========== ON COMPLETE ========== */
@@ -369,7 +385,7 @@ async function validateSyntax(specs) {
369
385
  let syntaxFailed = false;
370
386
 
371
387
  for (const fileUrl of specs) {
372
- console.log("file path ",fileUrl)
388
+ console.log("file path ", fileUrl)
373
389
  const filePath = url.fileURLToPath(fileUrl);
374
390
  const code = fs.readFileSync(filePath, 'utf8');
375
391