@amanat-qa/utils-backend 1.0.8
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 +37 -0
- package/src/api/baseAPI.js +72 -0
- package/src/data/JSONLoader.js +8 -0
- package/src/data/JSONMapper.js +214 -0
- package/src/data/dataUtils.js +398 -0
- package/src/data/filesParser.js +104 -0
- package/src/data/gitlabCIGenerator.js +50 -0
- package/src/db/baseDB.js +59 -0
- package/src/index.js +13 -0
- package/src/log/logger.js +57 -0
- package/src/random/randomizer.js +83 -0
- package/src/time/timeUtils.js +58 -0
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amanat-qa/utils-backend",
|
|
3
|
+
"version": "1.0.8",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"files": [
|
|
9
|
+
"src"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.js",
|
|
15
|
+
"./baseAPI": "./src/api/baseAPI.js",
|
|
16
|
+
"./JSONLoader": "./src/data/JSONLoader.js",
|
|
17
|
+
"./JSONMapper": "./src/data/JSONMapper.js",
|
|
18
|
+
"./dataUtils": "./src/data/dataUtils.js",
|
|
19
|
+
"./filesParser": "./src/data/filesParser.js",
|
|
20
|
+
"./gitlabCIGenerator": "./src/data/gitlabCIGenerator.js",
|
|
21
|
+
"./baseDB": "./src/db/baseDB.js",
|
|
22
|
+
"./index": "./src/index.js",
|
|
23
|
+
"./logger": "./src/log/logger.js",
|
|
24
|
+
"./randomizer": "./src/random/randomizer.js",
|
|
25
|
+
"./timeUtils": "./src/time/timeUtils.js"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"axios": "*",
|
|
29
|
+
"fs": "*",
|
|
30
|
+
"moment": "*",
|
|
31
|
+
"path": "*",
|
|
32
|
+
"dotenv": "*",
|
|
33
|
+
"js-yaml": "*",
|
|
34
|
+
"mysql2": "*",
|
|
35
|
+
"allure-mocha": "*"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const Logger = require('../log/logger');
|
|
3
|
+
|
|
4
|
+
class BaseAPI {
|
|
5
|
+
#baseURL;
|
|
6
|
+
|
|
7
|
+
#logString;
|
|
8
|
+
|
|
9
|
+
#timeout;
|
|
10
|
+
|
|
11
|
+
#headers;
|
|
12
|
+
|
|
13
|
+
#axiosInstance;
|
|
14
|
+
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.#baseURL = options.baseURL;
|
|
17
|
+
this.#logString = options.logString;
|
|
18
|
+
this.#timeout = options.timeout;
|
|
19
|
+
this.#headers = options.headers;
|
|
20
|
+
this.#axiosInstance = this.createInstance();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
createInstance() {
|
|
24
|
+
if (this.#logString) Logger.log(`${this.#logString} ${this.#baseURL}`);
|
|
25
|
+
return axios.create({
|
|
26
|
+
baseURL: this.#baseURL,
|
|
27
|
+
timeout: this.#timeout,
|
|
28
|
+
headers: this.#headers,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async get(endpoint, params) {
|
|
33
|
+
Logger.log(`[req] ▶ get ${JSON.stringify(params || {})} from ${endpoint}:`);
|
|
34
|
+
try {
|
|
35
|
+
const response = await this.#axiosInstance.get(`/${endpoint}`, { params });
|
|
36
|
+
Logger.log(`[res] status code: ${response.status}`);
|
|
37
|
+
return response;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
Logger.log(`[res] status code: ${error.response.status}`);
|
|
40
|
+
Logger.log(`[res] body: ${JSON.stringify(error.response.data)}`);
|
|
41
|
+
return error.response;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async post(endpoint, params) {
|
|
46
|
+
Logger.log(`[req] ▶ post ${JSON.stringify(params || {})} to ${endpoint}:`);
|
|
47
|
+
try {
|
|
48
|
+
const response = await this.#axiosInstance.post(`/${endpoint}`, params);
|
|
49
|
+
Logger.log(`[res] status code: ${response.status}`);
|
|
50
|
+
return response;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
Logger.log(`[res] status code: ${error.response.status}`);
|
|
53
|
+
Logger.log(`[res] body: ${JSON.stringify(error.response.data)}`);
|
|
54
|
+
return error.response;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async patch(endpoint, params) {
|
|
59
|
+
Logger.log(`[req] ▶ patch ${JSON.stringify(params || {})} to ${endpoint}:`);
|
|
60
|
+
try {
|
|
61
|
+
const response = await this.#axiosInstance.patch(`/${endpoint}`, params);
|
|
62
|
+
Logger.log(`[res] status code: ${response.status}`);
|
|
63
|
+
return response;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
Logger.log(`[res] status code: ${error.response.status}`);
|
|
66
|
+
Logger.log(`[res] body: ${JSON.stringify(error.response.data)}`);
|
|
67
|
+
return error.response;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = BaseAPI;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/* eslint no-restricted-syntax: ['off', 'ForInStatement'] */
|
|
2
|
+
const Logger = require('../log/logger');
|
|
3
|
+
|
|
4
|
+
class JSONMapper {
|
|
5
|
+
static getNestedProperty(flattenedObj, path) {
|
|
6
|
+
const keys = [];
|
|
7
|
+
const values = [];
|
|
8
|
+
for (const key in flattenedObj) {
|
|
9
|
+
if (Object.hasOwn(flattenedObj, key)) {
|
|
10
|
+
if (key.endsWith(`.${path}`) || key === path) {
|
|
11
|
+
keys.push(key);
|
|
12
|
+
values.push(flattenedObj[key]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return { keys, values };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static deleteNotSimilarProperty(flattenedObj, mappingSchema) {
|
|
21
|
+
const keysToDelete = [];
|
|
22
|
+
const outputObj = { ...flattenedObj };
|
|
23
|
+
for (const key in outputObj) {
|
|
24
|
+
if (Object.hasOwn(outputObj, key)) {
|
|
25
|
+
let shouldDelete = true;
|
|
26
|
+
for (const path in mappingSchema) {
|
|
27
|
+
if (Object.hasOwn(mappingSchema, path)) {
|
|
28
|
+
if (key.endsWith(`.${path}`) || key === path) {
|
|
29
|
+
shouldDelete = false;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (shouldDelete) keysToDelete.push(key);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
keysToDelete.forEach((key) => delete outputObj[key]);
|
|
40
|
+
return outputObj;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static flattenJSON(obj) {
|
|
44
|
+
const result = {};
|
|
45
|
+
const recursive = (currentObj, prefix = '') => {
|
|
46
|
+
for (const objKey in currentObj) {
|
|
47
|
+
if (Object.hasOwn(currentObj, objKey)) {
|
|
48
|
+
const fullKey = prefix ? `${prefix}.${objKey}` : objKey;
|
|
49
|
+
if (typeof currentObj[objKey] === 'object') {
|
|
50
|
+
recursive(currentObj[objKey], fullKey);
|
|
51
|
+
} else {
|
|
52
|
+
result[fullKey] = currentObj[objKey];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
recursive(obj);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static mapValues(firstData, secondData, mappingSchema) {
|
|
63
|
+
const [firstName] = Object.keys(firstData);
|
|
64
|
+
const firstObj = firstData[firstName];
|
|
65
|
+
const [secondName] = Object.keys(secondData);
|
|
66
|
+
const secondObj = secondData[secondName];
|
|
67
|
+
const firstFlattenedObj = this.flattenJSON(firstObj);
|
|
68
|
+
const secondFlattenedObj = this.flattenJSON(secondObj);
|
|
69
|
+
const firstFlattenedObjKeys = Object.keys(firstFlattenedObj);
|
|
70
|
+
const secondFlattenedObjKeys = Object.keys(secondFlattenedObj);
|
|
71
|
+
for (const path in mappingSchema) {
|
|
72
|
+
if (Object.hasOwn(mappingSchema, path)) {
|
|
73
|
+
if (firstFlattenedObjKeys.some((key) => key.endsWith(path))) {
|
|
74
|
+
if (secondFlattenedObjKeys.some((key) => key.endsWith(mappingSchema[path]))) {
|
|
75
|
+
let index = 0;
|
|
76
|
+
for (const key in firstFlattenedObj) {
|
|
77
|
+
if (Object.hasOwn(firstFlattenedObj, key)) {
|
|
78
|
+
if (this.getNestedProperty(firstFlattenedObj, path).keys.includes(key)) {
|
|
79
|
+
const valuesArr = this.getNestedProperty(secondFlattenedObj, mappingSchema[path])
|
|
80
|
+
.values;
|
|
81
|
+
firstFlattenedObj[key] = index >= valuesArr.length
|
|
82
|
+
? valuesArr[valuesArr.length - 1]
|
|
83
|
+
: valuesArr[index];
|
|
84
|
+
index += 1;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
throw new Error(Logger.log(`[err] mapping key "${mappingSchema[path]}" wasn't found in ${secondName}`));
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
throw new Error(Logger.log(`[err] mapping key "${path}" wasn't found in ${firstName}`));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return this.deleteNotSimilarProperty(firstFlattenedObj, mappingSchema);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static rewriteValues(mappedObj, firstDict, secondDict) {
|
|
101
|
+
const firstDictKeys = Object.keys(firstDict);
|
|
102
|
+
const secondDictKeys = Object.keys(secondDict);
|
|
103
|
+
const outputObj = { ...mappedObj };
|
|
104
|
+
for (const key in outputObj) {
|
|
105
|
+
if (Object.hasOwn(outputObj, key)) {
|
|
106
|
+
if (firstDictKeys.some((path) => this.getNestedProperty(outputObj, path)
|
|
107
|
+
.keys.includes(key))
|
|
108
|
+
&& secondDictKeys.some((path) => this.getNestedProperty(outputObj, path)
|
|
109
|
+
.keys.includes(key))) {
|
|
110
|
+
secondDictKeys.forEach((dictKey) => {
|
|
111
|
+
if (this.getNestedProperty(outputObj, dictKey).keys.includes(key)) {
|
|
112
|
+
for (const dictSubKey in secondDict[dictKey]) {
|
|
113
|
+
if (Object.hasOwn(secondDict[dictKey], dictSubKey)) {
|
|
114
|
+
if (secondDict[dictKey][dictSubKey] === outputObj[key] || dictSubKey === 'constant') {
|
|
115
|
+
outputObj[key] = firstDict[dictKey][dictSubKey];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return outputObj;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static unflattenJSON(flattenedObj) {
|
|
129
|
+
const result = {};
|
|
130
|
+
for (const key in flattenedObj) {
|
|
131
|
+
if (Object.hasOwn(flattenedObj, key)) {
|
|
132
|
+
const keys = key.split('.');
|
|
133
|
+
let currentLevel = result;
|
|
134
|
+
for (let i = 0; i < keys.length - 1; i += 1) {
|
|
135
|
+
const currentKey = keys[i];
|
|
136
|
+
const nextKeyIsArrayIndex = /^\d+$/.test(keys[i + 1]);
|
|
137
|
+
if (!currentLevel[currentKey] || typeof currentLevel[currentKey] !== 'object') {
|
|
138
|
+
currentLevel[currentKey] = nextKeyIsArrayIndex ? [] : {};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
currentLevel = currentLevel[currentKey];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
currentLevel[keys[keys.length - 1]] = flattenedObj[key];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static safeMergeObjects(...mappedObjects) {
|
|
152
|
+
const result = {};
|
|
153
|
+
const locations = {};
|
|
154
|
+
mappedObjects.forEach((mappedObj) => {
|
|
155
|
+
const [currentLocation] = Object.keys(mappedObj);
|
|
156
|
+
const data = mappedObj[currentLocation];
|
|
157
|
+
locations[currentLocation] = {};
|
|
158
|
+
for (const [key, value] of Object.entries(data)) {
|
|
159
|
+
if (key in result) {
|
|
160
|
+
if (result[key] !== value) {
|
|
161
|
+
for (const location in locations) {
|
|
162
|
+
if (Object.hasOwn(locations, location)) {
|
|
163
|
+
if (key in locations[location]) {
|
|
164
|
+
if (location[key] !== value) {
|
|
165
|
+
throw new Error(`[err] conflicting values for duplicated keys "${key}" found in the ${currentLocation} and in the ${location} during mapped objects merge`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
result[key] = value;
|
|
174
|
+
locations[currentLocation][key] = value;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static getObjectWithSpecifiedKeyFromArray(array, keyName) {
|
|
182
|
+
let result = null;
|
|
183
|
+
for (let i = 0; i < array.length; i += 1) {
|
|
184
|
+
if (this.hasKey(array[i], keyName)) result = array[i];
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static hasKey(obj, keyToFind) {
|
|
190
|
+
if (typeof obj !== 'object' || obj === null) return false;
|
|
191
|
+
|
|
192
|
+
for (const key in obj) {
|
|
193
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) { // Safeguard added
|
|
194
|
+
if (key === keyToFind) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
if (typeof obj[key] === 'object' && this.hasKey(obj[key], keyToFind)) {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
static appendPrefixToKeys(obj, prefix) {
|
|
206
|
+
const newObj = {};
|
|
207
|
+
Object.keys(obj).forEach((key) => {
|
|
208
|
+
newObj[prefix + key] = obj[key];
|
|
209
|
+
});
|
|
210
|
+
return newObj;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = JSONMapper;
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const moment = require('moment');
|
|
3
|
+
const JSONMapper = require('./JSONMapper');
|
|
4
|
+
const JSONLoader = require('./JSONLoader');
|
|
5
|
+
const TimeUtils = require('../time/timeUtils');
|
|
6
|
+
const Randomizer = require('../random/randomizer');
|
|
7
|
+
|
|
8
|
+
class DataUtils {
|
|
9
|
+
static saveToJSON(obj) {
|
|
10
|
+
const [name] = Object.keys(obj);
|
|
11
|
+
const data = obj[name];
|
|
12
|
+
const replacer = (key, value) => (typeof value === 'undefined' ? null : value);
|
|
13
|
+
fs.writeFileSync(`./test/artifacts/${name}.json`, JSON.stringify(data, replacer, 4));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static passBugsTWB(mappedData, getPolicyData) {
|
|
17
|
+
const outputData = { ...mappedData };
|
|
18
|
+
|
|
19
|
+
// Pass TWB bug with "doc_gived_by" value
|
|
20
|
+
const docGivedByFullKeys = JSONMapper.getNestedProperty(outputData, 'doc_gived_by').keys;
|
|
21
|
+
docGivedByFullKeys.forEach((fullKey) => {
|
|
22
|
+
if (JSONMapper.flattenJSON(getPolicyData)[fullKey] === 'МВД РК'
|
|
23
|
+
|| JSONMapper.flattenJSON(getPolicyData)[fullKey] === '-') {
|
|
24
|
+
outputData[fullKey] = JSONMapper.flattenJSON(getPolicyData)[fullKey];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Pass TWB bug with "driver_certificate_date" empty value
|
|
29
|
+
const driverCertificateDateFullKeys = JSONMapper
|
|
30
|
+
.getNestedProperty(outputData, 'driver_certificate_date').keys;
|
|
31
|
+
driverCertificateDateFullKeys.forEach((fullKey) => {
|
|
32
|
+
if (JSONMapper.flattenJSON(getPolicyData)[fullKey] === '') {
|
|
33
|
+
outputData[fullKey] = JSONMapper.flattenJSON(getPolicyData)[fullKey];
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Pass TWB bug with "verify_bool" value without verification
|
|
38
|
+
if (getPolicyData.contracts[0].verify_bool === 1
|
|
39
|
+
&& outputData['contracts.0.verify_bool'] === 0) {
|
|
40
|
+
outputData['contracts.0.verify_bool'] = getPolicyData.contracts[0].verify_bool;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return outputData;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* eslint-disable no-param-reassign */
|
|
47
|
+
static mapRequestToOnes(onesData, requestData, isOGPO, optionalSchema) {
|
|
48
|
+
let onesDataFileName = 'onesDataCommon';
|
|
49
|
+
let requestToOnesMappedDataFileName = 'requestToOnesMappedDataCommon';
|
|
50
|
+
let mapSchema = JSONLoader.requestToOnesMapSchemaCommonKASKO;
|
|
51
|
+
|
|
52
|
+
if (isOGPO) {
|
|
53
|
+
mapSchema = JSONLoader.requestToOnesMapSchemaOGPO;
|
|
54
|
+
onesDataFileName = 'onesDataOGPO';
|
|
55
|
+
requestToOnesMappedDataFileName = 'requestToOnesMappedDataOGPO';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const mappedData = JSONMapper.mapValues(
|
|
59
|
+
{ onesData },
|
|
60
|
+
{ requestData },
|
|
61
|
+
optionalSchema ?? mapSchema,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const rewrittenData = JSONMapper.rewriteValues(
|
|
65
|
+
mappedData,
|
|
66
|
+
JSONLoader.dictOnes,
|
|
67
|
+
JSONLoader.dictRequest,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const requestToOnesMappedData = JSONMapper.unflattenJSON(rewrittenData);
|
|
71
|
+
requestToOnesMappedData.ie_date = TimeUtils.reformatDateFromDMYToYMDHms(rewrittenData.ie_date);
|
|
72
|
+
requestToOnesMappedData.claims.forEach((claim, index) => {
|
|
73
|
+
const rewrittenDateKey = `claims.${index}.notice_date`; // Build the dynamic key
|
|
74
|
+
claim.notice_date = TimeUtils.reformatDateFromDMYToYMDHms(rewrittenData[rewrittenDateKey]);
|
|
75
|
+
});
|
|
76
|
+
this.saveToJSON({ [onesDataFileName]: onesData });
|
|
77
|
+
this.saveToJSON({ [requestToOnesMappedDataFileName]: requestToOnesMappedData });
|
|
78
|
+
return requestToOnesMappedData;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static sortOGPORequestAndOnesData(requestData, onesData) {
|
|
82
|
+
/* This method sorts victim objects in requestData and claims in onesData for OGPO case
|
|
83
|
+
in preparation for mapping.
|
|
84
|
+
Order: 1st - Victim_Vehicle, 2nd - Victim_Client, 3rd - Victim_Other.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
const priority = JSONLoader.testData.victimObjectsSortPriority;
|
|
88
|
+
|
|
89
|
+
requestData.victim_objects.sort((a, b) => {
|
|
90
|
+
const typeA = a.type;
|
|
91
|
+
const typeB = b.type;
|
|
92
|
+
return (priority[typeA] || 999) - (priority[typeB] || 999);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
onesData.claims.sort((a, b) => {
|
|
96
|
+
const typeA = a.victim_objects[0].type;
|
|
97
|
+
const typeB = b.victim_objects[0].type;
|
|
98
|
+
return (priority[typeA] || 999) - (priority[typeB] || 999);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this.saveToJSON({ requestDataSorted: requestData });
|
|
102
|
+
this.saveToJSON({ onesDataSorted: onesData });
|
|
103
|
+
return { requestData, onesData };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static mapIEESBDToRequestOGPO(requestData, getIEESBDResponse) {
|
|
107
|
+
/* OGPO IE and victim object mapping is separated into 4 parts:
|
|
108
|
+
IE and each of 3 victim objects.
|
|
109
|
+
Victim objects are created asynchronically, so we can't rely on
|
|
110
|
+
their array order in request to map them with ESBD.
|
|
111
|
+
So we need to separate them and determine which victim object from
|
|
112
|
+
response is to be mapped with victim object in response.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
// Save input data into files.
|
|
116
|
+
this.saveToJSON({ requestDataOGPO: requestData });
|
|
117
|
+
this.saveToJSON({ getIEESBDResponseOGPO: getIEESBDResponse });
|
|
118
|
+
|
|
119
|
+
// Main part of mapping - ie from ESBD to request.
|
|
120
|
+
const IEMappedPart = JSONMapper.mapValues(
|
|
121
|
+
{ requestDataOGPO: requestData },
|
|
122
|
+
{ getIEESBDResponse },
|
|
123
|
+
JSONLoader.IEToRequestMapSchemaOGPO,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Form array of victim objects from request and esbd response.
|
|
127
|
+
const victimObjectsRequestArray = requestData.victim_objects;
|
|
128
|
+
const victimObjectsESBDArray = getIEESBDResponse
|
|
129
|
+
.GetInsuranceEventsResult.Insurance_Event.Victim_Objects.Victim_Object;
|
|
130
|
+
|
|
131
|
+
// Find victim objects in request and ESBD response and using unique keys.
|
|
132
|
+
const victimVehicleRequest = JSONMapper
|
|
133
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsRequestArray, 'TF_ID');
|
|
134
|
+
const victimVehicleESBD = JSONMapper
|
|
135
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsESBDArray, 'Victim_Vehicle');
|
|
136
|
+
let victimVehicleMappedPart = JSONMapper.mapValues(
|
|
137
|
+
{ victimVehicleRequest },
|
|
138
|
+
{ victimVehicleESBD },
|
|
139
|
+
JSONLoader.victimVehicleToRequestMapSchema,
|
|
140
|
+
);
|
|
141
|
+
victimVehicleMappedPart = JSONMapper.appendPrefixToKeys(victimVehicleMappedPart, 'victim_objects.0.');
|
|
142
|
+
|
|
143
|
+
const victimClientRequest = JSONMapper
|
|
144
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsRequestArray, 'DEATH_BOOL');
|
|
145
|
+
const victimClientESBD = JSONMapper
|
|
146
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsESBDArray, 'Victim_Client');
|
|
147
|
+
let victimClientMappedPart = JSONMapper.mapValues(
|
|
148
|
+
{ victimClientRequest },
|
|
149
|
+
{ victimClientESBD },
|
|
150
|
+
JSONLoader.victimClientToRequestMapSchema,
|
|
151
|
+
);
|
|
152
|
+
victimClientMappedPart = JSONMapper.appendPrefixToKeys(victimClientMappedPart, 'victim_objects.1.');
|
|
153
|
+
|
|
154
|
+
const victimOtherRequest = JSONMapper
|
|
155
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsRequestArray, 'VICTIM_OTHER_TYPE_ID');
|
|
156
|
+
const victimOtherESBD = JSONMapper
|
|
157
|
+
.getObjectWithSpecifiedKeyFromArray(victimObjectsESBDArray, 'Victim_Other');
|
|
158
|
+
let victimOtherMappedPart = JSONMapper.mapValues(
|
|
159
|
+
{ victimOtherRequest },
|
|
160
|
+
{ victimOtherESBD },
|
|
161
|
+
JSONLoader.victimOtherToRequestMapSchema,
|
|
162
|
+
);
|
|
163
|
+
victimOtherMappedPart = JSONMapper.appendPrefixToKeys(victimOtherMappedPart, 'victim_objects.2.');
|
|
164
|
+
|
|
165
|
+
// After mapping merge them together into single mapped object.
|
|
166
|
+
const mappingResult = JSONMapper.safeMergeObjects(
|
|
167
|
+
{ IEMappedPart },
|
|
168
|
+
{ victimVehicleMappedPart },
|
|
169
|
+
{ victimClientMappedPart },
|
|
170
|
+
{ victimOtherMappedPart },
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Save output data into files.
|
|
174
|
+
this.saveToJSON({ IEMappedPart });
|
|
175
|
+
this.saveToJSON({ victimVehicleMappedPart });
|
|
176
|
+
this.saveToJSON({ victimClientMappedPart });
|
|
177
|
+
this.saveToJSON({ victimOtherMappedPart });
|
|
178
|
+
|
|
179
|
+
const IEToRequestMappedData = JSONMapper.unflattenJSON(mappingResult);
|
|
180
|
+
this.saveToJSON({ OGPOMappingResult: mappingResult });
|
|
181
|
+
this.saveToJSON({ OGPOIEToRequestMappedData: IEToRequestMappedData });
|
|
182
|
+
|
|
183
|
+
return IEToRequestMappedData;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static mapClaimESBDToRequestOGPO(claimESBD) {
|
|
187
|
+
const mappedBody = JSONLoader.claimToRequestMapTemplateOGPO;
|
|
188
|
+
|
|
189
|
+
mappedBody.informer.id_esbd = claimESBD.CLAIMANT_ID;
|
|
190
|
+
mappedBody.victim_objects[0].pre_appraisal_damage = claimESBD.PRELIMINARY_DAMAGE_APPRAISAL;
|
|
191
|
+
mappedBody.claimant_type_id = claimESBD.CLAIMANT_TYPE_ID;
|
|
192
|
+
|
|
193
|
+
const claimESBDFileName = `claim_ESBD_${claimESBD.IE_CLAIM_ID}`;
|
|
194
|
+
const claimMappingResultFileName = `claim_mapped_ESBD_to_request_${claimESBD.IE_CLAIM_ID}`;
|
|
195
|
+
this.saveToJSON({ [claimMappingResultFileName]: mappedBody });
|
|
196
|
+
this.saveToJSON({ [claimESBDFileName]: claimESBD });
|
|
197
|
+
|
|
198
|
+
return mappedBody;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static mapESBDToRequestCommon(requestData, getIEESBDResponse) {
|
|
202
|
+
// Common IE, claim, victim objects are possible to get
|
|
203
|
+
// using single ESBD method to get common IE.
|
|
204
|
+
|
|
205
|
+
this.saveToJSON({ requestDataCommonKASKO: requestData });
|
|
206
|
+
this.saveToJSON({ getIEESBDResponseCommonKASKO: getIEESBDResponse });
|
|
207
|
+
|
|
208
|
+
const mappedData = JSONMapper.mapValues(
|
|
209
|
+
{ requestData },
|
|
210
|
+
{ getIEESBDResponse },
|
|
211
|
+
JSONLoader.IEToRequestMapSchemaCommon,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const IEToRequestMappedData = JSONMapper.unflattenJSON(mappedData);
|
|
215
|
+
|
|
216
|
+
// Calculating preliminary damage appraisal from ESBD average RBNS reserve value
|
|
217
|
+
const insuranceTypeID = requestData.victim_objects[0].insurance_type_id;
|
|
218
|
+
const averageRBNS = JSONLoader
|
|
219
|
+
.averageRBNS.filter((avgRBNS) => (
|
|
220
|
+
avgRBNS.insurance_type_id_esbd === insuranceTypeID
|
|
221
|
+
? avgRBNS.insurance_type_id_esbd
|
|
222
|
+
: null))[0];
|
|
223
|
+
let preliminaryDamageCalculated = getIEESBDResponse
|
|
224
|
+
.data.GetIECommon_By_IdResult.COMMON_CLAIMS.COMMON_CLAIM.PRELIMINARY_DAMAGE_APPRAISAL;
|
|
225
|
+
preliminaryDamageCalculated = Math
|
|
226
|
+
.round(preliminaryDamageCalculated / (1 + (averageRBNS.percent * 0.01)));
|
|
227
|
+
IEToRequestMappedData.victim_objects[0].pre_appraisal_damage = preliminaryDamageCalculated;
|
|
228
|
+
|
|
229
|
+
// Delete redundant mapped "descriptions".
|
|
230
|
+
delete IEToRequestMappedData.location.description;
|
|
231
|
+
delete IEToRequestMappedData.victim_objects[0].participants.client.description;
|
|
232
|
+
|
|
233
|
+
this.saveToJSON({ IEToRequestMappedDataCommon: IEToRequestMappedData });
|
|
234
|
+
|
|
235
|
+
return IEToRequestMappedData;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* eslint camelcase: ["error", {"properties": "never",
|
|
239
|
+
ignoreDestructuring: true, allow: ["verify_bool", "verify_type_id"]}] */
|
|
240
|
+
static generateSetPolicyRequest() {
|
|
241
|
+
const params = {};
|
|
242
|
+
const datesInterval = TimeUtils.getDatesInterval(...JSONLoader.testData.timeIncrement);
|
|
243
|
+
params.date_beg = datesInterval.startDate;
|
|
244
|
+
params.date_end = datesInterval.finishDate;
|
|
245
|
+
|
|
246
|
+
const { testClients } = JSONLoader;
|
|
247
|
+
const { testCars } = JSONLoader;
|
|
248
|
+
|
|
249
|
+
const { holder, insured } = DataUtils.createRandomHolderAndInsuredStructures(testClients);
|
|
250
|
+
const car = DataUtils.createRandomCarStructure(testCars);
|
|
251
|
+
|
|
252
|
+
params.insured_people = [];
|
|
253
|
+
params.insured_people[0] = insured;
|
|
254
|
+
params.holder = holder;
|
|
255
|
+
params.vehicles = [];
|
|
256
|
+
params.vehicles[0] = car;
|
|
257
|
+
|
|
258
|
+
return params;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static filterClients(clients, options = {}) {
|
|
262
|
+
const { isResident } = options;
|
|
263
|
+
const { hasPassport } = options;
|
|
264
|
+
const { hasDriverLicence } = options;
|
|
265
|
+
const { isUnderSixtyYearsOld } = options;
|
|
266
|
+
let filteredClients = [...clients];
|
|
267
|
+
|
|
268
|
+
filteredClients = filteredClients.filter((client) => {
|
|
269
|
+
if (isResident !== undefined) {
|
|
270
|
+
return isResident ? client.resident_bool : !client.resident_bool;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return true;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
filteredClients = filteredClients.filter((client) => {
|
|
277
|
+
if (hasDriverLicence !== undefined) {
|
|
278
|
+
return hasDriverLicence ? client.driving_license : !client.driving_license;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return true;
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
filteredClients = filteredClients.filter((client) => {
|
|
285
|
+
if (hasPassport !== undefined) {
|
|
286
|
+
return hasPassport ? client.document_type_id === 2 : client.document_type_id !== 2;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return true;
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
filteredClients = filteredClients.filter((client) => {
|
|
293
|
+
if (isUnderSixtyYearsOld !== undefined) {
|
|
294
|
+
return isUnderSixtyYearsOld
|
|
295
|
+
? moment(client.born) > moment().subtract(60, 'years')
|
|
296
|
+
: moment(client.born) <= moment().subtract(60, 'years');
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return true;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return filteredClients;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* eslint-disable camelcase */
|
|
306
|
+
static createRandomHolderAndInsuredStructures(clientsArr) {
|
|
307
|
+
const randomHolderIndex = Randomizer.getRandomInteger(clientsArr.length - 1);
|
|
308
|
+
let randomInsuredIndex;
|
|
309
|
+
do {
|
|
310
|
+
randomInsuredIndex = Randomizer.getRandomInteger(clientsArr.length - 1);
|
|
311
|
+
} while (randomInsuredIndex === randomHolderIndex);
|
|
312
|
+
const tempHolder = clientsArr[randomHolderIndex];
|
|
313
|
+
const tempInsured = clientsArr[randomInsuredIndex];
|
|
314
|
+
const resultHolder = { ...tempHolder };
|
|
315
|
+
const resultInsured = { ...tempInsured };
|
|
316
|
+
|
|
317
|
+
const verify_bool = Number(JSONLoader.configData.verification);
|
|
318
|
+
const verify_type_id = Number(JSONLoader.configData.verification) || 3;
|
|
319
|
+
const pdl = Randomizer.getRandomInteger(1);
|
|
320
|
+
|
|
321
|
+
resultInsured.pdl = pdl;
|
|
322
|
+
resultInsured.verify_bool = verify_bool;
|
|
323
|
+
resultInsured.verify_type_id = verify_type_id;
|
|
324
|
+
|
|
325
|
+
resultInsured.esbd_id = tempInsured.client_id;
|
|
326
|
+
resultInsured.driver_certificate = tempInsured.driving_license;
|
|
327
|
+
|
|
328
|
+
resultInsured.born = TimeUtils.reformatDateFromYMDToDMY(tempInsured.born);
|
|
329
|
+
resultInsured.document_gived_date = TimeUtils
|
|
330
|
+
.reformatDateFromYMDToDMY(tempInsured.document_gived_date);
|
|
331
|
+
resultInsured.driver_certificate_date = TimeUtils
|
|
332
|
+
.reformatDateFromYMDToDMY(tempInsured.date_issue_license);
|
|
333
|
+
|
|
334
|
+
resultInsured.iin = tempInsured.iin.toString();
|
|
335
|
+
|
|
336
|
+
resultInsured.natural_person_bool = JSONLoader.testData.natural_person_bool;
|
|
337
|
+
resultInsured.economics_sector_id = JSONLoader.testData.economics_sector_id;
|
|
338
|
+
resultInsured.notification_type_id = JSONLoader.testData.notification_type_id;
|
|
339
|
+
resultInsured.driver_certificate_type_id = JSONLoader.testData.driver_certificate_type_id;
|
|
340
|
+
resultInsured.experience_less = JSONLoader.testData.experience_less;
|
|
341
|
+
resultInsured.pensioner_bool = JSONLoader.testData.pensioner_bool;
|
|
342
|
+
resultInsured.country_id = JSONLoader.testData.country_id;
|
|
343
|
+
resultInsured.is_new = JSONLoader.testData.is_new;
|
|
344
|
+
resultInsured.class_id = JSONLoader.testData.class_id;
|
|
345
|
+
resultInsured.class = JSONLoader.testData.class;
|
|
346
|
+
resultInsured.document_gived_by = JSONLoader.testData.insured_document_gived_by;
|
|
347
|
+
resultInsured.email = JSONLoader.testData.insured_email;
|
|
348
|
+
resultInsured.mobile_phone = JSONLoader.testData.insured_mobile_phone;
|
|
349
|
+
resultInsured.address = JSONLoader.testData.insured_address;
|
|
350
|
+
resultInsured.is_insured = 1;
|
|
351
|
+
|
|
352
|
+
resultHolder.pdl = pdl;
|
|
353
|
+
resultHolder.verify_bool = verify_bool;
|
|
354
|
+
resultHolder.verify_type_id = verify_type_id;
|
|
355
|
+
|
|
356
|
+
resultHolder.esbd_id = tempHolder.client_id;
|
|
357
|
+
resultHolder.driver_certificate = tempHolder.driving_license;
|
|
358
|
+
|
|
359
|
+
resultHolder.born = TimeUtils.reformatDateFromYMDToDMY(tempHolder.born);
|
|
360
|
+
resultHolder.document_gived_date = TimeUtils
|
|
361
|
+
.reformatDateFromYMDToDMY(tempHolder.document_gived_date);
|
|
362
|
+
resultHolder.driver_certificate_date = TimeUtils
|
|
363
|
+
.reformatDateFromYMDToDMY(tempHolder.date_issue_license);
|
|
364
|
+
|
|
365
|
+
resultHolder.iin = tempHolder.iin.toString();
|
|
366
|
+
|
|
367
|
+
resultHolder.natural_person_bool = JSONLoader.testData.natural_person_bool;
|
|
368
|
+
resultHolder.economics_sector_id = JSONLoader.testData.economics_sector_id;
|
|
369
|
+
resultHolder.notification_type_id = JSONLoader.testData.notification_type_id;
|
|
370
|
+
resultHolder.driver_certificate_type_id = JSONLoader.testData.driver_certificate_type_id;
|
|
371
|
+
resultHolder.experience_less = JSONLoader.testData.experience_less;
|
|
372
|
+
resultHolder.pensioner_bool = JSONLoader.testData.pensioner_bool;
|
|
373
|
+
resultHolder.country_id = JSONLoader.testData.country_id;
|
|
374
|
+
resultHolder.is_new = JSONLoader.testData.is_new;
|
|
375
|
+
resultHolder.activity_kind_id = JSONLoader.testData.activity_kind_id;
|
|
376
|
+
resultHolder.document_gived_by = JSONLoader.testData.holder_document_gived_by;
|
|
377
|
+
resultHolder.email = JSONLoader.testData.holder_email;
|
|
378
|
+
resultHolder.mobile_phone = JSONLoader.testData.holder_mobile_phone;
|
|
379
|
+
resultHolder.address = JSONLoader.testData.holder_address;
|
|
380
|
+
resultHolder.is_insured = 0;
|
|
381
|
+
|
|
382
|
+
return { holder: resultHolder, insured: resultInsured };
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static createRandomCarStructure(carsArr) {
|
|
386
|
+
const randomCarIndex = Randomizer.getRandomInteger(carsArr.length - 1);
|
|
387
|
+
const tempCar = carsArr[randomCarIndex];
|
|
388
|
+
const resultCar = { ...tempCar };
|
|
389
|
+
|
|
390
|
+
resultCar.esbd_id = tempCar.tf_id;
|
|
391
|
+
resultCar.dt_reg_cert = TimeUtils.reformatDateFromYMDToDMY(tempCar.dt_reg_cert);
|
|
392
|
+
resultCar.verified_bool = 1;
|
|
393
|
+
|
|
394
|
+
return resultCar;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
module.exports = DataUtils;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
require('dotenv').config({ path: path.join(__dirname, '../../../../../', '.env.test'), override: true });
|
|
4
|
+
|
|
5
|
+
const envDirectory = path.join(__dirname, '../../../../../');
|
|
6
|
+
const loaderFileLocation = path.join(__dirname, 'JSONLoader.js');
|
|
7
|
+
const testClientsFileLocation = path.join(envDirectory, './test/resources/data/testClients.json');
|
|
8
|
+
const testCarsFileLocation = path.join(envDirectory, './test/resources/data/testCars.json');
|
|
9
|
+
const averageRBNSFileLocation = path.join(envDirectory, './test/resources/data/averageRBNS.json');
|
|
10
|
+
const JSONDirectory = path.join(envDirectory, './test/resources');
|
|
11
|
+
|
|
12
|
+
const getFiles = (directory, extension) => {
|
|
13
|
+
const allFiles = fs.readdirSync(directory);
|
|
14
|
+
const selectedFiles = allFiles.filter((file) => file.endsWith(extension));
|
|
15
|
+
allFiles.forEach((file) => {
|
|
16
|
+
const fullPath = path.join(directory, file);
|
|
17
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
18
|
+
const nestedFiles = getFiles(fullPath, extension);
|
|
19
|
+
selectedFiles.push(...nestedFiles.map((nestedFile) => path.join(file, nestedFile)));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return selectedFiles;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const generateClassInit = (selectedFiles, directory) => `class JSONLoader {\n${selectedFiles.map((file) => {
|
|
27
|
+
const variableName = path.parse(file).name;
|
|
28
|
+
return `\tstatic get ${variableName}() {\n\t\tconst ${variableName} = require('${path.join(directory, file)}');\n\t\treturn JSON.parse(JSON.stringify(${variableName}));\n\t}\n\n`;
|
|
29
|
+
}).join('')}`;
|
|
30
|
+
|
|
31
|
+
const generateJSONLoader = (filePath, directory, extension) => {
|
|
32
|
+
const files = getFiles(directory, extension);
|
|
33
|
+
const classInit = generateClassInit(files, directory);
|
|
34
|
+
const classExport = '}\n\nmodule.exports = JSONLoader;';
|
|
35
|
+
fs.writeFileSync(filePath, classInit + classExport);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const setConfigData = (directory, extension) => {
|
|
39
|
+
const files = getFiles(directory, extension);
|
|
40
|
+
const configFile = files.filter((file) => file.includes('config')).pop();
|
|
41
|
+
if (configFile) {
|
|
42
|
+
const filePath = `${directory}/${configFile}`;
|
|
43
|
+
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
44
|
+
data.parallel = process.argv.includes('--parallel');
|
|
45
|
+
data.setPolicyWaitingTWB = process.argv.includes('--setPolicyWaitingTWB');
|
|
46
|
+
data.testOGPOClaim = process.argv.includes('--testOGPOClaim');
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
data.verification = Boolean(JSON.parse(process.env.VERIFICATION ?? data.verification));
|
|
50
|
+
} catch (error) { // eslint-disable-next-line no-console
|
|
51
|
+
console.log(' [err] incorrect value of "VERIFICATION" .env variable!');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const value = JSON.parse(process.env.SET_POLICY_WAITING_TWB ?? data.setPolicyWaitingTWB);
|
|
56
|
+
data.setPolicyWaitingTWB = Boolean(value);
|
|
57
|
+
} catch (error) { // eslint-disable-next-line no-console
|
|
58
|
+
console.log(' [err] incorrect value of "SET_POLICY_WAITING_TWB" .env variable!');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
data.getPolicyTWB = Boolean(JSON.parse(process.env.GET_POLICY_TWB ?? data.getPolicyTWB));
|
|
63
|
+
} catch (error) { // eslint-disable-next-line no-console
|
|
64
|
+
console.log(' [err] incorrect value of "GET_POLICY_TWB" .env variable!');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (process.env.GATEWAY_URL) {
|
|
68
|
+
const value = process.env.GATEWAY_URL.match(/\b(?:localhost|dev|staging)\b/g);
|
|
69
|
+
if (value) {
|
|
70
|
+
data.environment = value.pop();
|
|
71
|
+
} else { // eslint-disable-next-line no-console
|
|
72
|
+
console.log(' [err] incorrect value of "GATEWAY_URL" .env variable!');
|
|
73
|
+
}
|
|
74
|
+
} else { // eslint-disable-next-line no-console
|
|
75
|
+
console.log(' [err] "GATEWAY_URL" .env variable not exists!');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const value = JSON.parse(process.env.TEST_OGPO_CLAIM ?? data.testOGPOClaim);
|
|
80
|
+
data.testOGPOClaim = Boolean(value);
|
|
81
|
+
} catch (error) { // eslint-disable-next-line no-console
|
|
82
|
+
console.log(' [err] incorrect value of "TEST_OGPO_CLAIM" .env variable!');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const checkEnvExists = (directory, extension) => {
|
|
90
|
+
const files = getFiles(directory, extension);
|
|
91
|
+
if (!files.length) throw new Error('[err] .env.test file not exists in root directory!');
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const generateTestDataFile = (filePath) => {
|
|
95
|
+
const emptyObj = {};
|
|
96
|
+
if (!fs.existsSync(filePath)) fs.writeFileSync(filePath, JSON.stringify(emptyObj, null, 2), 'utf8');
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
checkEnvExists(envDirectory, '.test');
|
|
100
|
+
setConfigData(JSONDirectory, '.json');
|
|
101
|
+
generateTestDataFile(testCarsFileLocation);
|
|
102
|
+
generateTestDataFile(testClientsFileLocation);
|
|
103
|
+
generateTestDataFile(averageRBNSFileLocation);
|
|
104
|
+
generateJSONLoader(loaderFileLocation, JSONDirectory, '.json');
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const YAML = require('js-yaml');
|
|
4
|
+
|
|
5
|
+
const projectDirectory = path.join(__dirname, '../../../../../');
|
|
6
|
+
const specDirectory = path.join(projectDirectory, './test/tests/specs');
|
|
7
|
+
|
|
8
|
+
const specFiles = fs.readdirSync(specDirectory);
|
|
9
|
+
const jobs = specFiles.map((spec, index) => ({
|
|
10
|
+
[`API tests ${index + 1}`]: {
|
|
11
|
+
image: 'node:latest',
|
|
12
|
+
stage: 'test',
|
|
13
|
+
variables: {
|
|
14
|
+
SPEC_PATTERN: index + 1,
|
|
15
|
+
},
|
|
16
|
+
only: [
|
|
17
|
+
'dev',
|
|
18
|
+
],
|
|
19
|
+
tags: [
|
|
20
|
+
'k8s',
|
|
21
|
+
],
|
|
22
|
+
before_script: [
|
|
23
|
+
// eslint-disable-next-line no-template-curly-in-string
|
|
24
|
+
'echo "${ENV_TEST}" | tr -d "\r" > ./.env.test',
|
|
25
|
+
'apt-get update && apt-get install -y default-jre',
|
|
26
|
+
'npm install',
|
|
27
|
+
],
|
|
28
|
+
script: [
|
|
29
|
+
'npm run lint',
|
|
30
|
+
'npm run test:split',
|
|
31
|
+
],
|
|
32
|
+
artifacts: {
|
|
33
|
+
when: 'always',
|
|
34
|
+
expire_in: '1 month',
|
|
35
|
+
paths: [
|
|
36
|
+
'test/artifacts',
|
|
37
|
+
'test/resources/data/configData.json',
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
const gitlabCIConfig = {
|
|
44
|
+
...Object.assign({}, ...jobs),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
fs.writeFileSync(
|
|
48
|
+
path.join(__dirname, '..', '..', '..', '..', '.split-config.yml'),
|
|
49
|
+
YAML.dump(gitlabCIConfig),
|
|
50
|
+
);
|
package/src/db/baseDB.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const mysql = require('mysql2/promise');
|
|
2
|
+
const Logger = require('../log/logger');
|
|
3
|
+
|
|
4
|
+
class BaseDB {
|
|
5
|
+
#host;
|
|
6
|
+
|
|
7
|
+
#user;
|
|
8
|
+
|
|
9
|
+
#port;
|
|
10
|
+
|
|
11
|
+
#password;
|
|
12
|
+
|
|
13
|
+
#database;
|
|
14
|
+
|
|
15
|
+
#connection;
|
|
16
|
+
|
|
17
|
+
constructor(host, user, password, database, port) {
|
|
18
|
+
this.#host = host;
|
|
19
|
+
this.#user = user;
|
|
20
|
+
this.#password = password;
|
|
21
|
+
this.#database = database;
|
|
22
|
+
this.#port = port;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async createConnection() {
|
|
26
|
+
Logger.log(`[inf] ▶ connect to ${this.#database} database`);
|
|
27
|
+
this.#connection = await mysql.createConnection({
|
|
28
|
+
host: this.#host,
|
|
29
|
+
user: this.#user,
|
|
30
|
+
password: this.#password,
|
|
31
|
+
database: this.#database,
|
|
32
|
+
port: this.#port,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async closeConnection() {
|
|
37
|
+
Logger.log(`[inf] ▶ close connection to ${this.#database} database`);
|
|
38
|
+
await this.#connection.end();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async sqlQuery(query, values) {
|
|
42
|
+
const [rows] = await this.#connection.query(query, values);
|
|
43
|
+
return rows;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async sqlSelect(
|
|
47
|
+
tableName,
|
|
48
|
+
target = '*',
|
|
49
|
+
conditions = '',
|
|
50
|
+
values = [],
|
|
51
|
+
options = { hasLogger: true },
|
|
52
|
+
) {
|
|
53
|
+
if (options.hasLogger) Logger.log(`[inf] ▶ select ${target} from ${tableName} table`);
|
|
54
|
+
const query = `SELECT ${target} FROM ${tableName} ${conditions};`;
|
|
55
|
+
return this.sqlQuery(query, values);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = BaseDB;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Auto-generated file
|
|
2
|
+
|
|
3
|
+
exports.baseAPI = require('./api/baseAPI');
|
|
4
|
+
exports.JSONLoader = require('./data/JSONLoader');
|
|
5
|
+
exports.JSONMapper = require('./data/JSONMapper');
|
|
6
|
+
exports.dataUtils = require('./data/dataUtils');
|
|
7
|
+
exports.filesParser = require('./data/filesParser');
|
|
8
|
+
exports.gitlabCIGenerator = require('./data/gitlabCIGenerator');
|
|
9
|
+
exports.baseDB = require('./db/baseDB');
|
|
10
|
+
exports.index = require('./index');
|
|
11
|
+
exports.logger = require('./log/logger');
|
|
12
|
+
exports.randomizer = require('./random/randomizer');
|
|
13
|
+
exports.timeUtils = require('./time/timeUtils');
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const moment = require('moment');
|
|
3
|
+
const { createWriteStream } = require('fs');
|
|
4
|
+
const allureMocha = require('allure-mocha/runtime');
|
|
5
|
+
const JSONLoader = require('../data/JSONLoader');
|
|
6
|
+
|
|
7
|
+
const filePath = path.join(path.resolve(), 'test', 'artifacts', 'log.txt');
|
|
8
|
+
const timeList = [];
|
|
9
|
+
const logList = [];
|
|
10
|
+
|
|
11
|
+
class Logger {
|
|
12
|
+
static #title;
|
|
13
|
+
|
|
14
|
+
static log(step, title) {
|
|
15
|
+
logList.push(` ${step}`);
|
|
16
|
+
const timeStamp = moment().format().slice(0, 19).replace('T', ' ');
|
|
17
|
+
timeList.push(`${timeStamp}`);
|
|
18
|
+
if (title) this.#title = title;
|
|
19
|
+
allureMocha.allure.logStep(`${timeStamp} ${step}`);
|
|
20
|
+
if (!JSONLoader.configData.parallel) {
|
|
21
|
+
const stream = createWriteStream(filePath, { flags: 'a', autoClose: true });
|
|
22
|
+
if (!title) stream.write(`${timeStamp} ${step}\n`);
|
|
23
|
+
this.hideLogBodies(step);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static hideLogBodies(step) {
|
|
28
|
+
if (JSONLoader.configData.hiddenLogBodies && step.includes('[req]')) {
|
|
29
|
+
const words = step.split(' ');
|
|
30
|
+
const firstPart = words.slice(0, 3).join(' ');
|
|
31
|
+
const secondPart = words.slice(words.length - 2).join(' ');
|
|
32
|
+
console.log(` ${firstPart} ${secondPart}`); // eslint-disable-line no-console
|
|
33
|
+
} else {
|
|
34
|
+
console.log(` ${step}`); // eslint-disable-line no-console
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static logParallel() {
|
|
39
|
+
logList.forEach((step) => this.hideLogBodies(step.trim()));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static logToFileParallel() {
|
|
43
|
+
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
|
|
44
|
+
const summaryList = zip(timeList, logList);
|
|
45
|
+
summaryList.shift();
|
|
46
|
+
const fileName = filePath.split('/')
|
|
47
|
+
.map((part, index, array) => (index === array.length - 1 ? `${this.#title}.${part}` : part))
|
|
48
|
+
.join('/');
|
|
49
|
+
const stream = createWriteStream(fileName, { flags: 'a', autoClose: true });
|
|
50
|
+
summaryList.forEach((logString) => logString.forEach((logSubString, index) => {
|
|
51
|
+
/* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
|
|
52
|
+
index % 2 !== 0 ? stream.write(`${logSubString}\n`) : stream.write(`${logSubString}`);
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = Logger;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
class Randomizer {
|
|
2
|
+
static getRandomString(
|
|
3
|
+
hasLowerCase = false,
|
|
4
|
+
hasUpperCase = false,
|
|
5
|
+
hasNumber = false,
|
|
6
|
+
hasCyrillic = false,
|
|
7
|
+
chosenLetter = false,
|
|
8
|
+
minLength = 1,
|
|
9
|
+
maxLength = 10,
|
|
10
|
+
) {
|
|
11
|
+
const upperCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
12
|
+
const lowerCaseLetters = 'abcdefghijklmnopqrstuvwxyz';
|
|
13
|
+
const numbers = '0123456789';
|
|
14
|
+
const cyrillicLetters = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя';
|
|
15
|
+
|
|
16
|
+
const length = this.getRandomInteger(maxLength, minLength);
|
|
17
|
+
|
|
18
|
+
let randomString = '';
|
|
19
|
+
if (chosenLetter) randomString += chosenLetter;
|
|
20
|
+
|
|
21
|
+
let requiredCharacters = '';
|
|
22
|
+
if (hasLowerCase) {
|
|
23
|
+
requiredCharacters
|
|
24
|
+
+= lowerCaseLetters.charAt(Math.floor(Math.random() * lowerCaseLetters.length));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (hasUpperCase) {
|
|
28
|
+
requiredCharacters
|
|
29
|
+
+= upperCaseLetters.charAt(Math.floor(Math.random() * upperCaseLetters.length));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (hasNumber) {
|
|
33
|
+
requiredCharacters
|
|
34
|
+
+= numbers.charAt(Math.floor(Math.random() * numbers.length));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (hasCyrillic) {
|
|
38
|
+
requiredCharacters
|
|
39
|
+
+= cyrillicLetters.charAt(Math.floor(Math.random() * cyrillicLetters.length));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
randomString += requiredCharacters;
|
|
43
|
+
|
|
44
|
+
const characters = (hasLowerCase ? lowerCaseLetters : '')
|
|
45
|
+
+ (hasUpperCase ? upperCaseLetters : '')
|
|
46
|
+
+ (hasNumber ? numbers : '')
|
|
47
|
+
+ (hasCyrillic ? cyrillicLetters : '');
|
|
48
|
+
const charactersLength = characters.length;
|
|
49
|
+
const randomLength = length - randomString.length;
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < randomLength; i += 1) {
|
|
52
|
+
randomString += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this.stringShuffler(randomString);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static stringShuffler(inputString) {
|
|
59
|
+
const array = inputString.split('');
|
|
60
|
+
let currentIndex = array.length;
|
|
61
|
+
let temporaryValue;
|
|
62
|
+
let randomIndex;
|
|
63
|
+
while (currentIndex !== 0) {
|
|
64
|
+
randomIndex = Math.floor(Math.random() * currentIndex);
|
|
65
|
+
currentIndex -= 1;
|
|
66
|
+
temporaryValue = array[currentIndex];
|
|
67
|
+
array[currentIndex] = array[randomIndex];
|
|
68
|
+
array[randomIndex] = temporaryValue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return array.join('');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static getRandomInteger(max = 9, min = 0) {
|
|
75
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static getRandomArrayElement(array) {
|
|
79
|
+
return array[Randomizer.getRandomInteger(array.length - 1)];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = Randomizer;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const moment = require('moment');
|
|
2
|
+
const JSONLoader = require('../data/JSONLoader');
|
|
3
|
+
|
|
4
|
+
class TimeUtils {
|
|
5
|
+
static getDatesInterval(count, unitOfTime, options = {}) {
|
|
6
|
+
const { dateBegin } = options;
|
|
7
|
+
const startNextDay = options.startNextDay ?? true;
|
|
8
|
+
const isNotIncluded = options.isNotIncluded ?? true;
|
|
9
|
+
const reverseInterval = options.reverseInterval ?? false;
|
|
10
|
+
|
|
11
|
+
let startDate;
|
|
12
|
+
if (reverseInterval) {
|
|
13
|
+
startDate = startNextDay ? moment().subtract(1, 'days') : moment();
|
|
14
|
+
} else {
|
|
15
|
+
startDate = startNextDay ? moment().add(1, 'days') : moment();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let finishDate;
|
|
19
|
+
if (reverseInterval) {
|
|
20
|
+
finishDate = dateBegin
|
|
21
|
+
? moment(dateBegin, JSONLoader.testData.datesFormatDMY).subtract(count, unitOfTime)
|
|
22
|
+
: moment(startDate).subtract(count, unitOfTime);
|
|
23
|
+
if (isNotIncluded) {
|
|
24
|
+
finishDate = moment(finishDate).add(1, 'days');
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
finishDate = dateBegin
|
|
28
|
+
? moment(dateBegin, JSONLoader.testData.datesFormatDMY).add(count, unitOfTime)
|
|
29
|
+
: moment(startDate).add(count, unitOfTime);
|
|
30
|
+
if (isNotIncluded) {
|
|
31
|
+
finishDate = moment(finishDate).subtract(1, 'days');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
startDate = moment(startDate).format(JSONLoader.testData.datesFormatDMY);
|
|
36
|
+
finishDate = moment(finishDate).format(JSONLoader.testData.datesFormatDMY);
|
|
37
|
+
return reverseInterval
|
|
38
|
+
? { startDate: finishDate, finishDate: dateBegin ?? startDate }
|
|
39
|
+
: { startDate: dateBegin ?? startDate, finishDate };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static reformatDateFromYMDToDMY(date) {
|
|
43
|
+
return moment(date, JSONLoader.testData.datesFormatYMD)
|
|
44
|
+
.format(JSONLoader.testData.datesFormatDMY);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static reformatDateFromDMYToYMD(date) {
|
|
48
|
+
return moment(date, JSONLoader.testData.datesFormatDMY)
|
|
49
|
+
.format(JSONLoader.testData.datesFormatYMD);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static reformatDateFromDMYToYMDHms(date) {
|
|
53
|
+
return moment(date, JSONLoader.testData.datesFormatDMY)
|
|
54
|
+
.format(JSONLoader.testData.datesFormatYMDHms);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = TimeUtils;
|