ftmocks-utils 1.3.1 → 1.3.3
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 +1 -1
- package/src/compare-utils.js +151 -0
- package/src/index.js +26 -316
- package/src/log-utils.js +103 -0
- package/src/mock-utils.js +101 -0
- package/src/rank-compare-utils.js +62 -0
- package/src/recorder.js +289 -271
- package/src/test-utils.js +49 -0
package/package.json
CHANGED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
const { clearNulls, processURL } = require("./common-utils");
|
|
2
|
+
const { FtJSON } = require("./json-utils");
|
|
3
|
+
|
|
4
|
+
const isUrlAndMethodSame = (req1, req2) => {
|
|
5
|
+
const url1 = new URL(`http://domain.com${req1.url}`);
|
|
6
|
+
const url2 = new URL(`http://domain.com${req2.url}`);
|
|
7
|
+
return (
|
|
8
|
+
url1.pathname === url2.pathname &&
|
|
9
|
+
url1.method?.toLowerCase() === url2.method?.toLowerCase()
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const isSameRequest = (req1, req2) => {
|
|
14
|
+
clearNulls(req1.postData);
|
|
15
|
+
clearNulls(req2.postData);
|
|
16
|
+
let matched = true;
|
|
17
|
+
if (req1.url !== req2.url) {
|
|
18
|
+
matched = false;
|
|
19
|
+
} else if (req1.method?.toLowerCase() !== req2.method?.toLowerCase()) {
|
|
20
|
+
matched = false;
|
|
21
|
+
} else if (
|
|
22
|
+
(!req1.postData && req2.postData) ||
|
|
23
|
+
(req1.postData && !req2.postData)
|
|
24
|
+
) {
|
|
25
|
+
matched = FtJSON.areJsonEqual(req1.postData || {}, req2.postData || {});
|
|
26
|
+
} else if (
|
|
27
|
+
req1.postData &&
|
|
28
|
+
req2.postData &&
|
|
29
|
+
!FtJSON.areJsonEqual(req1.postData, req2.postData)
|
|
30
|
+
) {
|
|
31
|
+
matched = false;
|
|
32
|
+
}
|
|
33
|
+
return matched;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const isSameResponse = (req1, req2) => {
|
|
37
|
+
try {
|
|
38
|
+
let matched = true;
|
|
39
|
+
if (req1.response.status !== req2.response.status) {
|
|
40
|
+
matched = false;
|
|
41
|
+
// console.log('not matched at url', req1.method, req2.method);
|
|
42
|
+
} else if (
|
|
43
|
+
(!req1.response.content && req2.response.content) ||
|
|
44
|
+
(req1.response.content && !req2.response.content)
|
|
45
|
+
) {
|
|
46
|
+
matched = FtJSON.areJsonEqual(
|
|
47
|
+
FtJSON.parse(req1.response.content) || {},
|
|
48
|
+
FtJSON.parse(req2.response.content) || {}
|
|
49
|
+
);
|
|
50
|
+
// console.log('not matched at post Data 0', req1.postData, req2.postData);
|
|
51
|
+
} else if (
|
|
52
|
+
req1.response.content &&
|
|
53
|
+
req2.response.content &&
|
|
54
|
+
!FtJSON.areJsonEqual(
|
|
55
|
+
FtJSON.parse(req1.response.content) || {},
|
|
56
|
+
FtJSON.parse(req2.response.content) || {}
|
|
57
|
+
)
|
|
58
|
+
) {
|
|
59
|
+
matched = false;
|
|
60
|
+
}
|
|
61
|
+
// if (matched) {
|
|
62
|
+
// console.log('matched responses', req1, req2);
|
|
63
|
+
// }
|
|
64
|
+
return matched;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(error);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function compareMockToRequest(mock, req) {
|
|
72
|
+
const mockURL = processURL(
|
|
73
|
+
mock.fileContent.url,
|
|
74
|
+
mock.fileContent.ignoreParams
|
|
75
|
+
);
|
|
76
|
+
const reqURL = processURL(req.originalUrl, mock.fileContent.ignoreParams);
|
|
77
|
+
const isSameUrlAndMethod = isUrlAndMethodSame(
|
|
78
|
+
{ url: mockURL, method: mock.fileContent.method },
|
|
79
|
+
{ url: reqURL, method: req.method }
|
|
80
|
+
);
|
|
81
|
+
if (!isSameUrlAndMethod) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const postData = mock.fileContent.request?.postData?.text
|
|
85
|
+
? FtJSON.parse(mock.fileContent.request?.postData?.text)
|
|
86
|
+
: mock.fileContent.request?.postData;
|
|
87
|
+
return isSameRequest(
|
|
88
|
+
{ url: mockURL, method: mock.fileContent.method, postData },
|
|
89
|
+
{
|
|
90
|
+
method: req.method,
|
|
91
|
+
postData: req.body,
|
|
92
|
+
url: reqURL,
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function compareMockToFetchRequest(mock, fetchReq) {
|
|
98
|
+
try {
|
|
99
|
+
const mockURL = processURL(
|
|
100
|
+
mock.fileContent.url,
|
|
101
|
+
mock.fileContent.ignoreParams
|
|
102
|
+
);
|
|
103
|
+
const reqURL = processURL(fetchReq.url, mock.fileContent.ignoreParams);
|
|
104
|
+
const isSameUrlAndMethod = isUrlAndMethodSame(
|
|
105
|
+
{ url: mockURL, method: mock.fileContent.method },
|
|
106
|
+
{ url: reqURL, method: fetchReq.options.method || "GET" }
|
|
107
|
+
);
|
|
108
|
+
if (!isSameUrlAndMethod) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const postData = mock.fileContent.request?.postData?.text
|
|
112
|
+
? FtJSON.parse(mock.fileContent.request?.postData?.text)
|
|
113
|
+
: mock.fileContent.request?.postData;
|
|
114
|
+
return isSameRequest(
|
|
115
|
+
{ url: mockURL, method: mock.fileContent.method, postData },
|
|
116
|
+
{
|
|
117
|
+
method: fetchReq.options.method || "GET",
|
|
118
|
+
postData: fetchReq.options.body?.length
|
|
119
|
+
? FtJSON.parse(fetchReq.options.body)
|
|
120
|
+
: fetchReq.options.body,
|
|
121
|
+
url: reqURL,
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.error("error at compareMockToFetchRequest", mock, fetchReq);
|
|
126
|
+
console.error(e);
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const compareMockToMock = (mock1, mock2, matchResponse) => {
|
|
132
|
+
try {
|
|
133
|
+
if (matchResponse) {
|
|
134
|
+
return isSameRequest(mock1, mock2) && isSameResponse(mock1, mock2);
|
|
135
|
+
} else {
|
|
136
|
+
return isSameRequest(mock1, mock2);
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(error);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
module.exports = {
|
|
145
|
+
isUrlAndMethodSame,
|
|
146
|
+
isSameRequest,
|
|
147
|
+
isSameResponse,
|
|
148
|
+
compareMockToRequest,
|
|
149
|
+
compareMockToFetchRequest,
|
|
150
|
+
compareMockToMock,
|
|
151
|
+
};
|
package/src/index.js
CHANGED
|
@@ -12,206 +12,25 @@ const {
|
|
|
12
12
|
countFilesInDirectory,
|
|
13
13
|
getTestByName,
|
|
14
14
|
} = require("./common-utils");
|
|
15
|
+
const {
|
|
16
|
+
getDefaultMockDataFromConfig,
|
|
17
|
+
loadMockDataFromConfig,
|
|
18
|
+
resetAllMockStats,
|
|
19
|
+
} = require("./mock-utils");
|
|
20
|
+
const { createTest } = require("./test-utils");
|
|
15
21
|
const { FtJSON } = require("./json-utils");
|
|
22
|
+
const { Logger, deleteAllLogs } = require("./log-utils");
|
|
23
|
+
const {
|
|
24
|
+
isSameRequest,
|
|
25
|
+
compareMockToRequest,
|
|
26
|
+
compareMockToFetchRequest,
|
|
27
|
+
compareMockToMock,
|
|
28
|
+
} = require("./compare-utils");
|
|
29
|
+
const { getCompareRankMockToFetchRequest } = require("./rank-compare-utils");
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
const defaultPath = path.join(
|
|
19
|
-
getMockDir(testConfig),
|
|
20
|
-
"defaultMocks",
|
|
21
|
-
"_mock_list.json"
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const defaultData = fs.readFileSync(defaultPath, "utf8");
|
|
26
|
-
let parsedData = JSON.parse(defaultData);
|
|
27
|
-
|
|
28
|
-
// Read and attach mock data for each entry in parsedData
|
|
29
|
-
parsedData.forEach((entry) => {
|
|
30
|
-
const mockFilePath = path.join(
|
|
31
|
-
getMockDir(testConfig),
|
|
32
|
-
"defaultMocks",
|
|
33
|
-
`mock_${entry.id}.json`
|
|
34
|
-
);
|
|
35
|
-
try {
|
|
36
|
-
const mockData = fs.readFileSync(mockFilePath, "utf8");
|
|
37
|
-
entry.fileContent = JSON.parse(mockData);
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error(`Error reading mock data for ${entry.id}:`, error);
|
|
40
|
-
return entry; // Return the original entry if there's an error
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
return parsedData;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error(`Error reading or parsing default mocks:`, error);
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
};
|
|
31
|
+
let logger = null;
|
|
49
32
|
|
|
50
33
|
// src/index.js
|
|
51
|
-
const loadMockDataFromConfig = (testConfig, _testName) => {
|
|
52
|
-
try {
|
|
53
|
-
let testName = _testName;
|
|
54
|
-
if (!testName) {
|
|
55
|
-
// Read the test ID from mockServer.config.json
|
|
56
|
-
const configPath = path.join(
|
|
57
|
-
getMockDir(testConfig),
|
|
58
|
-
"mockServer.config.json"
|
|
59
|
-
);
|
|
60
|
-
const configData = fs.readFileSync(configPath, "utf8");
|
|
61
|
-
const config = JSON.parse(configData);
|
|
62
|
-
testName = config.testName;
|
|
63
|
-
}
|
|
64
|
-
// Read the tests from testConfig
|
|
65
|
-
const mocksPath = path.join(
|
|
66
|
-
getMockDir(testConfig),
|
|
67
|
-
`test_${nameToFolder(testName)}`,
|
|
68
|
-
"_mock_list.json"
|
|
69
|
-
);
|
|
70
|
-
const mocksData = fs.readFileSync(mocksPath, "utf8");
|
|
71
|
-
const mocks = JSON.parse(mocksData);
|
|
72
|
-
|
|
73
|
-
mocks.forEach((mock) => {
|
|
74
|
-
const fileContent = JSON.parse(
|
|
75
|
-
fs.readFileSync(
|
|
76
|
-
path.join(
|
|
77
|
-
getMockDir(testConfig),
|
|
78
|
-
`test_${nameToFolder(testName)}`,
|
|
79
|
-
`mock_${mock.id}.json`
|
|
80
|
-
),
|
|
81
|
-
"utf8"
|
|
82
|
-
)
|
|
83
|
-
);
|
|
84
|
-
mock.fileContent = fileContent;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return mocks;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error("Error loading test data:", error.message);
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const isSameRequest = (req1, req2) => {
|
|
95
|
-
clearNulls(req1.postData);
|
|
96
|
-
clearNulls(req2.postData);
|
|
97
|
-
let matched = true;
|
|
98
|
-
if (req1.url !== req2.url) {
|
|
99
|
-
matched = false;
|
|
100
|
-
} else if (req1.method?.toLowerCase() !== req2.method?.toLowerCase()) {
|
|
101
|
-
matched = false;
|
|
102
|
-
} else if (
|
|
103
|
-
(!req1.postData && req2.postData) ||
|
|
104
|
-
(req1.postData && !req2.postData)
|
|
105
|
-
) {
|
|
106
|
-
matched = FtJSON.areJsonEqual(req1.postData || {}, req2.postData || {});
|
|
107
|
-
} else if (
|
|
108
|
-
req1.postData &&
|
|
109
|
-
req2.postData &&
|
|
110
|
-
!FtJSON.areJsonEqual(req1.postData, req2.postData)
|
|
111
|
-
) {
|
|
112
|
-
matched = false;
|
|
113
|
-
}
|
|
114
|
-
return matched;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const getSameRequestRank = (req1, req2) => {
|
|
118
|
-
let rank = 1;
|
|
119
|
-
clearNulls(req1.postData);
|
|
120
|
-
clearNulls(req2.postData);
|
|
121
|
-
// Compare path names
|
|
122
|
-
const url1 = new URL(`http://domain.com${req1.url}`);
|
|
123
|
-
const url2 = new URL(`http://domain.com${req2.url}`);
|
|
124
|
-
if (url1.pathname !== url2.pathname) {
|
|
125
|
-
rank = 0;
|
|
126
|
-
} else if (url1.method?.toLowerCase() !== url2.method?.toLowerCase()) {
|
|
127
|
-
rank = 0;
|
|
128
|
-
} else {
|
|
129
|
-
// Compare query strings
|
|
130
|
-
const queryDiff = charDifference(url1.search || "", url2.search || "");
|
|
131
|
-
rank = rank + queryDiff;
|
|
132
|
-
// Compare post data
|
|
133
|
-
const charDiff = charDifference(
|
|
134
|
-
FtJSON.stringify(req1.postData || {}),
|
|
135
|
-
FtJSON.stringify(req2.postData || {})
|
|
136
|
-
);
|
|
137
|
-
rank = rank + charDiff;
|
|
138
|
-
}
|
|
139
|
-
return rank;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
function compareMockToRequest(mock, req) {
|
|
143
|
-
const mockURL = processURL(
|
|
144
|
-
mock.fileContent.url,
|
|
145
|
-
mock.fileContent.ignoreParams
|
|
146
|
-
);
|
|
147
|
-
const reqURL = processURL(req.originalUrl, mock.fileContent.ignoreParams);
|
|
148
|
-
const postData = mock.fileContent.request?.postData?.text
|
|
149
|
-
? FtJSON.parse(mock.fileContent.request?.postData?.text)
|
|
150
|
-
: mock.fileContent.request?.postData;
|
|
151
|
-
return isSameRequest(
|
|
152
|
-
{ url: mockURL, method: mock.fileContent.method, postData },
|
|
153
|
-
{
|
|
154
|
-
method: req.method,
|
|
155
|
-
postData: req.body,
|
|
156
|
-
url: reqURL,
|
|
157
|
-
}
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function compareMockToFetchRequest(mock, fetchReq) {
|
|
162
|
-
try {
|
|
163
|
-
const mockURL = processURL(
|
|
164
|
-
mock.fileContent.url,
|
|
165
|
-
mock.fileContent.ignoreParams
|
|
166
|
-
);
|
|
167
|
-
const reqURL = processURL(fetchReq.url, mock.fileContent.ignoreParams);
|
|
168
|
-
const postData = mock.fileContent.request?.postData?.text
|
|
169
|
-
? FtJSON.parse(mock.fileContent.request?.postData?.text)
|
|
170
|
-
: mock.fileContent.request?.postData;
|
|
171
|
-
return isSameRequest(
|
|
172
|
-
{ url: mockURL, method: mock.fileContent.method, postData },
|
|
173
|
-
{
|
|
174
|
-
method: fetchReq.options.method || "GET",
|
|
175
|
-
postData: fetchReq.options.body?.length
|
|
176
|
-
? FtJSON.parse(fetchReq.options.body)
|
|
177
|
-
: fetchReq.options.body,
|
|
178
|
-
url: reqURL,
|
|
179
|
-
}
|
|
180
|
-
);
|
|
181
|
-
} catch (e) {
|
|
182
|
-
console.error("error at compareMockToFetchRequest", mock, fetchReq);
|
|
183
|
-
console.error(e);
|
|
184
|
-
}
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function getCompareRankMockToFetchRequest(mock, fetchReq) {
|
|
189
|
-
try {
|
|
190
|
-
const mockURL = processURL(
|
|
191
|
-
mock.fileContent.url,
|
|
192
|
-
mock.fileContent.ignoreParams
|
|
193
|
-
);
|
|
194
|
-
const reqURL = processURL(fetchReq.url, mock.fileContent.ignoreParams);
|
|
195
|
-
const postData = mock.fileContent.request?.postData?.text
|
|
196
|
-
? FtJSON.parse(mock.fileContent.request?.postData?.text)
|
|
197
|
-
: mock.fileContent.request?.postData;
|
|
198
|
-
return getSameRequestRank(
|
|
199
|
-
{ url: mockURL, method: mock.fileContent.method, postData },
|
|
200
|
-
{
|
|
201
|
-
method: fetchReq.options.method || "GET",
|
|
202
|
-
postData: fetchReq.options.body?.length
|
|
203
|
-
? FtJSON.parse(fetchReq.options.body)
|
|
204
|
-
: fetchReq.options.body,
|
|
205
|
-
url: reqURL,
|
|
206
|
-
}
|
|
207
|
-
);
|
|
208
|
-
} catch (e) {
|
|
209
|
-
console.error("error at getCompareRankMockToFetchRequest", mock, fetchReq);
|
|
210
|
-
console.error(e);
|
|
211
|
-
}
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
34
|
function getMatchingMockData({
|
|
216
35
|
testMockData,
|
|
217
36
|
defaultMockData,
|
|
@@ -297,22 +116,6 @@ function getMatchingMockData({
|
|
|
297
116
|
return foundMock ? foundMock.fileContent : null;
|
|
298
117
|
}
|
|
299
118
|
|
|
300
|
-
async function resetAllMockStats({ testMockData, testConfig, testName }) {
|
|
301
|
-
for (let i = 0; i < testMockData.length; i++) {
|
|
302
|
-
const tmd = testMockData[i];
|
|
303
|
-
const mockFilePath = path.join(
|
|
304
|
-
getMockDir(testConfig),
|
|
305
|
-
`test_${nameToFolder(testName)}`,
|
|
306
|
-
`mock_${tmd.id}.json`
|
|
307
|
-
);
|
|
308
|
-
tmd.fileContent.served = false;
|
|
309
|
-
await fs.writeFileSync(
|
|
310
|
-
mockFilePath,
|
|
311
|
-
JSON.stringify(tmd.fileContent, null, 2)
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
119
|
async function initiatePlaywrightRoutes(
|
|
317
120
|
page,
|
|
318
121
|
ftmocksConifg,
|
|
@@ -320,13 +123,18 @@ async function initiatePlaywrightRoutes(
|
|
|
320
123
|
mockPath = "**/*",
|
|
321
124
|
excludeMockPath = null
|
|
322
125
|
) {
|
|
126
|
+
logger = new Logger(
|
|
127
|
+
{ disableLogs: ftmocksConifg.DISABLE_LOGS },
|
|
128
|
+
ftmocksConifg,
|
|
129
|
+
testName
|
|
130
|
+
);
|
|
323
131
|
const testMockData = testName
|
|
324
132
|
? loadMockDataFromConfig(ftmocksConifg, testName)
|
|
325
133
|
: [];
|
|
326
134
|
resetAllMockStats({ testMockData, testConfig: ftmocksConifg, testName });
|
|
327
135
|
const test = await getTestByName(ftmocksConifg, testName);
|
|
328
136
|
const defaultMockData = getDefaultMockDataFromConfig(ftmocksConifg);
|
|
329
|
-
|
|
137
|
+
logger.debug("\x1b[32mcalling initiatePlaywrightRoutes fetch\x1b[0m");
|
|
330
138
|
let firstUrl = null;
|
|
331
139
|
await page.route(mockPath, async (route, request) => {
|
|
332
140
|
const url = request.url();
|
|
@@ -413,7 +221,7 @@ async function initiatePlaywrightRoutes(
|
|
|
413
221
|
fallbackDir,
|
|
414
222
|
ftmocksConifg.FALLBACK_DIR_INDEX_FILE_FOR_STATUS_404 || "index.html"
|
|
415
223
|
);
|
|
416
|
-
|
|
224
|
+
logger.debug(
|
|
417
225
|
"\x1b[32mserving file for status 404\x1b[0m",
|
|
418
226
|
filePath,
|
|
419
227
|
url
|
|
@@ -476,19 +284,19 @@ async function initiatePlaywrightRoutes(
|
|
|
476
284
|
".php": "application/x-httpd-php",
|
|
477
285
|
}[ext] || "application/octet-stream";
|
|
478
286
|
|
|
479
|
-
|
|
287
|
+
logger.info("\x1b[32mserving file\x1b[0m", filePath);
|
|
480
288
|
await route.fulfill({
|
|
481
289
|
body: fileContent,
|
|
482
290
|
headers: { "Content-Type": contentType },
|
|
483
291
|
});
|
|
484
292
|
} else {
|
|
485
|
-
|
|
293
|
+
logger.debug("\x1b[31mmissing mock data, falling back\x1b[0m", url);
|
|
486
294
|
await route.fallback();
|
|
487
295
|
}
|
|
488
296
|
}
|
|
489
297
|
} catch (e) {
|
|
490
|
-
|
|
491
|
-
|
|
298
|
+
logger.error(e);
|
|
299
|
+
logger.error(
|
|
492
300
|
"\x1b[31merror at initiatePlaywrightRoutes\x1b[0m",
|
|
493
301
|
url,
|
|
494
302
|
options
|
|
@@ -688,15 +496,6 @@ const deleteAllSnaps = async (ftmocksConifg, testName) => {
|
|
|
688
496
|
fs.rmSync(snapFolder, { recursive: true, force: true });
|
|
689
497
|
};
|
|
690
498
|
|
|
691
|
-
const deleteAllLogs = async (ftmocksConifg, testName) => {
|
|
692
|
-
const mockDir = path.join(
|
|
693
|
-
getMockDir(ftmocksConifg),
|
|
694
|
-
`test_${nameToFolder(testName)}`
|
|
695
|
-
);
|
|
696
|
-
const logFilePath = path.join(mockDir, `_logs.json`);
|
|
697
|
-
fs.rmSync(logFilePath, { recursive: true, force: true });
|
|
698
|
-
};
|
|
699
|
-
|
|
700
499
|
function initiateJestEventSnaps(jest, ftmocksConifg, testName) {
|
|
701
500
|
const mouseEvents = ftmocksConifg.snapEvents || [
|
|
702
501
|
"click",
|
|
@@ -716,95 +515,6 @@ function initiateJestEventSnaps(jest, ftmocksConifg, testName) {
|
|
|
716
515
|
});
|
|
717
516
|
}
|
|
718
517
|
|
|
719
|
-
const createTest = async (ftmocksConifg, testName) => {
|
|
720
|
-
const testsPath = path.join(getMockDir(ftmocksConifg), "tests.json");
|
|
721
|
-
let tests = [];
|
|
722
|
-
try {
|
|
723
|
-
// Read existing tests
|
|
724
|
-
const testsData = fs.readFileSync(testsPath, "utf8");
|
|
725
|
-
tests = JSON.parse(testsData);
|
|
726
|
-
const etest = tests.find((tst) => tst.name === testName);
|
|
727
|
-
if (!etest) {
|
|
728
|
-
const newTest = {
|
|
729
|
-
id: uuidv4(),
|
|
730
|
-
name: testName,
|
|
731
|
-
};
|
|
732
|
-
tests.push(newTest);
|
|
733
|
-
fs.writeFileSync(testsPath, JSON.stringify(tests, null, 2));
|
|
734
|
-
const folderPath = path.join(
|
|
735
|
-
getMockDir(ftmocksConifg),
|
|
736
|
-
`test_${nameToFolder(testName)}`
|
|
737
|
-
);
|
|
738
|
-
const mockListFilePath = path.join(folderPath, "_mock_list.json");
|
|
739
|
-
fs.mkdir(folderPath, { recursive: true }, (err) => {
|
|
740
|
-
if (err) {
|
|
741
|
-
console.error("\x1b[31mError creating directory:\x1b[0m", err);
|
|
742
|
-
} else {
|
|
743
|
-
console.log("\x1b[32mDirectory created successfully!\x1b[0m");
|
|
744
|
-
}
|
|
745
|
-
});
|
|
746
|
-
await fs.appendFile(mockListFilePath, "[]", () => {
|
|
747
|
-
console.log("\x1b[32mmock list file created successfully\x1b[0m");
|
|
748
|
-
});
|
|
749
|
-
|
|
750
|
-
return newTest;
|
|
751
|
-
} else {
|
|
752
|
-
throw "Test already exists";
|
|
753
|
-
}
|
|
754
|
-
} catch (error) {
|
|
755
|
-
console.error(`\x1b[31mError reading tests.json:\x1b[0m`, error);
|
|
756
|
-
return null;
|
|
757
|
-
}
|
|
758
|
-
};
|
|
759
|
-
|
|
760
|
-
const isSameResponse = (req1, req2) => {
|
|
761
|
-
try {
|
|
762
|
-
let matched = true;
|
|
763
|
-
if (req1.response.status !== req2.response.status) {
|
|
764
|
-
matched = false;
|
|
765
|
-
// console.log('not matched at url', req1.method, req2.method);
|
|
766
|
-
} else if (
|
|
767
|
-
(!req1.response.content && req2.response.content) ||
|
|
768
|
-
(req1.response.content && !req2.response.content)
|
|
769
|
-
) {
|
|
770
|
-
matched = FtJSON.areJsonEqual(
|
|
771
|
-
FtJSON.parse(req1.response.content) || {},
|
|
772
|
-
FtJSON.parse(req2.response.content) || {}
|
|
773
|
-
);
|
|
774
|
-
// console.log('not matched at post Data 0', req1.postData, req2.postData);
|
|
775
|
-
} else if (
|
|
776
|
-
req1.response.content &&
|
|
777
|
-
req2.response.content &&
|
|
778
|
-
!FtJSON.areJsonEqual(
|
|
779
|
-
FtJSON.parse(req1.response.content) || {},
|
|
780
|
-
FtJSON.parse(req2.response.content) || {}
|
|
781
|
-
)
|
|
782
|
-
) {
|
|
783
|
-
matched = false;
|
|
784
|
-
}
|
|
785
|
-
// if (matched) {
|
|
786
|
-
// console.log('matched responses', req1, req2);
|
|
787
|
-
// }
|
|
788
|
-
return matched;
|
|
789
|
-
} catch (error) {
|
|
790
|
-
console.error(error);
|
|
791
|
-
return false;
|
|
792
|
-
}
|
|
793
|
-
};
|
|
794
|
-
|
|
795
|
-
const compareMockToMock = (mock1, mock2, matchResponse) => {
|
|
796
|
-
try {
|
|
797
|
-
if (matchResponse) {
|
|
798
|
-
return isSameRequest(mock1, mock2) && isSameResponse(mock1, mock2);
|
|
799
|
-
} else {
|
|
800
|
-
return isSameRequest(mock1, mock2);
|
|
801
|
-
}
|
|
802
|
-
} catch (error) {
|
|
803
|
-
console.error(error);
|
|
804
|
-
return false;
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
|
|
808
518
|
const saveIfItIsFile = async (route, testName, ftmocksConifg) => {
|
|
809
519
|
const urlObj = new URL(route.request().url());
|
|
810
520
|
|
package/src/log-utils.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { getMockDir, nameToFolder } = require("./common-utils");
|
|
4
|
+
|
|
5
|
+
class Logger {
|
|
6
|
+
constructor(options = {}, ftmocksConifg, testName) {
|
|
7
|
+
this.levels = ["error", "warn", "info", "debug"];
|
|
8
|
+
this.level = options.level || "info";
|
|
9
|
+
this.disableLogs = options.disableLogs || false;
|
|
10
|
+
this.logsFile = path.join(
|
|
11
|
+
getMockDir(ftmocksConifg),
|
|
12
|
+
`test_${nameToFolder(testName)}`,
|
|
13
|
+
"_logs.json"
|
|
14
|
+
);
|
|
15
|
+
this.logs = [];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setLevel(level) {
|
|
19
|
+
if (this.levels.includes(level)) {
|
|
20
|
+
this.level = level;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
writeToFile(type, params) {
|
|
25
|
+
try {
|
|
26
|
+
const logMessage = params.join(" ") + "\n"; // Combine params into a string with spaces
|
|
27
|
+
this.logs.push({
|
|
28
|
+
type,
|
|
29
|
+
message: logMessage,
|
|
30
|
+
time: Date.now(),
|
|
31
|
+
source: "ftmocks-utils",
|
|
32
|
+
});
|
|
33
|
+
fs.writeFileSync(
|
|
34
|
+
this.logsFile,
|
|
35
|
+
JSON.stringify(this.logs, null, 2),
|
|
36
|
+
"utf8"
|
|
37
|
+
); // Append the log message to the file
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// Ignore error
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
log(level, ...args) {
|
|
44
|
+
if (this.disableLogs) return;
|
|
45
|
+
const levelIdx = this.levels.indexOf(level);
|
|
46
|
+
const currentLevelIdx = this.levels.indexOf(this.level);
|
|
47
|
+
if (levelIdx <= currentLevelIdx) {
|
|
48
|
+
const color = this._getColor(level);
|
|
49
|
+
const prefix = `[${level.toUpperCase()}]`;
|
|
50
|
+
if (typeof args[0] === "string") {
|
|
51
|
+
// Color only the prefix
|
|
52
|
+
console.log(`${color}${prefix}\x1b[0m`, ...args);
|
|
53
|
+
} else {
|
|
54
|
+
// Non-string first arg, just print
|
|
55
|
+
console.log(`${color}${prefix}\x1b[0m`, ...args);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.writeToFile(level, args);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
error(...args) {
|
|
62
|
+
this.log("error", ...args);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
warn(...args) {
|
|
66
|
+
this.log("warn", ...args);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
info(...args) {
|
|
70
|
+
this.log("info", ...args);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
debug(...args) {
|
|
74
|
+
this.log("debug", ...args);
|
|
75
|
+
console.debug(...args);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_getColor(level) {
|
|
79
|
+
switch (level) {
|
|
80
|
+
case "error":
|
|
81
|
+
return "\x1b[31m"; // Red
|
|
82
|
+
case "warn":
|
|
83
|
+
return "\x1b[33m"; // Yellow
|
|
84
|
+
case "info":
|
|
85
|
+
return "\x1b[36m"; // Cyan
|
|
86
|
+
case "debug":
|
|
87
|
+
return "\x1b[90m"; // Gray
|
|
88
|
+
default:
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const deleteAllLogs = async (ftmocksConifg, testName) => {
|
|
95
|
+
const mockDir = path.join(
|
|
96
|
+
getMockDir(ftmocksConifg),
|
|
97
|
+
`test_${nameToFolder(testName)}`
|
|
98
|
+
);
|
|
99
|
+
const logFilePath = path.join(mockDir, `_logs.json`);
|
|
100
|
+
fs.rmSync(logFilePath, { recursive: true, force: true });
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
module.exports = { Logger, deleteAllLogs };
|