ftmocks-utils 1.2.4 → 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftmocks-utils",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "Util functions for FtMocks",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,171 @@
1
+ const path = require("path");
2
+ const fs = require("fs");
3
+
4
+ const charDifference = (str1, str2) => {
5
+ let count1 = {},
6
+ count2 = {};
7
+
8
+ for (let ch of str1) count1[ch] = (count1[ch] || 0) + 1;
9
+ for (let ch of str2) count2[ch] = (count2[ch] || 0) + 1;
10
+
11
+ let diff = 0;
12
+ let chars = new Set([...Object.keys(count1), ...Object.keys(count2)]);
13
+
14
+ for (let ch of chars) {
15
+ diff += Math.abs((count1[ch] || 0) - (count2[ch] || 0));
16
+ }
17
+
18
+ return diff;
19
+ };
20
+
21
+ const nameToFolder = (name) => {
22
+ return name.replaceAll(" ", "_");
23
+ };
24
+
25
+ const getMockDir = (config) => {
26
+ if (!path.isAbsolute(config.MOCK_DIR)) {
27
+ return path.resolve(process.cwd(), config.MOCK_DIR);
28
+ }
29
+ return config.MOCK_DIR;
30
+ };
31
+
32
+ const getFallbackDir = (config) => {
33
+ if (config.FALLBACK_DIR && !path.isAbsolute(config.FALLBACK_DIR)) {
34
+ return path.resolve(process.cwd(), config.FALLBACK_DIR);
35
+ }
36
+ return config.FALLBACK_DIR;
37
+ };
38
+
39
+ const capitalizeHeader = (header) => {
40
+ return header
41
+ .split("-")
42
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
43
+ .join("-");
44
+ };
45
+
46
+ const capitalizeHeaders = (headers) => {
47
+ return Object.fromEntries(
48
+ Object.entries(headers).map(([key, value]) => [
49
+ capitalizeHeader(key),
50
+ value,
51
+ ])
52
+ );
53
+ };
54
+
55
+ const areJsonEqual = (jsonObj1, jsonObj2) => {
56
+ // Check if both are objects and not null
57
+ if (
58
+ typeof jsonObj1 === "object" &&
59
+ jsonObj1 !== null &&
60
+ typeof jsonObj2 === "object" &&
61
+ jsonObj2 !== null
62
+ ) {
63
+ // Get the keys of both objects
64
+ const keys1 = Object.keys(jsonObj1);
65
+ const keys2 = Object.keys(jsonObj2);
66
+
67
+ // Check if the number of keys is different
68
+ if (keys1.length !== keys2.length) {
69
+ return false;
70
+ }
71
+
72
+ // Recursively check each key-value pair
73
+ for (let key of keys1) {
74
+ if (!keys2.includes(key) || !areJsonEqual(jsonObj1[key], jsonObj2[key])) {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ return true;
80
+ } else {
81
+ // For non-object types, use strict equality comparison
82
+ return jsonObj1 === jsonObj2;
83
+ }
84
+ };
85
+
86
+ const clearNulls = (postData) => {
87
+ Object.keys(postData || {}).forEach((key) => {
88
+ if (postData[key] === null) {
89
+ delete postData[key];
90
+ }
91
+ });
92
+ };
93
+
94
+ const processURL = (url, ignoreParams = []) => {
95
+ // Remove the hostname from the URL
96
+ const urlWithoutHost = url.replace(/^(https?:\/\/)?[^\/]+/, "");
97
+ const processedURL = new URL(`http://domain.com${urlWithoutHost}`);
98
+ const params = new URLSearchParams(processedURL.search);
99
+ if (ignoreParams?.length > 0) {
100
+ ignoreParams.forEach((ip) => {
101
+ params.delete(ip);
102
+ });
103
+ }
104
+ params.sort();
105
+ return decodeURIComponent(`${processedURL.pathname}?${params}`);
106
+ };
107
+
108
+ const getHeaders = (headers) => {
109
+ let res = null;
110
+ try {
111
+ res = new Map([
112
+ ...Object.entries(headers),
113
+ ...Object.entries(capitalizeHeaders(headers)),
114
+ ]);
115
+ } catch (e) {
116
+ console.error("error at getHeaders", e);
117
+ res = new Map([
118
+ ["Content-Type", "application/json"],
119
+ ["content-type", "application/json"],
120
+ ]);
121
+ }
122
+ return Object.fromEntries(res);
123
+ };
124
+
125
+ function countFilesInDirectory(directoryPath) {
126
+ return new Promise((resolve, reject) => {
127
+ fs.readdir(directoryPath, (err, files) => {
128
+ if (err) {
129
+ return reject(err); // Handle error
130
+ }
131
+
132
+ // Filter out directories and only count files
133
+ const fileCount = files.filter((file) => {
134
+ const filePath = path.join(directoryPath, file);
135
+ return fs.statSync(filePath).isFile();
136
+ }).length;
137
+
138
+ resolve(fileCount);
139
+ });
140
+ });
141
+ }
142
+
143
+ const getTestByName = async (ftmocksConifg, testName) => {
144
+ const testsPath = path.join(getMockDir(ftmocksConifg), "tests.json");
145
+ let tests = [];
146
+ try {
147
+ // Read existing tests
148
+ const testsData = fs.readFileSync(testsPath, "utf8");
149
+ tests = JSON.parse(testsData);
150
+ const etest = tests.find((tst) => tst.name === testName);
151
+ return etest;
152
+ } catch (error) {
153
+ console.error(`\x1b[31mError reading tests.json:\x1b[0m`, error);
154
+ return null;
155
+ }
156
+ };
157
+
158
+ module.exports = {
159
+ charDifference,
160
+ nameToFolder,
161
+ getMockDir,
162
+ getFallbackDir,
163
+ capitalizeHeader,
164
+ capitalizeHeaders,
165
+ areJsonEqual,
166
+ clearNulls,
167
+ processURL,
168
+ getHeaders,
169
+ countFilesInDirectory,
170
+ getTestByName,
171
+ };
package/src/index.js CHANGED
@@ -1,108 +1,25 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
3
  const { v4: uuidv4 } = require("uuid");
4
-
5
- function charDifference(str1, str2) {
6
- let count1 = {},
7
- count2 = {};
8
-
9
- for (let ch of str1) count1[ch] = (count1[ch] || 0) + 1;
10
- for (let ch of str2) count2[ch] = (count2[ch] || 0) + 1;
11
-
12
- let diff = 0;
13
- let chars = new Set([...Object.keys(count1), ...Object.keys(count2)]);
14
-
15
- for (let ch of chars) {
16
- diff += Math.abs((count1[ch] || 0) - (count2[ch] || 0));
17
- }
18
-
19
- return diff;
20
- }
21
-
22
- const nameToFolder = (name) => {
23
- return name.replaceAll(" ", "_");
24
- };
25
-
26
- const getMockDir = (config) => {
27
- if (!path.isAbsolute(config.MOCK_DIR)) {
28
- return path.resolve(process.cwd(), config.MOCK_DIR);
29
- }
30
- return config.MOCK_DIR;
31
- };
32
-
33
- const getFallbackDir = (config) => {
34
- if (config.FALLBACK_DIR && !path.isAbsolute(config.FALLBACK_DIR)) {
35
- return path.resolve(process.cwd(), config.FALLBACK_DIR);
36
- }
37
- return config.FALLBACK_DIR;
38
- };
39
-
40
- const capitalizeHeader = (header) => {
41
- return header
42
- .split("-")
43
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
44
- .join("-");
45
- };
46
-
47
- const capitalizeHeaders = (headers) => {
48
- return Object.fromEntries(
49
- Object.entries(headers).map(([key, value]) => [
50
- capitalizeHeader(key),
51
- value,
52
- ])
53
- );
54
- };
55
-
56
- const getHeaders = (headers) => {
57
- let res = null;
58
- try {
59
- res = new Map([
60
- ...Object.entries(headers),
61
- ...Object.entries(capitalizeHeaders(headers)),
62
- ]);
63
- } catch (e) {
64
- console.error("error at getHeaders", e);
65
- res = new Map([
66
- ["Content-Type", "application/json"],
67
- ["content-type", "application/json"],
68
- ]);
69
- }
70
- return Object.fromEntries(res);
71
- };
72
-
73
- const areJsonEqual = (jsonObj1, jsonObj2) => {
74
- // Check if both are objects and not null
75
- if (
76
- typeof jsonObj1 === "object" &&
77
- jsonObj1 !== null &&
78
- typeof jsonObj2 === "object" &&
79
- jsonObj2 !== null
80
- ) {
81
- // Get the keys of both objects
82
- const keys1 = Object.keys(jsonObj1);
83
- const keys2 = Object.keys(jsonObj2);
84
-
85
- // Check if the number of keys is different
86
- if (keys1.length !== keys2.length) {
87
- return false;
88
- }
89
-
90
- // Recursively check each key-value pair
91
- for (let key of keys1) {
92
- if (!keys2.includes(key) || !areJsonEqual(jsonObj1[key], jsonObj2[key])) {
93
- return false;
94
- }
95
- }
96
-
97
- return true;
98
- } else {
99
- // For non-object types, use strict equality comparison
100
- return jsonObj1 === jsonObj2;
101
- }
102
- };
4
+ const {
5
+ charDifference,
6
+ nameToFolder,
7
+ getMockDir,
8
+ getFallbackDir,
9
+ areJsonEqual,
10
+ clearNulls,
11
+ processURL,
12
+ getHeaders,
13
+ countFilesInDirectory,
14
+ getTestByName,
15
+ } = require("./common-utils");
103
16
 
104
17
  const getDefaultMockDataFromConfig = (testConfig) => {
105
- const defaultPath = path.join(getMockDir(testConfig), "default.json");
18
+ const defaultPath = path.join(
19
+ getMockDir(testConfig),
20
+ "defaultMocks",
21
+ "_mock_list.json"
22
+ );
106
23
 
107
24
  try {
108
25
  const defaultData = fs.readFileSync(defaultPath, "utf8");
@@ -125,7 +42,7 @@ const getDefaultMockDataFromConfig = (testConfig) => {
125
42
  });
126
43
  return parsedData;
127
44
  } catch (error) {
128
- console.error(`Error reading or parsing default.json:`, error);
45
+ console.error(`Error reading or parsing default mocks:`, error);
129
46
  return [];
130
47
  }
131
48
  };
@@ -174,14 +91,6 @@ const loadMockDataFromConfig = (testConfig, _testName) => {
174
91
  }
175
92
  };
176
93
 
177
- const clearNulls = (postData) => {
178
- Object.keys(postData || {}).forEach((key) => {
179
- if (postData[key] === null) {
180
- delete postData[key];
181
- }
182
- });
183
- };
184
-
185
94
  const isSameRequest = (req1, req2) => {
186
95
  clearNulls(req1.postData);
187
96
  clearNulls(req2.postData);
@@ -230,20 +139,6 @@ const getSameRequestRank = (req1, req2) => {
230
139
  return rank;
231
140
  };
232
141
 
233
- const processURL = (url, ignoreParams = []) => {
234
- // Remove the hostname from the URL
235
- const urlWithoutHost = url.replace(/^(https?:\/\/)?[^\/]+/, "");
236
- const processedURL = new URL(`http://domain.com${urlWithoutHost}`);
237
- const params = new URLSearchParams(processedURL.search);
238
- if (ignoreParams?.length > 0) {
239
- ignoreParams.forEach((ip) => {
240
- params.delete(ip);
241
- });
242
- }
243
- params.sort();
244
- return decodeURIComponent(`${processedURL.pathname}?${params}`);
245
- };
246
-
247
142
  function compareMockToRequest(mock, req) {
248
143
  const mockURL = processURL(
249
144
  mock.fileContent.url,
@@ -381,11 +276,18 @@ function getMatchingMockData({
381
276
  }
382
277
  // updating stats to mock file
383
278
  if (foundMock) {
384
- const mockFilePath = path.join(
279
+ let mockFilePath = path.join(
385
280
  getMockDir(testConfig),
386
281
  `test_${nameToFolder(testName)}`,
387
282
  `mock_${foundMock.id}.json`
388
283
  );
284
+ if (!fs.existsSync(mockFilePath)) {
285
+ mockFilePath = path.join(
286
+ getMockDir(testConfig),
287
+ "defaultMocks",
288
+ `mock_${foundMock.id}.json`
289
+ );
290
+ }
389
291
  foundMock.fileContent.served = true;
390
292
  fs.writeFileSync(
391
293
  mockFilePath,
@@ -460,12 +362,20 @@ async function initiatePlaywrightRoutes(
460
362
  };
461
363
 
462
364
  if (file) {
463
- const filePath = path.join(
365
+ let filePath = path.join(
464
366
  getMockDir(ftmocksConifg),
465
367
  `test_${nameToFolder(testName)}`,
466
368
  "_files",
467
369
  file
468
370
  );
371
+ if (!fs.existsSync(filePath)) {
372
+ filePath = path.join(
373
+ getMockDir(ftmocksConifg),
374
+ "defaultMocks",
375
+ "_files",
376
+ file
377
+ );
378
+ }
469
379
  if (fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) {
470
380
  const fileContent = fs.readFileSync(filePath);
471
381
  json.body = fileContent;
@@ -742,24 +652,6 @@ function initiateConsoleLogs(jest, ftmocksConifg, testName) {
742
652
  };
743
653
  }
744
654
 
745
- function countFilesInDirectory(directoryPath) {
746
- return new Promise((resolve, reject) => {
747
- fs.readdir(directoryPath, (err, files) => {
748
- if (err) {
749
- return reject(err); // Handle error
750
- }
751
-
752
- // Filter out directories and only count files
753
- const fileCount = files.filter((file) => {
754
- const filePath = path.join(directoryPath, file);
755
- return fs.statSync(filePath).isFile();
756
- }).length;
757
-
758
- resolve(fileCount);
759
- });
760
- });
761
- }
762
-
763
655
  const saveSnap = async (html, ftmocksConifg, testName) => {
764
656
  const snapFolder = path.join(
765
657
  getMockDir(ftmocksConifg),
@@ -824,21 +716,6 @@ function initiateJestEventSnaps(jest, ftmocksConifg, testName) {
824
716
  });
825
717
  }
826
718
 
827
- const getTestByName = async (ftmocksConifg, testName) => {
828
- const testsPath = path.join(getMockDir(ftmocksConifg), "tests.json");
829
- let tests = [];
830
- try {
831
- // Read existing tests
832
- const testsData = fs.readFileSync(testsPath, "utf8");
833
- tests = JSON.parse(testsData);
834
- const etest = tests.find((tst) => tst.name === testName);
835
- return etest;
836
- } catch (error) {
837
- console.error(`\x1b[31mError reading tests.json:\x1b[0m`, error);
838
- return null;
839
- }
840
- };
841
-
842
719
  const createTest = async (ftmocksConifg, testName) => {
843
720
  const testsPath = path.join(getMockDir(ftmocksConifg), "tests.json");
844
721
  let tests = [];