froth-webdriverio-framework 7.0.10 → 7.0.12

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,125 @@
1
+ const crypto = require('crypto');
2
+
3
+ //const SECRET_KEY = "froth-testops@rd";
4
+
5
+ async function encryptData(data, secretKey) {
6
+ try {
7
+ if (!data) return null
8
+
9
+ // Generate 12-byte nonce (GCM standard)
10
+ const nonce = crypto.getRandomValues(new Uint8Array(12))
11
+
12
+ // Import key (must be exactly 32 bytes)
13
+ const key = await crypto.subtle.importKey(
14
+ "raw",
15
+ new TextEncoder().encode(secretKey),
16
+ { name: "AES-GCM" },
17
+ false,
18
+ ["encrypt"]
19
+ )
20
+
21
+ // Encrypt
22
+ const encryptedBuffer = await crypto.subtle.encrypt(
23
+ {
24
+ name: "AES-GCM",
25
+ iv: nonce,
26
+ tagLength: 128, // 16 bytes
27
+ },
28
+ key,
29
+ new TextEncoder().encode(data)
30
+ )
31
+
32
+ // WebCrypto output = ciphertext + tag
33
+ const encryptedBytes = new Uint8Array(encryptedBuffer)
34
+
35
+ const ciphertext = encryptedBytes.slice(0, encryptedBytes.length - 16)
36
+ const tag = encryptedBytes.slice(encryptedBytes.length - 16)
37
+
38
+ // nonce + tag + ciphertext (same as backend)
39
+ const payload = new Uint8Array(
40
+ nonce.length + tag.length + ciphertext.length
41
+ )
42
+ payload.set(nonce)
43
+ payload.set(tag, nonce.length)
44
+ payload.set(ciphertext, nonce.length + tag.length)
45
+
46
+ // Base64 encode
47
+ return btoa(String.fromCharCode(...payload))
48
+ } catch (err) {
49
+ console.error("Encryption failed:", err)
50
+ return null
51
+ }
52
+ }
53
+
54
+
55
+
56
+
57
+ async function decrpytData(encryptedData) {
58
+ try {
59
+ if (!encryptedData) return null
60
+
61
+ // Base64 → Uint8Array
62
+ const encryptedBytes = Uint8Array.from(atob(encryptedData), c =>
63
+ c.charCodeAt(0)
64
+ )
65
+
66
+ // Extract nonce, tag, ciphertext
67
+ const nonce = encryptedBytes.slice(0, 12) // 12 bytes
68
+ const tag = encryptedBytes.slice(12, 28) // 16 bytes
69
+ const ciphertext = encryptedBytes.slice(28)
70
+
71
+ // WebCrypto expects: ciphertext + tag
72
+ const encryptedPayload = new Uint8Array(ciphertext.length + tag.length)
73
+ encryptedPayload.set(ciphertext)
74
+ encryptedPayload.set(tag, ciphertext.length)
75
+
76
+ // Import key
77
+ const key = await crypto.subtle.importKey(
78
+ "raw",
79
+ new TextEncoder().encode(config.encryptKeyValue),
80
+ { name: "AES-GCM" },
81
+ false,
82
+ ["decrypt"]
83
+ )
84
+
85
+ // Decrypt
86
+ const decryptedBuffer = await crypto.subtle.decrypt(
87
+ {
88
+ name: "AES-GCM",
89
+ iv: nonce,
90
+ tagLength: 128, // bits (16 bytes)
91
+ },
92
+ key,
93
+ encryptedPayload
94
+ )
95
+
96
+ return new TextDecoder().decode(decryptedBuffer)
97
+ } catch (error) {
98
+ console.error("Error decrypting:", error)
99
+ return null
100
+ }
101
+
102
+ }
103
+
104
+ module.exports = {
105
+ encryptData,
106
+ decrpytData
107
+ };
108
+
109
+ await encryptData(
110
+ data,
111
+ secret_key
112
+ )
113
+
114
+ const decrypted_data = await decrpytData(response)
115
+ const data = JSON.parse(decrypted_data)
116
+ console.log("decrpted data" + data)
117
+ return data
118
+
119
+ // Encrypt a password
120
+ //const encryptedPassword = encryptData("admin@1234", SECRET_KEY);
121
+ //console.log("Encrypted Password:", encryptedPassword);
122
+
123
+
124
+
125
+
@@ -126,10 +126,7 @@ async function amend2Browserstack(annotationMessage, level) {
126
126
  : chunks[i];
127
127
 
128
128
  // 🔍 LOCAL LOG
129
- console.log("=======================================");
130
- console.log(`BrowserStack Chunk ${i + 1}/${chunks.length}`);
131
- console.log(chunkMessage);
132
- console.log("=======================================");
129
+ console.log(`=======> BrowserStack Chunk ${i + 1}/${chunks.length}`, JSON.stringify(chunkMessage, null, 2));
133
130
 
134
131
  // 🚀 SEND TO BROWSERSTACK (WDIO-safe)
135
132
  if (process.env.PLATFORM === "browserstack") {
@@ -1,3 +1,4 @@
1
+ const aes=require('./aesEncryptionDecryption')
1
2
  /* =========================================================
2
3
  Execution / Script API Helpers (Normalized)
3
4
  ========================================================= */
@@ -261,3 +262,24 @@ module.exports = {
261
262
  updateScriptExecutionStatus,
262
263
  update_CICDRUNID_ReportUrl
263
264
  };
265
+
266
+ async function main() {
267
+ try {
268
+ const frothUrl = "devapi.frothtestops.com";
269
+ // const username = "subhra.subudhi@roboticodigital.com";
270
+ // const password = "V2VsY29tZUAxMjM=";
271
+
272
+ // const token = await getLoginToken(frothUrl, username, password);
273
+ // if (!token) {
274
+ // throw new Error('Login failed, no token obtained');
275
+ // }
276
+ const token='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzcyNTgyMzk5LCJpYXQiOjE3NjQ3NjU3OTQsImp0aSI6IjRhOWUyNjlkNWZhMzRlYzQ4NjZhZjk5MTc3Y2MwNzZiIiwidXNlcl9pZCI6NH0.1a_KwJvW3LOoBgzWMZBCoyGnA3eNm_XYeiah6Ql_EoA'
277
+ const id = 147;
278
+ const data = await getExecuitonDetails(frothUrl, token, id);
279
+ console.log("Retrieved JSON Data:", data);
280
+ } catch (error) {
281
+ console.error('Error in main function:', error);
282
+ }
283
+ }
284
+
285
+ main();
@@ -1,7 +1,7 @@
1
1
  //const fetch = require('node-fetch'); // Import the fetch function
2
2
  //const FormData = require('form-data'); // Import the FormData constructor
3
3
 
4
- const enc = require('./aesEncryption.js')
4
+ const enc = require('./aesEncryptionDecryption.js')
5
5
  async function getLoginToken(frothUrl, email, password) {
6
6
  try {
7
7
  const url = `${frothUrl}/api/login/`;
@@ -8,7 +8,7 @@ const amendToBrowserstack = require("../froth_api_calls/browsersatckSessionInfo"
8
8
  * UTILS
9
9
  * ===============================
10
10
  */
11
- function safeStringify(data) {
11
+ async function safeStringify(data) {
12
12
  try {
13
13
  return JSON.stringify(data, null, 2);
14
14
  } catch {
@@ -32,6 +32,7 @@ async function callapi(
32
32
  ) {
33
33
  let response;
34
34
  const startTime = Date.now();
35
+ console.log("Final API URL:", api_url);
35
36
 
36
37
  try {
37
38
  const method = methodType.toUpperCase();
@@ -39,11 +40,18 @@ async function callapi(
39
40
 
40
41
  let body;
41
42
  if (bodyType === "raw" && payloadDetails) {
43
+ console.log("Payload (JSON):", JSON.stringify(payloaddetails));
42
44
  body = payloadDetails;
45
+ console.log("Payload (raw):", body);
46
+
43
47
  }
44
48
 
45
49
  if (bodyType === "form-data" && payloadDetails) {
46
- body = jsonToFormData(payloadDetails);
50
+ body = await jsonToFormData(payloadDetails);
51
+ console.log("Payload (FormData):", body);
52
+ for (let [key, value] of body.entries()) {
53
+ console.log(`FormData Key: ${key}, Value: ${value}`);
54
+ }
47
55
  Object.assign(headers, body.getHeaders());
48
56
  }
49
57
 
@@ -52,7 +60,7 @@ async function callapi(
52
60
  * Full request annotated with chunking handled in amend2Browserstack
53
61
  */
54
62
  await amendToBrowserstack.amend2Browserstack(
55
- safeStringify({
63
+ await safeStringify({
56
64
  method,
57
65
  url: apiUrl,
58
66
  bodyType,
@@ -73,14 +81,15 @@ async function callapi(
73
81
  const duration = Date.now() - startTime;
74
82
 
75
83
  // Always store full response
76
- BUFFER.setItem("LAST_API_RESPONSE", response.data);
84
+ // BUFFER.setItem("LAST_API_RESPONSE", response.data);
85
+ console.log("Response Data:", response.data);
77
86
 
78
87
  /**
79
88
  * -------- ANNOTATE FULL RESPONSE --------
80
89
  * Now chunking is handled in amend2Browserstack
81
90
  */
82
91
  await amendToBrowserstack.amend2Browserstack(
83
- safeStringify({
92
+ await safeStringify({
84
93
  status: response.status,
85
94
  durationMs: duration,
86
95
  data: response.data
@@ -89,8 +98,9 @@ async function callapi(
89
98
  );
90
99
 
91
100
  } catch (error) {
101
+ console.error('Error during API call in call api menthod:', error);
92
102
  await amendToBrowserstack.amend2Browserstack(
93
- safeStringify({
103
+ await safeStringify({
94
104
  message: error.message,
95
105
  status: error.response?.status,
96
106
  data: error.response?.data
@@ -109,20 +119,21 @@ async function callapi(
109
119
  * JSON → FORM DATA
110
120
  * ===============================
111
121
  */
112
- function jsonToFormData(json) {
122
+ async function jsonToFormData(json) {
113
123
  const formData = new FormData();
114
124
 
115
- function append(data, parentKey) {
125
+ async function append(data, parentKey) {
116
126
  if (data && typeof data === "object" && !Array.isArray(data)) {
117
- Object.keys(data).forEach(key =>
118
- append(data[key], parentKey ? `${parentKey}[${key}]` : key)
119
- );
127
+ for (const key of Object.keys(data)) {
128
+ await append(data[key], parentKey ? `${parentKey}[${key}]` : key);
129
+ }
120
130
  } else {
121
131
  formData.append(parentKey, data);
122
132
  }
123
133
  }
124
134
 
125
- append(json);
135
+ await append(json);
136
+ console.log("FormData in json to formdata:", formData);
126
137
  return formData;
127
138
  }
128
139
 
@@ -149,6 +160,8 @@ async function formHeaders(authentication, headers = {}, bodyType) {
149
160
  ).toString("base64")}`;
150
161
  }
151
162
  }
163
+ console.log('Headers:', headers);
164
+
152
165
 
153
166
  return headers;
154
167
  }
@@ -168,7 +181,7 @@ async function validate(
168
181
  ) {
169
182
  switch (actionName.toLowerCase()) {
170
183
  case "verify":
171
- return validateAttributeData(
184
+ return await validateAttributeData(
172
185
  attributeName,
173
186
  actualValue,
174
187
  useBuffer,
@@ -189,7 +202,7 @@ async function validate(
189
202
  `Retrieved value from BUFFER: ${bufferKey}`,
190
203
  "info"
191
204
  );
192
- return BUFFER.getItem(bufferKey);
205
+ return await BUFFER.getItem(bufferKey);
193
206
  }
194
207
  }
195
208
 
@@ -200,6 +213,7 @@ async function validateAttributeData(
200
213
  bufferKey,
201
214
  datatype
202
215
  ) {
216
+ let assertionStatus = false; // Initialize status
203
217
  let expectedValue = useBuffer
204
218
  ? BUFFER.getItem(bufferKey)
205
219
  : bufferKey;
@@ -220,14 +234,16 @@ async function validateAttributeData(
220
234
  }
221
235
 
222
236
  try {
223
- expect(actualValue).toBe(expectedValue);
237
+ expect(attribute).toBe(expectedValue, `${attributeName} --> Expected value: ${expectedValue}, but got: ${attribute}`);
238
+ let annotationMessage = `Attribute name : ${attributeName} - verification passed. Actual text: ${attribute}, Expected text: ${expectedValue}.`;
224
239
  await amendToBrowserstack.amend2Browserstack(
225
- `${attributeName} verification passed`,
240
+ annotationMessage,
226
241
  "info"
227
242
  );
228
243
  } catch (e) {
244
+ let annotationMessage = `Attribute name : ${attributeName} - verification failed. Expected text: ${expectedValue}. error: ${e.toString()}`;
229
245
  await amendToBrowserstack.amend2Browserstack(
230
- `${attributeName} verification failed`,
246
+ annotationMessage,
231
247
  "error"
232
248
  );
233
249
  throw e;
@@ -36,7 +36,7 @@ module.exports = (bsCaps) => {
36
36
  debug: bsCaps.debug,
37
37
  networkLogs: bsCaps.networkLogs,
38
38
  interactiveDebugging: bsCaps.interactiveDebugging,
39
-
39
+
40
40
  }
41
41
  }],
42
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "froth-webdriverio-framework",
3
- "version": "7.0.10",
3
+ "version": "7.0.12",
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": {
@@ -1,33 +0,0 @@
1
- const crypto = require('crypto');
2
-
3
- //const SECRET_KEY = "froth-testops@rd";
4
-
5
- async function encryptData(data, secretKey) {
6
- // Generate a random 16-byte IV (Initialization Vector)
7
- const iv = crypto.randomBytes(16);
8
-
9
- // Ensure the key is 16 bytes long
10
- const key = Buffer.from(secretKey, 'utf-8');
11
-
12
- // Initialize cipher in CBC mode with the key and IV
13
- const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
14
-
15
- // Encrypt the data
16
- let encrypted = cipher.update(data, 'utf-8', 'base64');
17
- encrypted += cipher.final('base64');
18
-
19
- // Combine the IV and encrypted data, encode as base64
20
- const encryptedData = Buffer.concat([iv, Buffer.from(encrypted, 'base64')]).toString('base64');
21
-
22
- return encryptedData;
23
- }
24
-
25
-
26
-
27
- // Encrypt a password
28
- //const encryptedPassword = encryptData("admin@1234", SECRET_KEY);
29
- //console.log("Encrypted Password:", encryptedPassword);
30
-
31
- module.exports = encryptData;
32
-
33
-