complexqa_frontend_core 1.0.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 +43 -0
- package/publish/complexqa_frontend_core.js +2991 -0
|
@@ -0,0 +1,2991 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Прототип идеи, пока не уверен, что именно так надо
|
|
3
|
+
*
|
|
4
|
+
* @version v.0.1 (25/06/2024)
|
|
5
|
+
*/
|
|
6
|
+
class App
|
|
7
|
+
{
|
|
8
|
+
|
|
9
|
+
init_options = false;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @version v.0.1 (25/06/2024)
|
|
14
|
+
*/
|
|
15
|
+
constructor(init_options)
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
if (this.constructor._instance)
|
|
19
|
+
{
|
|
20
|
+
return this.constructor._instance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.init_options = init_options;
|
|
24
|
+
this.constructor._instance = this;
|
|
25
|
+
|
|
26
|
+
this.#bootstrap();
|
|
27
|
+
|
|
28
|
+
return this.constructor._instance;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @version v.0.1 (25/06/2024)
|
|
34
|
+
*/
|
|
35
|
+
#bootstrap()
|
|
36
|
+
{
|
|
37
|
+
this.service = {};
|
|
38
|
+
this.service.translate = new serviceTranslate();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Общие методы для всех типизированных элементов
|
|
44
|
+
*
|
|
45
|
+
* @version v.2.0 (24/11/2024)
|
|
46
|
+
*/
|
|
47
|
+
class ApiAbstractElementClass
|
|
48
|
+
{
|
|
49
|
+
|
|
50
|
+
init_options;
|
|
51
|
+
element_class_instance;
|
|
52
|
+
dev_stage_config;
|
|
53
|
+
parent_app;
|
|
54
|
+
host_api;
|
|
55
|
+
stage = 'production';
|
|
56
|
+
module_prefix = false;
|
|
57
|
+
api_prefix = 'web_api';
|
|
58
|
+
method;
|
|
59
|
+
headers;
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @version v.0.1 (27/06/2024)
|
|
65
|
+
* @param options
|
|
66
|
+
*/
|
|
67
|
+
constructor(options)
|
|
68
|
+
{
|
|
69
|
+
if (options?.init_options)
|
|
70
|
+
{
|
|
71
|
+
this.init_options = options?.init_options;
|
|
72
|
+
}
|
|
73
|
+
if (options?.stage)
|
|
74
|
+
{
|
|
75
|
+
this.stage = options?.stage;
|
|
76
|
+
}
|
|
77
|
+
if (options?.dev_stage_config)
|
|
78
|
+
{
|
|
79
|
+
this.dev_stage_config = options?.dev_stage_config;
|
|
80
|
+
}
|
|
81
|
+
if (options?.parent_app)
|
|
82
|
+
{
|
|
83
|
+
this.parent_app = options?.parent_app;
|
|
84
|
+
}
|
|
85
|
+
if (options?.host_api)
|
|
86
|
+
{
|
|
87
|
+
this.host_api = options?.host_api;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
set_element_class_instance(element_class_instance)
|
|
93
|
+
{
|
|
94
|
+
this.element_class_instance = element_class_instance;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @version v.0.1 (26/05/2024)
|
|
101
|
+
* @param {object|typeFOR} payload
|
|
102
|
+
* @param {array} payload.filter
|
|
103
|
+
* @param {?object|undefined} payload.object
|
|
104
|
+
* @param {?object|undefined} payload.response
|
|
105
|
+
*/
|
|
106
|
+
async search(payload)
|
|
107
|
+
{
|
|
108
|
+
if (!this.module_prefix)
|
|
109
|
+
{
|
|
110
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (this.stage === 'development')
|
|
114
|
+
{
|
|
115
|
+
let response = await this.#mock_search(payload);
|
|
116
|
+
return {
|
|
117
|
+
response: response,
|
|
118
|
+
payload : payload
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let url = `/${ this.api_prefix }/${ this.module_prefix }/search`;
|
|
123
|
+
|
|
124
|
+
payload = this.#handle_request_payload(payload);
|
|
125
|
+
let response = this.#api_request(url, payload);
|
|
126
|
+
response = this.#handle_response(response);
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
response: response,
|
|
130
|
+
payload : payload
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
*
|
|
137
|
+
* @version v.0.1 (27/06/2024)
|
|
138
|
+
* @param payload
|
|
139
|
+
* @returns {Promise<array>}
|
|
140
|
+
*/
|
|
141
|
+
async #mock_search(payload)
|
|
142
|
+
{
|
|
143
|
+
// @todo - дописать
|
|
144
|
+
if (this.dev_stage_config.api_response_search_element_count > 0 && this.dev_stage_config.api_response_search_element_count < 999)
|
|
145
|
+
{
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
else
|
|
149
|
+
{
|
|
150
|
+
throw new Error('Error #100-154');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let model = new this.element_class_instance();
|
|
154
|
+
let response = model.get_random_demo_data(this.dev_stage_config.api_response_search_element_count)
|
|
155
|
+
|
|
156
|
+
return response;
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
*
|
|
163
|
+
* @version v.0.1 (26/05/2024)
|
|
164
|
+
* @param payload
|
|
165
|
+
*/
|
|
166
|
+
async find(payload)
|
|
167
|
+
{
|
|
168
|
+
if (!this.module_prefix)
|
|
169
|
+
{
|
|
170
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* @version v.0.1 (26/05/2024)
|
|
178
|
+
* @param payload
|
|
179
|
+
*/
|
|
180
|
+
async create(payload)
|
|
181
|
+
{
|
|
182
|
+
if (!this.module_prefix)
|
|
183
|
+
{
|
|
184
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (this.stage === 'development')
|
|
188
|
+
{
|
|
189
|
+
return {
|
|
190
|
+
response: payload,
|
|
191
|
+
payload : payload
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let url = `/${ this.api_prefix }/${ this.module_prefix }/create`;
|
|
196
|
+
|
|
197
|
+
payload = this.#handle_request_payload(payload);
|
|
198
|
+
let response = this.#api_request(url, payload);
|
|
199
|
+
response = this.#handle_response(response);
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
response: response,
|
|
203
|
+
payload : payload
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
*
|
|
210
|
+
* @version v.0.1 (26/05/2024)
|
|
211
|
+
* @param payload
|
|
212
|
+
*/
|
|
213
|
+
async update(payload)
|
|
214
|
+
{
|
|
215
|
+
if (!this.module_prefix)
|
|
216
|
+
{
|
|
217
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
*
|
|
225
|
+
* @version v.0.1 (26/05/2024)
|
|
226
|
+
* @param payload
|
|
227
|
+
*/
|
|
228
|
+
async update_property(payload)
|
|
229
|
+
{
|
|
230
|
+
if (!this.module_prefix)
|
|
231
|
+
{
|
|
232
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
*
|
|
240
|
+
* @version v.0.1 (26/05/2024)
|
|
241
|
+
* @param payload
|
|
242
|
+
*/
|
|
243
|
+
async delete(payload)
|
|
244
|
+
{
|
|
245
|
+
if (!this.module_prefix)
|
|
246
|
+
{
|
|
247
|
+
throw new Error('Error #10-1152 in ApiAbstractClass');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
/******************************************************************************************/
|
|
254
|
+
/******************************************************************************************/
|
|
255
|
+
|
|
256
|
+
/******************************************************************************************/
|
|
257
|
+
|
|
258
|
+
#handle_request_payload(payload)
|
|
259
|
+
{
|
|
260
|
+
return this.#object_replace_null_recursively(payload);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#object_replace_null_recursively(object)
|
|
264
|
+
{
|
|
265
|
+
let result = clone_object(object);
|
|
266
|
+
for (let key in result)
|
|
267
|
+
{
|
|
268
|
+
if (result[ key ] === null)
|
|
269
|
+
{
|
|
270
|
+
result[ key ] = 'NULL';
|
|
271
|
+
}
|
|
272
|
+
else if (( result[ key ]?.constructor === Object ) || ( result[ key ]?.constructor === Array ))
|
|
273
|
+
{
|
|
274
|
+
result[ key ] = this.#object_replace_null_recursively(result[ key ]);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
*
|
|
284
|
+
* @param url
|
|
285
|
+
* @param payload
|
|
286
|
+
* @param method
|
|
287
|
+
* @returns {Promise<Promise<axios.AxiosResponse<any>> | *>}
|
|
288
|
+
* @version v.0.2 (26/01/2025)
|
|
289
|
+
*/
|
|
290
|
+
async #api_request(url, payload, method = 'POST')
|
|
291
|
+
{
|
|
292
|
+
let request_params;
|
|
293
|
+
if (!payload)
|
|
294
|
+
{
|
|
295
|
+
request_params = {};
|
|
296
|
+
}
|
|
297
|
+
else
|
|
298
|
+
{
|
|
299
|
+
request_params = clone_object(payload)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
request_params = this.#mixin_service_params(request_params);
|
|
303
|
+
|
|
304
|
+
console.log({payload, request_params});
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
if (this.host_api)
|
|
308
|
+
{
|
|
309
|
+
url = 'https://' + this.host_api + url;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
let request_options = {
|
|
313
|
+
method : method,
|
|
314
|
+
headers: this.headers,
|
|
315
|
+
url : url
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
if (this.method === 'get')
|
|
319
|
+
{
|
|
320
|
+
request_options.paramsSerializer = this.object_to_string;
|
|
321
|
+
request_options.params = request_params;
|
|
322
|
+
}
|
|
323
|
+
else
|
|
324
|
+
{
|
|
325
|
+
request_options.data = (request_params);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let config = {};
|
|
329
|
+
|
|
330
|
+
return axios(request_options, config);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
*
|
|
336
|
+
* @param object
|
|
337
|
+
* @returns {string}
|
|
338
|
+
*/
|
|
339
|
+
object_to_string(object)
|
|
340
|
+
{
|
|
341
|
+
let result = qs.stringify(object, { array_format: 'indices' });
|
|
342
|
+
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
#mixin_service_params(params)
|
|
348
|
+
{
|
|
349
|
+
params.client = 'webapp';
|
|
350
|
+
return params;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
*
|
|
356
|
+
* @param {} response
|
|
357
|
+
* @returns {Promise<any>}
|
|
358
|
+
* @version v.0.1 (01/06/2024)
|
|
359
|
+
*/
|
|
360
|
+
#handle_response(response)
|
|
361
|
+
{
|
|
362
|
+
response = response.then((api_response) =>
|
|
363
|
+
{
|
|
364
|
+
let error_payload = {
|
|
365
|
+
api_response: api_response?.data?.api_response,
|
|
366
|
+
api_code : api_response?.data?.api_code,
|
|
367
|
+
api_result : api_response?.data?.api_result,
|
|
368
|
+
api_error : api_response?.data?.api_error
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
if (api_response?.data?.api_error?.adapted_message)
|
|
372
|
+
{
|
|
373
|
+
error_payload.message = api_response.data.api_error.adapted_message
|
|
374
|
+
throw new ApiException(error_payload);
|
|
375
|
+
}
|
|
376
|
+
else if (api_response?.data?.api_code)
|
|
377
|
+
{
|
|
378
|
+
let api_code = api_response.data.api_code;
|
|
379
|
+
|
|
380
|
+
if (( api_code >= 200 ) && ( api_code <= 299 ))
|
|
381
|
+
{
|
|
382
|
+
if (is_array(api_response?.data) && this.element_class_instance)
|
|
383
|
+
{
|
|
384
|
+
let result = api_response?.data.map((row) =>
|
|
385
|
+
{
|
|
386
|
+
return new this.element_class_instance(row);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
else
|
|
392
|
+
{
|
|
393
|
+
return api_response?.data;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else if (api_response?.data?.api_result === false)
|
|
397
|
+
{
|
|
398
|
+
throw new ApiException(error_payload);
|
|
399
|
+
}
|
|
400
|
+
else
|
|
401
|
+
{
|
|
402
|
+
throw new ApiException(error_payload);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else
|
|
406
|
+
{
|
|
407
|
+
return api_response?.data;
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
.catch((error) =>
|
|
411
|
+
{
|
|
412
|
+
|
|
413
|
+
echo({ app: this });
|
|
414
|
+
console.error(error);
|
|
415
|
+
if (error instanceof ApiException)
|
|
416
|
+
{
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
throw new ApiException({ error: error });
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
return response;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
*
|
|
430
|
+
* @version v.0.1 (24/11/2024)
|
|
431
|
+
*/
|
|
432
|
+
class FunctionalApi extends ApiAbstractElementClass
|
|
433
|
+
{
|
|
434
|
+
module_prefix = 'functional';
|
|
435
|
+
|
|
436
|
+
constructor(options)
|
|
437
|
+
{
|
|
438
|
+
super(options);
|
|
439
|
+
this.set_element_class_instance(typeFunctional);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Обертка над axios
|
|
444
|
+
* @version v.0.3 (26/01/2025)
|
|
445
|
+
*/
|
|
446
|
+
class Api
|
|
447
|
+
{
|
|
448
|
+
/**
|
|
449
|
+
* Режим работы
|
|
450
|
+
*
|
|
451
|
+
* @type {string} development || production || tests
|
|
452
|
+
*/
|
|
453
|
+
stage = 'development';
|
|
454
|
+
dev_stage_config = {
|
|
455
|
+
generate_error : false,
|
|
456
|
+
api_response_delay : 3500,
|
|
457
|
+
api_response_search_element_count: 8,
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
init_options;
|
|
461
|
+
|
|
462
|
+
test_plan;
|
|
463
|
+
/**
|
|
464
|
+
* {ProjectApi} project
|
|
465
|
+
*/
|
|
466
|
+
project;
|
|
467
|
+
service;
|
|
468
|
+
|
|
469
|
+
host_api = false;
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
*
|
|
474
|
+
* @version v.0.3 (26/01/2025)
|
|
475
|
+
*/
|
|
476
|
+
constructor(init_options)
|
|
477
|
+
{
|
|
478
|
+
|
|
479
|
+
if (this.constructor._instance)
|
|
480
|
+
{
|
|
481
|
+
return this.constructor._instance;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
if (init_options.host_api)
|
|
486
|
+
{
|
|
487
|
+
// @todo validate
|
|
488
|
+
this.host_api = init_options.host_api;
|
|
489
|
+
}
|
|
490
|
+
else
|
|
491
|
+
{
|
|
492
|
+
// подумать
|
|
493
|
+
this.host_api = 'complexqa.localhost';
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (init_options.stage)
|
|
497
|
+
{
|
|
498
|
+
// @todo validate
|
|
499
|
+
this.stage = init_options.stage;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (init_options.dev_stage_config)
|
|
503
|
+
{
|
|
504
|
+
// @todo validate
|
|
505
|
+
this.dev_stage_config = init_options.dev_stage_config;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
this.init_options = init_options;
|
|
509
|
+
this.constructor._instance = this;
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
this.#bootstrap();
|
|
513
|
+
return this.constructor._instance;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
*
|
|
519
|
+
* @param stage
|
|
520
|
+
*/
|
|
521
|
+
set_stage(stage)
|
|
522
|
+
{
|
|
523
|
+
this.stage = stage;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
*
|
|
529
|
+
* @version v.0.1 (25/06/2024)
|
|
530
|
+
*/
|
|
531
|
+
#bootstrap()
|
|
532
|
+
{
|
|
533
|
+
let payload = {
|
|
534
|
+
init_options : this.init_options,
|
|
535
|
+
stage : this.stage,
|
|
536
|
+
dev_stage_config: this.dev_stage_config,
|
|
537
|
+
host_api: this.host_api,
|
|
538
|
+
parent_app : this
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
//echo({payload});
|
|
542
|
+
|
|
543
|
+
this.test_plan = new TestPlanApi(payload);
|
|
544
|
+
this.project = new ProjectApi(payload);
|
|
545
|
+
this.service = new ServiceApi(payload);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
*
|
|
550
|
+
* @version v.0.1 (15/06/2024)
|
|
551
|
+
*/
|
|
552
|
+
class ProjectApi extends ApiAbstractElementClass
|
|
553
|
+
{
|
|
554
|
+
module_prefix = 'project';
|
|
555
|
+
|
|
556
|
+
constructor(options)
|
|
557
|
+
{
|
|
558
|
+
super(options);
|
|
559
|
+
this.set_element_class_instance(typeProject);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// тут нужен свой класс, не для типов
|
|
564
|
+
class ServiceApi
|
|
565
|
+
{
|
|
566
|
+
module_prefix = '--';
|
|
567
|
+
|
|
568
|
+
constructor(options)
|
|
569
|
+
{
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
*
|
|
575
|
+
* @returns {Promise<*[]>}
|
|
576
|
+
*/
|
|
577
|
+
async translate_get_dictionaries()
|
|
578
|
+
{
|
|
579
|
+
return [];
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
*
|
|
585
|
+
* @version v.0.1 (24/11/2024)
|
|
586
|
+
*/
|
|
587
|
+
class TeamMemberApi extends ApiAbstractElementClass
|
|
588
|
+
{
|
|
589
|
+
module_prefix = 'team_member';
|
|
590
|
+
|
|
591
|
+
constructor(options)
|
|
592
|
+
{
|
|
593
|
+
super(options);
|
|
594
|
+
this.set_element_class_instance(typeTeamMember);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
*
|
|
600
|
+
* @version v.0.1 (24/11/2024)
|
|
601
|
+
*/
|
|
602
|
+
class TestCaseApi extends ApiAbstractElementClass
|
|
603
|
+
{
|
|
604
|
+
module_prefix = 'test_case';
|
|
605
|
+
|
|
606
|
+
constructor(options)
|
|
607
|
+
{
|
|
608
|
+
super(options);
|
|
609
|
+
this.set_element_class_instance(typeTestCase);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
*
|
|
615
|
+
* @version v.0.1 (24/11/2024)
|
|
616
|
+
*/
|
|
617
|
+
class TestCaseStepApi extends ApiAbstractElementClass
|
|
618
|
+
{
|
|
619
|
+
module_prefix = 'test_case_step';
|
|
620
|
+
|
|
621
|
+
constructor(options)
|
|
622
|
+
{
|
|
623
|
+
super(options);
|
|
624
|
+
this.set_element_class_instance(typeTestCaseStep);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
*
|
|
630
|
+
* @version v.0.1 (26/05/2024)
|
|
631
|
+
*/
|
|
632
|
+
class TestPlanApi extends ApiAbstractElementClass
|
|
633
|
+
{
|
|
634
|
+
module_prefix = 'test_plan';
|
|
635
|
+
|
|
636
|
+
constructor(options)
|
|
637
|
+
{
|
|
638
|
+
super(options);
|
|
639
|
+
this.set_element_class_instance(typeTestPlan);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
class TestRunApi extends ApiAbstractElementClass
|
|
643
|
+
{
|
|
644
|
+
module_prefix = 'test_run';
|
|
645
|
+
|
|
646
|
+
constructor(options)
|
|
647
|
+
{
|
|
648
|
+
super(options);
|
|
649
|
+
this.set_element_class_instance(typeTestRun);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
*
|
|
655
|
+
* @version v.0.1 (24/11/2024)
|
|
656
|
+
*/
|
|
657
|
+
class TestRunResultApi extends ApiAbstractElementClass
|
|
658
|
+
{
|
|
659
|
+
module_prefix = 'test_run_result';
|
|
660
|
+
|
|
661
|
+
constructor(options)
|
|
662
|
+
{
|
|
663
|
+
super(options);
|
|
664
|
+
this.set_element_class_instance(typeTestRunResult);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
*
|
|
670
|
+
* @version v.0.1 (24/11/2024)
|
|
671
|
+
*/
|
|
672
|
+
class TestSuiteApi extends ApiAbstractElementClass
|
|
673
|
+
{
|
|
674
|
+
module_prefix = 'test_suite';
|
|
675
|
+
|
|
676
|
+
constructor(options)
|
|
677
|
+
{
|
|
678
|
+
super(options);
|
|
679
|
+
this.set_element_class_instance(typeTestSuite);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
class ApiException extends Error
|
|
683
|
+
{
|
|
684
|
+
/**
|
|
685
|
+
* Сообщение об ошибке
|
|
686
|
+
* @type {string}
|
|
687
|
+
*/
|
|
688
|
+
#message = '';
|
|
689
|
+
/**
|
|
690
|
+
* Нативная ошибка
|
|
691
|
+
* @type {null|Error}
|
|
692
|
+
*/
|
|
693
|
+
#error = null;
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
api_response = null;
|
|
697
|
+
api_code = null;
|
|
698
|
+
api_result = null;
|
|
699
|
+
api_error = null;
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
constructor(options)
|
|
703
|
+
{
|
|
704
|
+
super();
|
|
705
|
+
|
|
706
|
+
if (options.message)
|
|
707
|
+
{
|
|
708
|
+
this.#message = options.message;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (options.error instanceof Error)
|
|
712
|
+
{
|
|
713
|
+
this.#error = options.error;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
if (options?.api_response)
|
|
718
|
+
{
|
|
719
|
+
this.api_response = options?.api_response;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (options?.api_code)
|
|
723
|
+
{
|
|
724
|
+
this.api_code = options?.api_code;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (options?.api_result)
|
|
728
|
+
{
|
|
729
|
+
this.api_result = options?.api_result;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
if (options?.api_error)
|
|
733
|
+
{
|
|
734
|
+
this.api_error = options?.api_error;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
get_message()
|
|
740
|
+
{
|
|
741
|
+
if (this.#error instanceof Error)
|
|
742
|
+
{
|
|
743
|
+
return this.#error.message;
|
|
744
|
+
}
|
|
745
|
+
else
|
|
746
|
+
{
|
|
747
|
+
return this.#message;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
*
|
|
753
|
+
* @version v.0.1 (25/06/2024)
|
|
754
|
+
*/
|
|
755
|
+
class abstractService
|
|
756
|
+
{
|
|
757
|
+
init_options = false;
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
*
|
|
762
|
+
* @param init_options
|
|
763
|
+
*/
|
|
764
|
+
constructor(init_options = false)
|
|
765
|
+
{
|
|
766
|
+
/*if (this.constructor._instance)
|
|
767
|
+
{
|
|
768
|
+
return this.constructor._instance;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
this.init_options = init_options;
|
|
772
|
+
|
|
773
|
+
this.constructor._instance = this;*/
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/*#bootstrap()
|
|
777
|
+
{
|
|
778
|
+
|
|
779
|
+
}*/
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
*
|
|
783
|
+
* @version v.0.1 (25/06/2024)
|
|
784
|
+
*/
|
|
785
|
+
class serviceTranslate extends abstractService
|
|
786
|
+
{
|
|
787
|
+
#language = 'en';
|
|
788
|
+
#available_language = [ 'ru', 'en' ];
|
|
789
|
+
#dictionary = false; // может сделать сторадж отдельно и static ?
|
|
790
|
+
#vendor_instance;
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
*
|
|
795
|
+
* @version v.0.1 (25/06/2024)
|
|
796
|
+
* @param {?object} init_options
|
|
797
|
+
* @returns {serviceTranslate}
|
|
798
|
+
*/
|
|
799
|
+
constructor(init_options = false)
|
|
800
|
+
{
|
|
801
|
+
super(init_options);
|
|
802
|
+
|
|
803
|
+
if (init_options?.language)
|
|
804
|
+
{
|
|
805
|
+
if (in_array(init_options?.language, this.#available_language))
|
|
806
|
+
{
|
|
807
|
+
this.#language = init_options?.language;
|
|
808
|
+
}
|
|
809
|
+
else
|
|
810
|
+
{
|
|
811
|
+
echo({ init_options });
|
|
812
|
+
throw new Error('Unsupported language');
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (this.constructor._instance)
|
|
817
|
+
{
|
|
818
|
+
return this.constructor._instance;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
this.init_options = init_options;
|
|
822
|
+
this.constructor._instance = this;
|
|
823
|
+
|
|
824
|
+
this.#bootstrap();
|
|
825
|
+
|
|
826
|
+
return this.constructor._instance;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
*
|
|
832
|
+
* @version v.0.1 (25/06/2024)
|
|
833
|
+
* @param api_response
|
|
834
|
+
*/
|
|
835
|
+
#api_response_parser(api_response)
|
|
836
|
+
{
|
|
837
|
+
|
|
838
|
+
// заготовка
|
|
839
|
+
return api_response;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
*
|
|
845
|
+
* @version v.0.1 (25/06/2024)
|
|
846
|
+
*/
|
|
847
|
+
async #bootstrap()
|
|
848
|
+
{
|
|
849
|
+
this.#dictionary = await Api.service.translate_get_dictionaries();
|
|
850
|
+
|
|
851
|
+
let normalize_response = this.#api_response_parser(this.#dictionary);
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
await i18next.init({
|
|
855
|
+
lng : this.#language,
|
|
856
|
+
debug : false,
|
|
857
|
+
resources: normalize_response
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
this.#vendor_instance = i18next;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
*
|
|
866
|
+
* @version v.0.1 (25/06/2024)
|
|
867
|
+
* @param group
|
|
868
|
+
* @param key
|
|
869
|
+
*/
|
|
870
|
+
get(group, key)
|
|
871
|
+
{
|
|
872
|
+
return this.#vendor_instance.t(group + '.' + key);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
/*
|
|
876
|
+
/!**
|
|
877
|
+
*
|
|
878
|
+
* @version v.1.0 (18/11/2024)
|
|
879
|
+
*!/
|
|
880
|
+
class UserService extends abstractService
|
|
881
|
+
{
|
|
882
|
+
|
|
883
|
+
static #current_user_id = '-1';
|
|
884
|
+
static #user_name = '';
|
|
885
|
+
static #current_team_id = '';
|
|
886
|
+
static #user_teams = [ -1 ];
|
|
887
|
+
static #roles = [ 'user' ];
|
|
888
|
+
static #current_language = 'en';
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
/!**
|
|
892
|
+
*
|
|
893
|
+
*
|
|
894
|
+
* @version v.1.0 (18/11/2024)
|
|
895
|
+
*
|
|
896
|
+
* @param init_options
|
|
897
|
+
* @returns {*}
|
|
898
|
+
*!/
|
|
899
|
+
/!**
|
|
900
|
+
*
|
|
901
|
+
*
|
|
902
|
+
* @version v.1.0 (18/11/2024)
|
|
903
|
+
*
|
|
904
|
+
* @param init_options
|
|
905
|
+
* @returns {*}
|
|
906
|
+
*!/
|
|
907
|
+
constructor(init_options = false)
|
|
908
|
+
{
|
|
909
|
+
super();
|
|
910
|
+
if (this.constructor._instance)
|
|
911
|
+
{
|
|
912
|
+
return this.constructor._instance;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
this.init_options = init_options;
|
|
916
|
+
|
|
917
|
+
this.constructor._instance = this;
|
|
918
|
+
super();
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
static get_current_user_id()
|
|
922
|
+
{
|
|
923
|
+
return UserService.#current_user_id;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
static get_user_name()
|
|
927
|
+
{
|
|
928
|
+
return UserService.#user_name;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
static get_current_team_id()
|
|
932
|
+
{
|
|
933
|
+
return UserService.#current_team_id;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
static get_user_teams()
|
|
937
|
+
{
|
|
938
|
+
return UserService.#user_teams;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
static get_roles()
|
|
942
|
+
{
|
|
943
|
+
return UserService.#roles;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
static get_current_language()
|
|
947
|
+
{
|
|
948
|
+
return UserService.#current_language;
|
|
949
|
+
}
|
|
950
|
+
}*/
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
*
|
|
954
|
+
* @param {object} object
|
|
955
|
+
* @returns {object}
|
|
956
|
+
*/
|
|
957
|
+
function clone_object(object)
|
|
958
|
+
{
|
|
959
|
+
// @todo use deep clone
|
|
960
|
+
// @todo add validation
|
|
961
|
+
return JSON.parse(JSON.stringify(object));
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
*
|
|
966
|
+
* @param {string|number|array|object} text
|
|
967
|
+
*/
|
|
968
|
+
function echo(text)
|
|
969
|
+
{
|
|
970
|
+
console.log(text);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
*
|
|
976
|
+
* @param {string|number|array|object} data
|
|
977
|
+
*/
|
|
978
|
+
function echo_table(...data)
|
|
979
|
+
{
|
|
980
|
+
if (is_array(data))
|
|
981
|
+
{
|
|
982
|
+
data.map((row) =>
|
|
983
|
+
{
|
|
984
|
+
console.table(row);
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
else
|
|
988
|
+
{
|
|
989
|
+
echo(data);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
*
|
|
995
|
+
*
|
|
996
|
+
* @param {*} data
|
|
997
|
+
* @param {boolean} strict_mode
|
|
998
|
+
* @returns {boolean}
|
|
999
|
+
*/
|
|
1000
|
+
function is_array(data, strict_mode = false)
|
|
1001
|
+
{
|
|
1002
|
+
if (strict_mode)
|
|
1003
|
+
{
|
|
1004
|
+
if (data instanceof Array)
|
|
1005
|
+
{
|
|
1006
|
+
return true;
|
|
1007
|
+
}
|
|
1008
|
+
else
|
|
1009
|
+
{
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
else
|
|
1014
|
+
{
|
|
1015
|
+
if (data instanceof Array && data?.length > 0)
|
|
1016
|
+
{
|
|
1017
|
+
return true;
|
|
1018
|
+
}
|
|
1019
|
+
else
|
|
1020
|
+
{
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
*
|
|
1029
|
+
*
|
|
1030
|
+
* @param {*} value
|
|
1031
|
+
* @returns {boolean}
|
|
1032
|
+
*/
|
|
1033
|
+
function is_object(value)
|
|
1034
|
+
{
|
|
1035
|
+
return _.isObject(value);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
*
|
|
1041
|
+
*
|
|
1042
|
+
* @param {*} value
|
|
1043
|
+
* @returns {boolean}
|
|
1044
|
+
*/
|
|
1045
|
+
function is_string(value)
|
|
1046
|
+
{
|
|
1047
|
+
let response = false;
|
|
1048
|
+
if (typeof value === 'string')
|
|
1049
|
+
{
|
|
1050
|
+
response = true;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
return response;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Проверяем на число, не строго (!)
|
|
1059
|
+
* @param {*} value
|
|
1060
|
+
* @returns {boolean}
|
|
1061
|
+
*/
|
|
1062
|
+
function is_number(value)
|
|
1063
|
+
{
|
|
1064
|
+
let response = false;
|
|
1065
|
+
|
|
1066
|
+
if (typeof ( value ) === 'number')
|
|
1067
|
+
{
|
|
1068
|
+
response = true;
|
|
1069
|
+
}
|
|
1070
|
+
else if (value === false)
|
|
1071
|
+
{
|
|
1072
|
+
response = false;
|
|
1073
|
+
}
|
|
1074
|
+
else if (typeof ( value ) === "string" && (!isNaN( value )))
|
|
1075
|
+
{
|
|
1076
|
+
response = true;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
return response
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Возвращает количество элементов массива или false, если передан не массив
|
|
1085
|
+
*
|
|
1086
|
+
* @param {array} array массив
|
|
1087
|
+
* @returns {number|false} количество элементов массива
|
|
1088
|
+
*/
|
|
1089
|
+
function count(array)
|
|
1090
|
+
{
|
|
1091
|
+
let response = false;
|
|
1092
|
+
if (array instanceof Array)
|
|
1093
|
+
{
|
|
1094
|
+
response = array?.length;
|
|
1095
|
+
}
|
|
1096
|
+
else
|
|
1097
|
+
{
|
|
1098
|
+
response = false;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
return response;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
*
|
|
1107
|
+
* @param {string|number} value
|
|
1108
|
+
* @param {array} array
|
|
1109
|
+
* @param {boolean} strict
|
|
1110
|
+
* @returns {boolean}
|
|
1111
|
+
*/
|
|
1112
|
+
function in_array(value, array, strict = false)
|
|
1113
|
+
{
|
|
1114
|
+
if (!is_array(array))
|
|
1115
|
+
{
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
let response = false;
|
|
1119
|
+
|
|
1120
|
+
if (strict)
|
|
1121
|
+
{
|
|
1122
|
+
response = array.find(element =>
|
|
1123
|
+
{
|
|
1124
|
+
return element === value;
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
else
|
|
1128
|
+
{
|
|
1129
|
+
response = array.find(element =>
|
|
1130
|
+
{
|
|
1131
|
+
return element == value;
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
return Boolean(response);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function cls()
|
|
1139
|
+
{
|
|
1140
|
+
console.clear();
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Базовый абстрактный класс для всех типов
|
|
1144
|
+
*
|
|
1145
|
+
* @version v.0.1 (26/05/2024)
|
|
1146
|
+
*/
|
|
1147
|
+
class familyGeneralElement
|
|
1148
|
+
{
|
|
1149
|
+
primary_key = false;
|
|
1150
|
+
create_scheme = false;
|
|
1151
|
+
structure_scheme = false;
|
|
1152
|
+
available_enum_values = false;
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
/***********************************************/
|
|
1156
|
+
/***********************************************/
|
|
1157
|
+
|
|
1158
|
+
/***********************************************/
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
*
|
|
1162
|
+
* @version v.0.1 (26/05/2024)
|
|
1163
|
+
* @return {string|false}
|
|
1164
|
+
*/
|
|
1165
|
+
get_primary_key()
|
|
1166
|
+
{
|
|
1167
|
+
if (this.primary_key)
|
|
1168
|
+
{
|
|
1169
|
+
return this.primary_key;
|
|
1170
|
+
}
|
|
1171
|
+
else
|
|
1172
|
+
{
|
|
1173
|
+
throw new Error('familyGeneralElement has no primary_key. Error #01-01');
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
*
|
|
1180
|
+
* @version v.0.1 (27/06/2024)
|
|
1181
|
+
* @returns {array<familyGeneralElement>}
|
|
1182
|
+
* @param {number} count
|
|
1183
|
+
*/
|
|
1184
|
+
get_random_demo_data(count)
|
|
1185
|
+
{
|
|
1186
|
+
// @todo validations
|
|
1187
|
+
let response = [];
|
|
1188
|
+
for (let i = 0; i < count; i++)
|
|
1189
|
+
{
|
|
1190
|
+
response.push(this.get_demo_row());
|
|
1191
|
+
}
|
|
1192
|
+
// получаем массив сгенерированных элементов,
|
|
1193
|
+
// в том числе - с незаполненными данными (корректная обработка)
|
|
1194
|
+
|
|
1195
|
+
// контроль пересечения primary key
|
|
1196
|
+
// прототип идеи
|
|
1197
|
+
// @todo - дописать
|
|
1198
|
+
return response;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
*
|
|
1203
|
+
* @returns {familyGeneralElement}
|
|
1204
|
+
*/
|
|
1205
|
+
get_demo_row()
|
|
1206
|
+
{
|
|
1207
|
+
return this;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
*
|
|
1212
|
+
* @version v.0.2 (15/06/2024)
|
|
1213
|
+
* @param {string} attribute
|
|
1214
|
+
*/
|
|
1215
|
+
get_available_enum_values(attribute)
|
|
1216
|
+
{
|
|
1217
|
+
let response = false;
|
|
1218
|
+
if (this.structure_scheme?.[ attribute ])
|
|
1219
|
+
{
|
|
1220
|
+
// выбрасывать исключения?
|
|
1221
|
+
return false;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
let rules = this.get_attribute_structure_scheme(attribute);
|
|
1225
|
+
if (!rules)
|
|
1226
|
+
{
|
|
1227
|
+
return false;
|
|
1228
|
+
}
|
|
1229
|
+
if (!in_array('enum', rules))
|
|
1230
|
+
{
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
if (this.available_enum_values?.[ attribute ])
|
|
1235
|
+
{
|
|
1236
|
+
response = this.available_enum_values?.[ attribute ];
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
return response;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
*
|
|
1245
|
+
* @param attribute
|
|
1246
|
+
* @returns {array|false}
|
|
1247
|
+
*/
|
|
1248
|
+
get_attribute_structure_scheme(attribute)
|
|
1249
|
+
{
|
|
1250
|
+
let response = false;
|
|
1251
|
+
if (this.structure_scheme[ attribute ])
|
|
1252
|
+
{
|
|
1253
|
+
let scheme = clone_object(this.structure_scheme[ attribute ]);
|
|
1254
|
+
|
|
1255
|
+
if (scheme)
|
|
1256
|
+
{
|
|
1257
|
+
scheme = scheme.split('|');
|
|
1258
|
+
if (is_array(scheme))
|
|
1259
|
+
{
|
|
1260
|
+
response = [];
|
|
1261
|
+
scheme.map((row) =>
|
|
1262
|
+
{
|
|
1263
|
+
response.push(row.trim());
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return response;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
*
|
|
1275
|
+
* @version v.0.1 (26/05/2024)
|
|
1276
|
+
*/
|
|
1277
|
+
get_data()
|
|
1278
|
+
{
|
|
1279
|
+
return this.get_pure_data();
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
*
|
|
1285
|
+
* @version v.0.1 (26/05/2024)
|
|
1286
|
+
*/
|
|
1287
|
+
get_pure_data()
|
|
1288
|
+
{
|
|
1289
|
+
let response = false;
|
|
1290
|
+
if (this.structure_scheme)
|
|
1291
|
+
{
|
|
1292
|
+
response = {};
|
|
1293
|
+
_.mapObject(this.structure_scheme, (value, attribute) =>
|
|
1294
|
+
{
|
|
1295
|
+
if (this[ attribute ])
|
|
1296
|
+
{
|
|
1297
|
+
response [ attribute ] = this[ attribute ];
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
return response;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* @todo - сделать нормализация по create scheme с валидацией
|
|
1308
|
+
*
|
|
1309
|
+
* @version v.0.1 (26/01/2025)
|
|
1310
|
+
*
|
|
1311
|
+
* @param payload
|
|
1312
|
+
* @returns {*}
|
|
1313
|
+
*/
|
|
1314
|
+
normalize_payload(payload)
|
|
1315
|
+
{
|
|
1316
|
+
|
|
1317
|
+
return payload;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
get_editable_attributes() {}
|
|
1322
|
+
|
|
1323
|
+
is_editable_attribute(attribute) {}
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
*
|
|
1327
|
+
* @version v.0.1 (26/05/2024)
|
|
1328
|
+
* @param {string} attribute_name
|
|
1329
|
+
* @return {string}
|
|
1330
|
+
*/
|
|
1331
|
+
get_attribute_name_translate(attribute_name)
|
|
1332
|
+
{
|
|
1333
|
+
return attribute_name;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
/***********************************************/
|
|
1338
|
+
/***********************************************/
|
|
1339
|
+
|
|
1340
|
+
/***********************************************/
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
*
|
|
1344
|
+
* @version v.0.1 (26/05/2024)
|
|
1345
|
+
* @param id
|
|
1346
|
+
*/
|
|
1347
|
+
async find(id = false)
|
|
1348
|
+
{
|
|
1349
|
+
// или передаем ID, или используем вложенный
|
|
1350
|
+
// возвращаем инстанс себя же
|
|
1351
|
+
alert('Error #267-001 Not implemented method');
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
*
|
|
1356
|
+
* @version v.0.1 (26/05/2024)
|
|
1357
|
+
*/
|
|
1358
|
+
async create()
|
|
1359
|
+
{}
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
*
|
|
1364
|
+
* @version v.0.1 (26/05/2024)
|
|
1365
|
+
*/
|
|
1366
|
+
async update()
|
|
1367
|
+
{
|
|
1368
|
+
alert('Error #272-001 Not implemented method');
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
*
|
|
1374
|
+
* @version v.0.1 (26/05/2024)
|
|
1375
|
+
*/
|
|
1376
|
+
async update_property(key, value, callback)
|
|
1377
|
+
{
|
|
1378
|
+
alert('Error #272-001 Not implemented method');
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
*
|
|
1384
|
+
* @version v.0.1 (26/05/2024)
|
|
1385
|
+
*/
|
|
1386
|
+
async update_properties()
|
|
1387
|
+
{
|
|
1388
|
+
alert('Error #272-001 Not implemented method');
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
*
|
|
1394
|
+
* @version v.0.1 (26/05/2024)
|
|
1395
|
+
* @param element
|
|
1396
|
+
* @param callback
|
|
1397
|
+
* @returns {Promise<boolean>}
|
|
1398
|
+
*/
|
|
1399
|
+
async delete(element, callback)
|
|
1400
|
+
{
|
|
1401
|
+
alert('Error #267-001 Not implemented method');
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Заготовка - логи действий
|
|
1407
|
+
*
|
|
1408
|
+
* @version v.0.1 (15/10/2024)
|
|
1409
|
+
*/
|
|
1410
|
+
class typeActionLog
|
|
1411
|
+
{
|
|
1412
|
+
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
*
|
|
1417
|
+
* @version v.0.1 (23/06/2024)
|
|
1418
|
+
*/
|
|
1419
|
+
class typeFunctional extends familyGeneralElement
|
|
1420
|
+
{
|
|
1421
|
+
functional_id;
|
|
1422
|
+
project_id; // foreign key
|
|
1423
|
+
functional_group_id; // foreign key
|
|
1424
|
+
team_id; // foreign key
|
|
1425
|
+
functional_name;
|
|
1426
|
+
functional_description;
|
|
1427
|
+
reference_document_ids; // IDS документов по функционалу (к примеру confluence)
|
|
1428
|
+
created_at;
|
|
1429
|
+
updated_at;
|
|
1430
|
+
|
|
1431
|
+
primary_key = 'functional_id';
|
|
1432
|
+
|
|
1433
|
+
structure_scheme = {
|
|
1434
|
+
functional_id : 'integer | require',
|
|
1435
|
+
project_id : 'integer | require',
|
|
1436
|
+
functional_group_id : 'integer | require',
|
|
1437
|
+
team_id : 'integer | require',
|
|
1438
|
+
functional_name : 'string | max:90 | require',
|
|
1439
|
+
functional_description: 'string | max:2500 | optional',
|
|
1440
|
+
reference_document_ids: 'array | reference | optional',
|
|
1441
|
+
created_at : 'timestamp | require',
|
|
1442
|
+
updated_at : 'timestamp | optional',
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1445
|
+
available_enum_values = {
|
|
1446
|
+
functional_status: [ 'не идей. нужен ли тут статус' ]
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
/**
|
|
1451
|
+
*
|
|
1452
|
+
* @param {object|false|undefined} data
|
|
1453
|
+
*/
|
|
1454
|
+
constructor(data = false)
|
|
1455
|
+
{
|
|
1456
|
+
super();
|
|
1457
|
+
|
|
1458
|
+
if (data && is_object(data))
|
|
1459
|
+
{
|
|
1460
|
+
_.mapObject(data, (value, key) =>
|
|
1461
|
+
{
|
|
1462
|
+
if (this.hasOwnProperty(key))
|
|
1463
|
+
{
|
|
1464
|
+
this [ key ] = value;
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
return this;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
/******************************************************************************************/
|
|
1474
|
+
/*********************************** general **********************************************/
|
|
1475
|
+
|
|
1476
|
+
/******************************************************************************************/
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
*
|
|
1480
|
+
* @version v.0.1 (07/07/2024)
|
|
1481
|
+
*/
|
|
1482
|
+
async create()
|
|
1483
|
+
{}
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
*
|
|
1488
|
+
* @version v.0.1 (07/07/2024)
|
|
1489
|
+
*/
|
|
1490
|
+
async update()
|
|
1491
|
+
{
|
|
1492
|
+
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
/**
|
|
1497
|
+
*
|
|
1498
|
+
* @version v.0.1 (07/07/2024)
|
|
1499
|
+
*/
|
|
1500
|
+
async delete()
|
|
1501
|
+
{
|
|
1502
|
+
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
/**
|
|
1509
|
+
* @version v.0.2 (25/01/2025)
|
|
1510
|
+
*/
|
|
1511
|
+
class typeFunctionalGroup extends familyGeneralElement
|
|
1512
|
+
{
|
|
1513
|
+
functional_group_id;
|
|
1514
|
+
project_id; // foreign key
|
|
1515
|
+
team_id; // foreign key
|
|
1516
|
+
parent_id; // для организации вложенности
|
|
1517
|
+
functional_group_name;
|
|
1518
|
+
functional_group_description;
|
|
1519
|
+
//functional_group_status; // enum (active + archive ??)
|
|
1520
|
+
created_at;
|
|
1521
|
+
updated_at;
|
|
1522
|
+
|
|
1523
|
+
primary_key = 'functional_group_id';
|
|
1524
|
+
|
|
1525
|
+
structure_scheme = {
|
|
1526
|
+
functional_group_id : 'integer | require',
|
|
1527
|
+
functional_group_name : 'string | max:90 | require',
|
|
1528
|
+
functional_group_description: 'string | max:250 | optional',
|
|
1529
|
+
project_id : 'integer | require',
|
|
1530
|
+
team_id : 'integer | require',
|
|
1531
|
+
parent_id : 'integer | optional',
|
|
1532
|
+
functional_group_status : 'integer | enum | require',
|
|
1533
|
+
created_at : 'timestamp | require',
|
|
1534
|
+
updated_at : 'timestamp | optional',
|
|
1535
|
+
};
|
|
1536
|
+
|
|
1537
|
+
available_enum_values = {
|
|
1538
|
+
functional_group_status: [ 'не идей. нужен ли тут статус' ]
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
/**
|
|
1543
|
+
*
|
|
1544
|
+
* @param {object|false|undefined} data
|
|
1545
|
+
*/
|
|
1546
|
+
constructor(data = false)
|
|
1547
|
+
{
|
|
1548
|
+
super();
|
|
1549
|
+
|
|
1550
|
+
if (data && is_object(data))
|
|
1551
|
+
{
|
|
1552
|
+
_.mapObject(data, (value, key) =>
|
|
1553
|
+
{
|
|
1554
|
+
if (this.hasOwnProperty(key))
|
|
1555
|
+
{
|
|
1556
|
+
this [ key ] = value;
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
return this;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
|
|
1565
|
+
/******************************************************************************************/
|
|
1566
|
+
/*********************************** general **********************************************/
|
|
1567
|
+
|
|
1568
|
+
/******************************************************************************************/
|
|
1569
|
+
|
|
1570
|
+
/**
|
|
1571
|
+
*
|
|
1572
|
+
* @version v.0.1 (07/07/2024)
|
|
1573
|
+
*/
|
|
1574
|
+
async create()
|
|
1575
|
+
{}
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
/**
|
|
1579
|
+
*
|
|
1580
|
+
* @version v.0.1 (07/07/2024)
|
|
1581
|
+
*/
|
|
1582
|
+
async update()
|
|
1583
|
+
{
|
|
1584
|
+
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
*
|
|
1590
|
+
* @version v.0.1 (07/07/2024)
|
|
1591
|
+
*/
|
|
1592
|
+
async delete()
|
|
1593
|
+
{
|
|
1594
|
+
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
*
|
|
1601
|
+
* @version v.0.2 (15/06/2024)
|
|
1602
|
+
*/
|
|
1603
|
+
class typeMilestone extends familyGeneralElement
|
|
1604
|
+
{
|
|
1605
|
+
milestone_id; // primary AI
|
|
1606
|
+
milestone_name;
|
|
1607
|
+
milestone_description;
|
|
1608
|
+
milestone_status; // enum
|
|
1609
|
+
milestone_start_date;
|
|
1610
|
+
milestone_end_date;
|
|
1611
|
+
team_id; // foreign key
|
|
1612
|
+
project_id; // foreign key
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
primary_key = 'milestone_id';
|
|
1616
|
+
|
|
1617
|
+
structure_scheme = {
|
|
1618
|
+
milestone_id : 'integer | require',
|
|
1619
|
+
milestone_name : 'string | require',
|
|
1620
|
+
milestone_description: 'string | optional',
|
|
1621
|
+
milestone_status : 'string | enum | require',
|
|
1622
|
+
company_id : 'integer | require',
|
|
1623
|
+
milestone_start_date : 'date | require',
|
|
1624
|
+
milestone_end_date : 'date | optional',
|
|
1625
|
+
project_id : 'integer | require',
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1628
|
+
available_enum_values = {
|
|
1629
|
+
milestone_status: [ 'ACTUAL', 'COMPLETED', 'PLANNED' ]
|
|
1630
|
+
};
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
*
|
|
1634
|
+
* @param {object|false|undefined} data
|
|
1635
|
+
*/
|
|
1636
|
+
constructor(data = false)
|
|
1637
|
+
{
|
|
1638
|
+
super();
|
|
1639
|
+
|
|
1640
|
+
if (data && is_object(data))
|
|
1641
|
+
{
|
|
1642
|
+
_.mapObject(data, (value, key) =>
|
|
1643
|
+
{
|
|
1644
|
+
if (this.hasOwnProperty(key))
|
|
1645
|
+
{
|
|
1646
|
+
this [ key ] = value;
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
return this;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
/******************************************************************************************/
|
|
1656
|
+
/*********************************** general **********************************************/
|
|
1657
|
+
|
|
1658
|
+
/******************************************************************************************/
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
*
|
|
1662
|
+
* @version v.0.1 (07/07/2024)
|
|
1663
|
+
*/
|
|
1664
|
+
async create()
|
|
1665
|
+
{}
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
/**
|
|
1669
|
+
*
|
|
1670
|
+
* @version v.0.1 (07/07/2024)
|
|
1671
|
+
*/
|
|
1672
|
+
async update()
|
|
1673
|
+
{
|
|
1674
|
+
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
/**
|
|
1679
|
+
*
|
|
1680
|
+
* @version v.0.1 (07/07/2024)
|
|
1681
|
+
*/
|
|
1682
|
+
async delete()
|
|
1683
|
+
{
|
|
1684
|
+
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
*
|
|
1692
|
+
* @version v.0.2 (15/06/2024)
|
|
1693
|
+
*/
|
|
1694
|
+
class typeProject extends familyGeneralElement
|
|
1695
|
+
{
|
|
1696
|
+
project_id; // primary
|
|
1697
|
+
project_name;
|
|
1698
|
+
project_description; // some comment
|
|
1699
|
+
project_status; // enum
|
|
1700
|
+
team_id; // foreign key + owner
|
|
1701
|
+
reference_document_ids; // IDS документов по функционалу (к примеру confluence)
|
|
1702
|
+
// хосты/домены будут отдельно храниться, их может быть множество
|
|
1703
|
+
|
|
1704
|
+
primary_key = 'project_id';
|
|
1705
|
+
|
|
1706
|
+
structure_scheme = {
|
|
1707
|
+
project_id : 'integer | require',
|
|
1708
|
+
project_name : 'string | require',
|
|
1709
|
+
project_description : 'string | optional',
|
|
1710
|
+
project_status : 'string | enum | require',
|
|
1711
|
+
company_id : 'integer | require',
|
|
1712
|
+
reference_document_ids: 'array | reference | optional',
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1715
|
+
available_enum_values = {
|
|
1716
|
+
project_status: [ 'OPEN', 'CLOSED', 'PLANNED' ]
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
/**
|
|
1721
|
+
*
|
|
1722
|
+
* @param {object|false|undefined} data
|
|
1723
|
+
*/
|
|
1724
|
+
constructor(data = false)
|
|
1725
|
+
{
|
|
1726
|
+
super();
|
|
1727
|
+
|
|
1728
|
+
if (data && is_object(data))
|
|
1729
|
+
{
|
|
1730
|
+
_.mapObject(data, (value, key) =>
|
|
1731
|
+
{
|
|
1732
|
+
if (this.hasOwnProperty(key))
|
|
1733
|
+
{
|
|
1734
|
+
this [ key ] = value;
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
return this;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
/**
|
|
1744
|
+
*
|
|
1745
|
+
* @version v.0.1 (02/07/2024)
|
|
1746
|
+
* @returns {array<typeProject>}
|
|
1747
|
+
* @param {number} count
|
|
1748
|
+
*/
|
|
1749
|
+
get_random_demo_data(count)
|
|
1750
|
+
{
|
|
1751
|
+
// @todo validations
|
|
1752
|
+
let response = [];
|
|
1753
|
+
|
|
1754
|
+
for (let i = 0; i < count; i++)
|
|
1755
|
+
{
|
|
1756
|
+
response.push(new MockDataTypeProject());
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
return response;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
/******************************************************************************************/
|
|
1765
|
+
/*********************************** general **********************************************/
|
|
1766
|
+
/******************************************************************************************/
|
|
1767
|
+
|
|
1768
|
+
/**
|
|
1769
|
+
*
|
|
1770
|
+
* @param {familyGeneralElement|object} payload
|
|
1771
|
+
* @param {typeFunctionCallback|object|false} callback
|
|
1772
|
+
*
|
|
1773
|
+
* @param {?function} callback.before
|
|
1774
|
+
* @param {?function} callback.success
|
|
1775
|
+
* @param {?function} callback.error
|
|
1776
|
+
* @param {?function} callback.final
|
|
1777
|
+
*
|
|
1778
|
+
* @version v.0.1 (26/01/2025)
|
|
1779
|
+
*/
|
|
1780
|
+
async create(payload, callback)
|
|
1781
|
+
{
|
|
1782
|
+
if (typeof callback?.before === 'function')
|
|
1783
|
+
{
|
|
1784
|
+
callback?.before({ payload });
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
payload = this.normalize_payload(payload);
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
/**
|
|
1791
|
+
* {Api} ApiService
|
|
1792
|
+
*/
|
|
1793
|
+
ApiService.project.create(payload).then((response) =>
|
|
1794
|
+
{
|
|
1795
|
+
if (typeof callback?.success === 'function')
|
|
1796
|
+
{
|
|
1797
|
+
callback?.success({ response, payload })
|
|
1798
|
+
}
|
|
1799
|
+
}).catch((error) =>
|
|
1800
|
+
{
|
|
1801
|
+
echo({ error });
|
|
1802
|
+
if (typeof callback?.error === 'function')
|
|
1803
|
+
{
|
|
1804
|
+
callback?.error({ error, payload })
|
|
1805
|
+
}
|
|
1806
|
+
}).finally((response) =>
|
|
1807
|
+
{
|
|
1808
|
+
if (typeof callback?.final === 'function')
|
|
1809
|
+
{
|
|
1810
|
+
callback?.final({ response, payload })
|
|
1811
|
+
}
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
/**
|
|
1817
|
+
*
|
|
1818
|
+
* @version v.0.1 (07/07/2024)
|
|
1819
|
+
*/
|
|
1820
|
+
async update()
|
|
1821
|
+
{
|
|
1822
|
+
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
/**
|
|
1827
|
+
*
|
|
1828
|
+
* @version v.0.1 (07/07/2024)
|
|
1829
|
+
*/
|
|
1830
|
+
async delete()
|
|
1831
|
+
{
|
|
1832
|
+
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
/******************************************************************************************/
|
|
1837
|
+
/**************************** работа с участниками проекта ********************************/
|
|
1838
|
+
/******************************************************************************************/
|
|
1839
|
+
|
|
1840
|
+
// member = user + role
|
|
1841
|
+
|
|
1842
|
+
member_add() {}
|
|
1843
|
+
|
|
1844
|
+
member_update() {}
|
|
1845
|
+
|
|
1846
|
+
member_delete() {}
|
|
1847
|
+
|
|
1848
|
+
member_get() {}
|
|
1849
|
+
|
|
1850
|
+
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* (идея) - у проекта должна быть тестовая документация
|
|
1854
|
+
*
|
|
1855
|
+
* @see https://vladislaveremeev.gitbook.io/qa_bible/testovaya-dokumentaciya-i-artefakty-test-deliverablestest-artifacts/vidy-testovoi-dokumentacii
|
|
1856
|
+
*
|
|
1857
|
+
* @version v.0.2 (07/07/2024)
|
|
1858
|
+
*/
|
|
1859
|
+
class typeProjectDocument extends familyGeneralElement
|
|
1860
|
+
{
|
|
1861
|
+
project_document_id;
|
|
1862
|
+
project_id;
|
|
1863
|
+
project_document_type;
|
|
1864
|
+
// где и как храним файлы?
|
|
1865
|
+
// nextcloud integration?
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
available_enum_values = {
|
|
1870
|
+
project_document_type: [ 'QUALITY_POLICY', 'TEST_POLICY', 'PROJECT_DESCRIPTION', 'TEST_PLAN', 'DOCUMENT' ],
|
|
1871
|
+
};
|
|
1872
|
+
|
|
1873
|
+
|
|
1874
|
+
/**
|
|
1875
|
+
*
|
|
1876
|
+
* @param {object|false|undefined} data
|
|
1877
|
+
*/
|
|
1878
|
+
constructor(data = false)
|
|
1879
|
+
{
|
|
1880
|
+
super();
|
|
1881
|
+
|
|
1882
|
+
if (data && is_object(data))
|
|
1883
|
+
{
|
|
1884
|
+
_.mapObject(data, (value, key) =>
|
|
1885
|
+
{
|
|
1886
|
+
if (this.hasOwnProperty(key))
|
|
1887
|
+
{
|
|
1888
|
+
this [ key ] = value;
|
|
1889
|
+
}
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
return this;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
/******************************************************************************************/
|
|
1898
|
+
/*********************************** general **********************************************/
|
|
1899
|
+
|
|
1900
|
+
/******************************************************************************************/
|
|
1901
|
+
|
|
1902
|
+
/**
|
|
1903
|
+
*
|
|
1904
|
+
* @version v.0.1 (07/07/2024)
|
|
1905
|
+
*/
|
|
1906
|
+
async create()
|
|
1907
|
+
{}
|
|
1908
|
+
|
|
1909
|
+
|
|
1910
|
+
/**
|
|
1911
|
+
*
|
|
1912
|
+
* @version v.0.1 (07/07/2024)
|
|
1913
|
+
*/
|
|
1914
|
+
async update()
|
|
1915
|
+
{
|
|
1916
|
+
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
|
|
1920
|
+
/**
|
|
1921
|
+
*
|
|
1922
|
+
* @version v.0.1 (07/07/2024)
|
|
1923
|
+
*/
|
|
1924
|
+
async delete()
|
|
1925
|
+
{
|
|
1926
|
+
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Тестовые аккаунты
|
|
1931
|
+
*
|
|
1932
|
+
* У каждого проекта свои коллекции
|
|
1933
|
+
* (идея)
|
|
1934
|
+
*
|
|
1935
|
+
* @version v.0.1 (30/06/2024)
|
|
1936
|
+
*/
|
|
1937
|
+
class typeProjectTestAccount extends familyGeneralElement
|
|
1938
|
+
{
|
|
1939
|
+
test_account_id;
|
|
1940
|
+
project_id;
|
|
1941
|
+
site;
|
|
1942
|
+
authentication_type;
|
|
1943
|
+
login;
|
|
1944
|
+
password; // как будем хранить?
|
|
1945
|
+
comment;
|
|
1946
|
+
|
|
1947
|
+
primary_key = 'test_account_id';
|
|
1948
|
+
|
|
1949
|
+
structure_scheme = {
|
|
1950
|
+
test_account_id : 'integer | require',
|
|
1951
|
+
project_id : 'integer | require',
|
|
1952
|
+
authentication_type: 'enum | require',
|
|
1953
|
+
site : 'string | require',
|
|
1954
|
+
login : 'string | require',
|
|
1955
|
+
password : 'string | optional',
|
|
1956
|
+
comment : 'string | optional',
|
|
1957
|
+
};
|
|
1958
|
+
|
|
1959
|
+
available_enum_values = {
|
|
1960
|
+
authentication_type: [ 'FORMS' ] // другие пока нет автоматизации не особо нужны
|
|
1961
|
+
};
|
|
1962
|
+
|
|
1963
|
+
/**
|
|
1964
|
+
*
|
|
1965
|
+
* @param {object|false|undefined} data
|
|
1966
|
+
*/
|
|
1967
|
+
constructor(data = false)
|
|
1968
|
+
{
|
|
1969
|
+
super();
|
|
1970
|
+
|
|
1971
|
+
if (data && is_object(data))
|
|
1972
|
+
{
|
|
1973
|
+
_.mapObject(data, (value, key) =>
|
|
1974
|
+
{
|
|
1975
|
+
if (this.hasOwnProperty(key))
|
|
1976
|
+
{
|
|
1977
|
+
this [ key ] = value;
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
return this;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Тестовые данные
|
|
1987
|
+
* Какая-то коллекция, созданная для тестирования и ввода
|
|
1988
|
+
*
|
|
1989
|
+
* У каждого проекта свои коллекции
|
|
1990
|
+
*
|
|
1991
|
+
* (идея)
|
|
1992
|
+
* @version v.0.1 (30/06/2024)
|
|
1993
|
+
*/
|
|
1994
|
+
class typeProjectTestData extends familyGeneralElement
|
|
1995
|
+
{
|
|
1996
|
+
// как храним? json или какие-то структуры? [key->value] ?
|
|
1997
|
+
test_data_id;
|
|
1998
|
+
project_id;
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
primary_key = 'test_data_id';
|
|
2002
|
+
|
|
2003
|
+
/**
|
|
2004
|
+
*
|
|
2005
|
+
* @param {object|false|undefined} data
|
|
2006
|
+
*/
|
|
2007
|
+
constructor(data = false)
|
|
2008
|
+
{
|
|
2009
|
+
super();
|
|
2010
|
+
|
|
2011
|
+
if (data && is_object(data))
|
|
2012
|
+
{
|
|
2013
|
+
_.mapObject(data, (value, key) =>
|
|
2014
|
+
{
|
|
2015
|
+
if (this.hasOwnProperty(key))
|
|
2016
|
+
{
|
|
2017
|
+
this [ key ] = value;
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
return this;
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Роли в проекте
|
|
2027
|
+
* @version v.0.1 (07/07/2024)
|
|
2028
|
+
*/
|
|
2029
|
+
class typeProjectUserRole extends familyGeneralElement
|
|
2030
|
+
{
|
|
2031
|
+
// строго определенный список
|
|
2032
|
+
// без возможности создания иных
|
|
2033
|
+
// если роль не указана - то ADMINISTRATOR
|
|
2034
|
+
|
|
2035
|
+
role_slug;
|
|
2036
|
+
role_description;
|
|
2037
|
+
project_id;
|
|
2038
|
+
user_id;
|
|
2039
|
+
|
|
2040
|
+
primary_key = 'role_slug';
|
|
2041
|
+
|
|
2042
|
+
structure_scheme = {
|
|
2043
|
+
role_slug : 'string | require',
|
|
2044
|
+
role_description: 'string | optional',
|
|
2045
|
+
project_id : 'integer | require',
|
|
2046
|
+
user_id : 'integer | require',
|
|
2047
|
+
};
|
|
2048
|
+
|
|
2049
|
+
available_enum_values = {
|
|
2050
|
+
role_slug: [ 'ROOT', 'ADMINISTRATOR', 'LEAD', 'QA_ENGINEER' ]
|
|
2051
|
+
// ?? Системные администраторы, Разработчики, Тестировщики
|
|
2052
|
+
};
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
/**
|
|
2056
|
+
*
|
|
2057
|
+
* @param {object|false|undefined} data
|
|
2058
|
+
*/
|
|
2059
|
+
constructor(data = false)
|
|
2060
|
+
{
|
|
2061
|
+
super();
|
|
2062
|
+
|
|
2063
|
+
if (data && is_object(data))
|
|
2064
|
+
{
|
|
2065
|
+
_.mapObject(data, (value, key) =>
|
|
2066
|
+
{
|
|
2067
|
+
if (this.hasOwnProperty(key))
|
|
2068
|
+
{
|
|
2069
|
+
this [ key ] = value;
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
return this;
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
/**
|
|
2079
|
+
* @version v.2.0 (07/07/2024)
|
|
2080
|
+
*/
|
|
2081
|
+
class typeTask extends familyGeneralElement
|
|
2082
|
+
{
|
|
2083
|
+
task_id;
|
|
2084
|
+
team_id; // foreign key
|
|
2085
|
+
task_performer_id; // foreign key // @todo переименовать с общепринятой практикой
|
|
2086
|
+
task_initiator_id; // foreign key // @todo переименовать с общепринятой практикой
|
|
2087
|
+
task_type; // enum => сделать тест, выполнить тест, итд (!не дублирует предмет задания - тут тип + действие)
|
|
2088
|
+
task_status; // enum
|
|
2089
|
+
project_id; // foreign key (денормализация) (а надо ли)
|
|
2090
|
+
task_subject_element_type; // предмет задания
|
|
2091
|
+
task_subject_id; // ID предмета задания (изначально его может не быть)
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
primary_key = 'task_id';
|
|
2095
|
+
|
|
2096
|
+
structure_scheme = {
|
|
2097
|
+
task_id : 'integer | require',
|
|
2098
|
+
team_id : 'integer | require',
|
|
2099
|
+
task_performer_id : 'integer | require',
|
|
2100
|
+
task_initiator_id : 'integer | require',
|
|
2101
|
+
task_type : 'string | enum | require',
|
|
2102
|
+
task_status : 'string | enum | require',
|
|
2103
|
+
project_id : 'integer | require',
|
|
2104
|
+
task_subject_element_type: 'string | enum | require',
|
|
2105
|
+
task_subject_id : 'integer | optional',
|
|
2106
|
+
};
|
|
2107
|
+
|
|
2108
|
+
available_enum_values = {
|
|
2109
|
+
task_status: [ 'OPEN', 'IN_PROGRESS', 'DONE', 'CANCELLED' ],
|
|
2110
|
+
// тут будет много, все надо перечислить, чтобы просто по каждой описать свой код
|
|
2111
|
+
// и не все комбинации action + element доступны и могут существовать
|
|
2112
|
+
task_type : [
|
|
2113
|
+
'CREATE_PROJECT_DOCUMENT',
|
|
2114
|
+
'CREATE_FUNCTIONAL',
|
|
2115
|
+
'CREATE_TESTCASE',
|
|
2116
|
+
'CREATE_TEST_RUN',
|
|
2117
|
+
'RUN_TEST_RUN'
|
|
2118
|
+
],
|
|
2119
|
+
task_subject_element_type: [
|
|
2120
|
+
'PROJECT',
|
|
2121
|
+
'PROJECT_DOCUMENT',
|
|
2122
|
+
'TEST_SUITE',
|
|
2123
|
+
'TEST_CASE',
|
|
2124
|
+
'TEST_RUN',
|
|
2125
|
+
'TEST_RESULT',
|
|
2126
|
+
],
|
|
2127
|
+
};
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
/**
|
|
2131
|
+
*
|
|
2132
|
+
* @param {object|false|undefined} data
|
|
2133
|
+
*/
|
|
2134
|
+
constructor(data = false)
|
|
2135
|
+
{
|
|
2136
|
+
super();
|
|
2137
|
+
|
|
2138
|
+
if (data && is_object(data))
|
|
2139
|
+
{
|
|
2140
|
+
_.mapObject(data, (value, key) =>
|
|
2141
|
+
{
|
|
2142
|
+
if (this.hasOwnProperty(key))
|
|
2143
|
+
{
|
|
2144
|
+
this [ key ] = value;
|
|
2145
|
+
}
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
return this;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/**
|
|
2154
|
+
* @version v.0.1 (23/06/2024)
|
|
2155
|
+
*/
|
|
2156
|
+
class typeTeam extends familyGeneralElement
|
|
2157
|
+
{
|
|
2158
|
+
team_id; //
|
|
2159
|
+
team_status; // enum
|
|
2160
|
+
team_type; // enum
|
|
2161
|
+
team_country_code; // (закон о перс данных и иные) как минимум статистика
|
|
2162
|
+
team_name;
|
|
2163
|
+
_team_price_id // foreign key (тариф)
|
|
2164
|
+
team_root_user_id; // foreign key
|
|
2165
|
+
created_at;
|
|
2166
|
+
updated_at;
|
|
2167
|
+
// тут где-то могут быть тарифы
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
primary_key = 'team_id';
|
|
2171
|
+
|
|
2172
|
+
structure_scheme = {
|
|
2173
|
+
team_id : 'integer | require',
|
|
2174
|
+
team_status : 'string | enum | require',
|
|
2175
|
+
team_type : 'string | enum | require',
|
|
2176
|
+
team_country_code: 'string | country_code | require',
|
|
2177
|
+
team_name : 'string | require',
|
|
2178
|
+
team_price_id : 'integer | require',
|
|
2179
|
+
team_root_user_id: 'integer | require',
|
|
2180
|
+
created_at : 'timestamp | require',
|
|
2181
|
+
updated_at : 'timestamp | optional',
|
|
2182
|
+
};
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
available_enum_values = {
|
|
2186
|
+
team_status: [ 'PENDING', 'APPROVED', 'BANNED', 'FROZEN', 'TRIAL' ],
|
|
2187
|
+
team_type : [ 'PERSONAL', 'ORGANIZATION', 'SCHOOL' ],
|
|
2188
|
+
};
|
|
2189
|
+
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
*
|
|
2193
|
+
* @param {object|false|undefined} data
|
|
2194
|
+
*/
|
|
2195
|
+
constructor(data = false)
|
|
2196
|
+
{
|
|
2197
|
+
super();
|
|
2198
|
+
|
|
2199
|
+
if (data && is_object(data))
|
|
2200
|
+
{
|
|
2201
|
+
_.mapObject(data, (value, key) =>
|
|
2202
|
+
{
|
|
2203
|
+
if (this.hasOwnProperty(key))
|
|
2204
|
+
{
|
|
2205
|
+
this [ key ] = value;
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
return this;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
/******************************************************************************************/
|
|
2215
|
+
/*********************************** general **********************************************/
|
|
2216
|
+
|
|
2217
|
+
/******************************************************************************************/
|
|
2218
|
+
|
|
2219
|
+
/**
|
|
2220
|
+
*
|
|
2221
|
+
* @version v.0.1 (07/07/2024)
|
|
2222
|
+
*/
|
|
2223
|
+
async create()
|
|
2224
|
+
{}
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
/******************************************************************************************/
|
|
2228
|
+
/*********************** работа с администраторами компании *******************************/
|
|
2229
|
+
|
|
2230
|
+
/******************************************************************************************/
|
|
2231
|
+
|
|
2232
|
+
adminstator_add() {}
|
|
2233
|
+
|
|
2234
|
+
adminstator_update() {}
|
|
2235
|
+
|
|
2236
|
+
adminstator_delete() {}
|
|
2237
|
+
|
|
2238
|
+
adminstators_get() {}
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
/******************************************************************************************/
|
|
2242
|
+
/************************* работа с сотрудниками компании *********************************/
|
|
2243
|
+
|
|
2244
|
+
/******************************************************************************************/
|
|
2245
|
+
|
|
2246
|
+
user_add() {}
|
|
2247
|
+
|
|
2248
|
+
user_update() {}
|
|
2249
|
+
|
|
2250
|
+
user_delete() {}
|
|
2251
|
+
|
|
2252
|
+
users_get() {}
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
/**
|
|
2256
|
+
* @version v.0.2 (11/11/2024)
|
|
2257
|
+
*/
|
|
2258
|
+
class typeTeamMember extends familyGeneralElement
|
|
2259
|
+
{
|
|
2260
|
+
team_member_id;
|
|
2261
|
+
team_id;
|
|
2262
|
+
user_id;
|
|
2263
|
+
team_member_status;
|
|
2264
|
+
member_role;
|
|
2265
|
+
created_at;
|
|
2266
|
+
updated_at;
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
primary_key = 'team_member_id';
|
|
2270
|
+
|
|
2271
|
+
structure_scheme = {
|
|
2272
|
+
team_member_id : 'integer | require',
|
|
2273
|
+
team_id : 'integer | require',
|
|
2274
|
+
user_id : 'integer | require',
|
|
2275
|
+
team_member_status: 'string | enum | require',
|
|
2276
|
+
member_role: 'string | enum | require',
|
|
2277
|
+
created_at : 'timestamp | require',
|
|
2278
|
+
updated_at : 'timestamp | optional',
|
|
2279
|
+
};
|
|
2280
|
+
|
|
2281
|
+
available_enum_values = {
|
|
2282
|
+
team_member_status: [ 'PENDING', 'ACCEPTED', 'BANNED', 'REJECTED' ],
|
|
2283
|
+
member_role : [ 'ROOT', 'ADMINISTRATOR', 'MEMBER' ]
|
|
2284
|
+
};
|
|
2285
|
+
|
|
2286
|
+
|
|
2287
|
+
/**
|
|
2288
|
+
*
|
|
2289
|
+
* @param {object|false|undefined} data
|
|
2290
|
+
*/
|
|
2291
|
+
constructor(data = false)
|
|
2292
|
+
{
|
|
2293
|
+
super();
|
|
2294
|
+
|
|
2295
|
+
if (data && is_object(data))
|
|
2296
|
+
{
|
|
2297
|
+
_.mapObject(data, (value, key) =>
|
|
2298
|
+
{
|
|
2299
|
+
if (this.hasOwnProperty(key))
|
|
2300
|
+
{
|
|
2301
|
+
this [ key ] = value;
|
|
2302
|
+
}
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
return this;
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
/**
|
|
2310
|
+
* Роль пользователя в команде
|
|
2311
|
+
* Должно стать часть team management
|
|
2312
|
+
*
|
|
2313
|
+
* Один пользователь может иметь много ролей (разработчик, тестировщик, ...)
|
|
2314
|
+
*
|
|
2315
|
+
* @version v.0.1 (07/07/2024)
|
|
2316
|
+
*/
|
|
2317
|
+
class typeTeamUserRole extends familyGeneralElement
|
|
2318
|
+
{
|
|
2319
|
+
// @todo - все не актуально, поменять
|
|
2320
|
+
role_slug;
|
|
2321
|
+
role_description;
|
|
2322
|
+
team_id;
|
|
2323
|
+
user_id;
|
|
2324
|
+
|
|
2325
|
+
primary_key = 'role_slug';
|
|
2326
|
+
|
|
2327
|
+
structure_scheme = {
|
|
2328
|
+
role_slug : 'string | require',
|
|
2329
|
+
role_description: 'string | optional',
|
|
2330
|
+
team_id : 'integer | require',
|
|
2331
|
+
user_id : 'integer | require',
|
|
2332
|
+
};
|
|
2333
|
+
|
|
2334
|
+
/*available_enum_values = {
|
|
2335
|
+
// эти роли вынесены
|
|
2336
|
+
role_slug: [ 'ROOT', 'ADMINISTRATOR', 'MEMBER' ]
|
|
2337
|
+
};
|
|
2338
|
+
*/
|
|
2339
|
+
|
|
2340
|
+
/**
|
|
2341
|
+
*
|
|
2342
|
+
* @param {object|false|undefined} data
|
|
2343
|
+
*/
|
|
2344
|
+
constructor(data = false)
|
|
2345
|
+
{
|
|
2346
|
+
super();
|
|
2347
|
+
|
|
2348
|
+
if (data && is_object(data))
|
|
2349
|
+
{
|
|
2350
|
+
_.mapObject(data, (value, key) =>
|
|
2351
|
+
{
|
|
2352
|
+
if (this.hasOwnProperty(key))
|
|
2353
|
+
{
|
|
2354
|
+
this [ key ] = value;
|
|
2355
|
+
}
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
return this;
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
/**
|
|
2364
|
+
*
|
|
2365
|
+
* @version v.0.2 (10/12/2024)
|
|
2366
|
+
*/
|
|
2367
|
+
class typeTestCase extends familyGeneralElement
|
|
2368
|
+
{
|
|
2369
|
+
test_case_id;
|
|
2370
|
+
test_suite_id; // foreign key
|
|
2371
|
+
project_id; // foreign key
|
|
2372
|
+
team_id; // foreign key // secure - access
|
|
2373
|
+
functional_id; // foreign key
|
|
2374
|
+
test_case_title; // text 90
|
|
2375
|
+
test_case_preconditions; // text (взято у рельсов)
|
|
2376
|
+
test_case_mission; // text (взято у рельсов)
|
|
2377
|
+
test_case_goals; // text (взято у рельсов)
|
|
2378
|
+
test_case_description; // text 250
|
|
2379
|
+
test_case_time_to_execute; // время выполнения (в секундах) (оценочное) (для планирования работ)
|
|
2380
|
+
test_case_complexity; // enum (для планирования работ)
|
|
2381
|
+
test_case_importance; // enum (для планирования работ)
|
|
2382
|
+
test_case_steps; // pseudo // foreign key - relations
|
|
2383
|
+
test_case_presteps; // pseudo // foreign key - relations
|
|
2384
|
+
_attachments; // typeAttachments - <relations>
|
|
2385
|
+
preconditions; // text
|
|
2386
|
+
excepted_result; // text // ?? <goals>
|
|
2387
|
+
created_at;
|
|
2388
|
+
updated_at;
|
|
2389
|
+
|
|
2390
|
+
|
|
2391
|
+
primary_key = 'test_case_id';
|
|
2392
|
+
|
|
2393
|
+
// @todo - довнести
|
|
2394
|
+
structure_scheme = {
|
|
2395
|
+
test_case_id : 'integer | require',
|
|
2396
|
+
test_suite_id : 'integer | require',
|
|
2397
|
+
project_id : 'integer | require',
|
|
2398
|
+
team_id : 'integer | require',
|
|
2399
|
+
functional_id : 'integer | optional',
|
|
2400
|
+
test_case_title : 'string | require',
|
|
2401
|
+
test_case_descriptions : 'string | require',
|
|
2402
|
+
test_case_time_to_execute: 'integer | optional',
|
|
2403
|
+
test_case_complexity : 'string | enum | optional',
|
|
2404
|
+
test_case_importance : 'string | enum | optional',
|
|
2405
|
+
created_at : 'timestamp | require',
|
|
2406
|
+
updated_at : 'timestamp | optional',
|
|
2407
|
+
};
|
|
2408
|
+
|
|
2409
|
+
available_enum_values = {
|
|
2410
|
+
test_case_complexity: [ 'LOW', 'NORMAL', 'HIGH' ],
|
|
2411
|
+
test_case_importance: [ 'LOW', 'NORMAL', 'HIGH' ],
|
|
2412
|
+
};
|
|
2413
|
+
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
*
|
|
2417
|
+
* @param {object|false|undefined} data
|
|
2418
|
+
*/
|
|
2419
|
+
constructor(data = false)
|
|
2420
|
+
{
|
|
2421
|
+
super();
|
|
2422
|
+
|
|
2423
|
+
if (data && is_object(data))
|
|
2424
|
+
{
|
|
2425
|
+
_.mapObject(data, (value, key) =>
|
|
2426
|
+
{
|
|
2427
|
+
if (this.hasOwnProperty(key))
|
|
2428
|
+
{
|
|
2429
|
+
this [ key ] = value;
|
|
2430
|
+
}
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
return this;
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
|
|
2438
|
+
/******************************************************************************************/
|
|
2439
|
+
/*********************************** general **********************************************/
|
|
2440
|
+
|
|
2441
|
+
/******************************************************************************************/
|
|
2442
|
+
|
|
2443
|
+
/**
|
|
2444
|
+
*
|
|
2445
|
+
* @version v.0.1 (07/07/2024)
|
|
2446
|
+
*/
|
|
2447
|
+
async create()
|
|
2448
|
+
{}
|
|
2449
|
+
|
|
2450
|
+
|
|
2451
|
+
/**
|
|
2452
|
+
*
|
|
2453
|
+
* @version v.0.1 (07/07/2024)
|
|
2454
|
+
*/
|
|
2455
|
+
async update()
|
|
2456
|
+
{
|
|
2457
|
+
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
|
|
2461
|
+
/**
|
|
2462
|
+
*
|
|
2463
|
+
* @version v.0.1 (07/07/2024)
|
|
2464
|
+
*/
|
|
2465
|
+
async delete()
|
|
2466
|
+
{
|
|
2467
|
+
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
/**
|
|
2474
|
+
*
|
|
2475
|
+
* @version v.0.1 (26/05/2024)
|
|
2476
|
+
*/
|
|
2477
|
+
class typeTestCaseStep extends familyGeneralElement
|
|
2478
|
+
{
|
|
2479
|
+
test_case_step_id;
|
|
2480
|
+
test_case_step_type;
|
|
2481
|
+
team_id; // foreign key
|
|
2482
|
+
test_case_id; // relations
|
|
2483
|
+
step_text;
|
|
2484
|
+
|
|
2485
|
+
primary_key = 'test_case_step_id';
|
|
2486
|
+
|
|
2487
|
+
available_enum_values = {
|
|
2488
|
+
test_case_step_type: [ 'TEST_CASE_STEP', 'TEST_CASE_PRESTEP' ],
|
|
2489
|
+
};
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
/**
|
|
2493
|
+
* Нужен ли этот тип?
|
|
2494
|
+
*
|
|
2495
|
+
* @version v.0.1 (26/05/2024)
|
|
2496
|
+
*/
|
|
2497
|
+
class typeTestPlan extends familyGeneralElement
|
|
2498
|
+
{
|
|
2499
|
+
|
|
2500
|
+
|
|
2501
|
+
/**
|
|
2502
|
+
*
|
|
2503
|
+
* @param {object|false|undefined} data
|
|
2504
|
+
*/
|
|
2505
|
+
constructor(data = false)
|
|
2506
|
+
{
|
|
2507
|
+
super();
|
|
2508
|
+
|
|
2509
|
+
if (data && is_object(data))
|
|
2510
|
+
{
|
|
2511
|
+
_.mapObject(data, (value, key) =>
|
|
2512
|
+
{
|
|
2513
|
+
if (this.hasOwnProperty(key))
|
|
2514
|
+
{
|
|
2515
|
+
this [ key ] = value;
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
return this;
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* Коллекция тестов для работы, она же parent для typeTestRunResult
|
|
2525
|
+
*
|
|
2526
|
+
* Содержит ссылки на коллекцию тест кейсов
|
|
2527
|
+
*
|
|
2528
|
+
* @version v.0.2 (21/01/2025)
|
|
2529
|
+
*/
|
|
2530
|
+
class typeTestRun extends familyGeneralElement
|
|
2531
|
+
{
|
|
2532
|
+
test_run_id;
|
|
2533
|
+
test_run_name;
|
|
2534
|
+
test_run_description;
|
|
2535
|
+
milestone_id; /// ??
|
|
2536
|
+
assigned_to;
|
|
2537
|
+
test_case_ids; // массив тестов на запуск
|
|
2538
|
+
test_run_status;
|
|
2539
|
+
test_case_summary_statistic; // массив [key->value] по статусам вложенных тест-кейсов для визуализации
|
|
2540
|
+
// typeTestRunResult.test_result_status : 'PASSED', 'FAILED', 'SKIPPED', 'BLOCKED', 'RETEST'
|
|
2541
|
+
|
|
2542
|
+
|
|
2543
|
+
created_at;
|
|
2544
|
+
updated_at;
|
|
2545
|
+
completed_at;
|
|
2546
|
+
|
|
2547
|
+
// логи запуска, окончания - отдельно
|
|
2548
|
+
primary_key = 'test_run_id';
|
|
2549
|
+
|
|
2550
|
+
available_enum_values = {
|
|
2551
|
+
test_run_status: [ 'PENDING', 'IN_PROGRESS', 'COMPLETED', 'CLOSED' ],
|
|
2552
|
+
};
|
|
2553
|
+
|
|
2554
|
+
/**
|
|
2555
|
+
*
|
|
2556
|
+
* @param {object|false|undefined} data
|
|
2557
|
+
*/
|
|
2558
|
+
constructor(data = false)
|
|
2559
|
+
{
|
|
2560
|
+
super();
|
|
2561
|
+
|
|
2562
|
+
if (data && is_object(data))
|
|
2563
|
+
{
|
|
2564
|
+
_.mapObject(data, (value, key) =>
|
|
2565
|
+
{
|
|
2566
|
+
if (this.hasOwnProperty(key))
|
|
2567
|
+
{
|
|
2568
|
+
this [ key ] = value;
|
|
2569
|
+
}
|
|
2570
|
+
});
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
return this;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
/**
|
|
2577
|
+
* 1 результат по каждому тест кейсу
|
|
2578
|
+
*
|
|
2579
|
+
* отчет смотрим по testRuns
|
|
2580
|
+
*
|
|
2581
|
+
* @version v.0.4 (10/12/2024)
|
|
2582
|
+
*/
|
|
2583
|
+
class typeTestRunResult extends familyGeneralElement
|
|
2584
|
+
{
|
|
2585
|
+
test_run_result_id;
|
|
2586
|
+
test_case_id;
|
|
2587
|
+
test_run_id;
|
|
2588
|
+
test_result_status;
|
|
2589
|
+
task_id; // надо ли?
|
|
2590
|
+
project_id;
|
|
2591
|
+
functional_id; // надо ли?
|
|
2592
|
+
milestone_id;
|
|
2593
|
+
elapsed_time; // фактическое время выполнения
|
|
2594
|
+
reference_defects_ids; // list of IDs in user bug tracker / include sentry ids
|
|
2595
|
+
|
|
2596
|
+
created_at;
|
|
2597
|
+
updated_at;
|
|
2598
|
+
completed_at;
|
|
2599
|
+
|
|
2600
|
+
|
|
2601
|
+
// тут нужен ещё контекст выполнения (банально список браузеров)
|
|
2602
|
+
|
|
2603
|
+
primary_key = 'test_run_result_id';
|
|
2604
|
+
|
|
2605
|
+
structure_scheme = {
|
|
2606
|
+
test_result_id : 'integer | require',
|
|
2607
|
+
test_case_id : 'integer | require',
|
|
2608
|
+
test_run_id : 'integer | require',
|
|
2609
|
+
test_result_status : 'string | enum | require',
|
|
2610
|
+
task_id : 'integer | require',
|
|
2611
|
+
project_id : 'integer | require',
|
|
2612
|
+
functional_id : 'integer | optional',
|
|
2613
|
+
milestone_id : 'integer | optional',
|
|
2614
|
+
test_run_result_to_execute: 'time | optional',
|
|
2615
|
+
reference_defects_ids : 'array | reference | optional',
|
|
2616
|
+
};
|
|
2617
|
+
|
|
2618
|
+
available_enum_values = {
|
|
2619
|
+
test_result_status: [ 'PASSED', 'FAILED', 'SKIPPED', 'BLOCKED', 'RETEST' ]
|
|
2620
|
+
};
|
|
2621
|
+
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
*
|
|
2625
|
+
* @param {object|false|undefined} data
|
|
2626
|
+
*/
|
|
2627
|
+
constructor(data = false)
|
|
2628
|
+
{
|
|
2629
|
+
super();
|
|
2630
|
+
|
|
2631
|
+
if (data && is_object(data))
|
|
2632
|
+
{
|
|
2633
|
+
_.mapObject(data, (value, key) =>
|
|
2634
|
+
{
|
|
2635
|
+
if (this.hasOwnProperty(key))
|
|
2636
|
+
{
|
|
2637
|
+
this [ key ] = value;
|
|
2638
|
+
}
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
return this;
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
/**
|
|
2646
|
+
* Структурная коллекция тестов
|
|
2647
|
+
*
|
|
2648
|
+
* @version v.0.1 (23/06/2024)
|
|
2649
|
+
*/
|
|
2650
|
+
class typeTestSuite extends familyGeneralElement
|
|
2651
|
+
{
|
|
2652
|
+
test_suite_id;
|
|
2653
|
+
project_id;
|
|
2654
|
+
functional_id;
|
|
2655
|
+
test_suite_name;
|
|
2656
|
+
test_suite_description;
|
|
2657
|
+
team_id;
|
|
2658
|
+
|
|
2659
|
+
primary_key = 'test_suite_id';
|
|
2660
|
+
|
|
2661
|
+
structure_scheme = {
|
|
2662
|
+
test_suite_id : 'integer | require',
|
|
2663
|
+
project_id : 'integer | require',
|
|
2664
|
+
functional_id : 'integer | optional',
|
|
2665
|
+
test_suite_name : 'string | protected | require',
|
|
2666
|
+
test_suite_description: 'string | require',
|
|
2667
|
+
team_id : 'integer | require',
|
|
2668
|
+
};
|
|
2669
|
+
|
|
2670
|
+
|
|
2671
|
+
/**
|
|
2672
|
+
*
|
|
2673
|
+
* @param {object|false|undefined} data
|
|
2674
|
+
*/
|
|
2675
|
+
constructor(data = false)
|
|
2676
|
+
{
|
|
2677
|
+
super();
|
|
2678
|
+
|
|
2679
|
+
if (data && is_object(data))
|
|
2680
|
+
{
|
|
2681
|
+
_.mapObject(data, (value, key) =>
|
|
2682
|
+
{
|
|
2683
|
+
if (this.hasOwnProperty(key))
|
|
2684
|
+
{
|
|
2685
|
+
this [ key ] = value;
|
|
2686
|
+
}
|
|
2687
|
+
});
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
return this;
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
/******************************************************************************************/
|
|
2695
|
+
/*********************************** general **********************************************/
|
|
2696
|
+
|
|
2697
|
+
/******************************************************************************************/
|
|
2698
|
+
|
|
2699
|
+
/**
|
|
2700
|
+
*
|
|
2701
|
+
* @version v.0.1 (07/07/2024)
|
|
2702
|
+
*/
|
|
2703
|
+
async create()
|
|
2704
|
+
{}
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
/**
|
|
2708
|
+
*
|
|
2709
|
+
* @version v.0.1 (07/07/2024)
|
|
2710
|
+
*/
|
|
2711
|
+
async update()
|
|
2712
|
+
{
|
|
2713
|
+
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
|
|
2717
|
+
/**
|
|
2718
|
+
*
|
|
2719
|
+
* @version v.0.1 (07/07/2024)
|
|
2720
|
+
*/
|
|
2721
|
+
async delete()
|
|
2722
|
+
{
|
|
2723
|
+
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
/**
|
|
2730
|
+
* @version v.0.1 (23/06/2024)
|
|
2731
|
+
*/
|
|
2732
|
+
class typeUser extends familyGeneralElement
|
|
2733
|
+
{
|
|
2734
|
+
user_id;
|
|
2735
|
+
country;
|
|
2736
|
+
user_name;
|
|
2737
|
+
user_password; // не доступно на фронте
|
|
2738
|
+
user_status;
|
|
2739
|
+
user_email;
|
|
2740
|
+
user_phone;
|
|
2741
|
+
|
|
2742
|
+
primary_key = 'user_id';
|
|
2743
|
+
|
|
2744
|
+
structure_scheme = {
|
|
2745
|
+
user_id : 'integer | require',
|
|
2746
|
+
country : 'string | enum | require',
|
|
2747
|
+
user_name : 'string | require',
|
|
2748
|
+
user_password : 'string | protected | require',
|
|
2749
|
+
user_status : 'string | enum| require',
|
|
2750
|
+
user_email : 'string | email | require',
|
|
2751
|
+
user_phone_number: 'string | phone_number | optional',
|
|
2752
|
+
};
|
|
2753
|
+
|
|
2754
|
+
available_enum_values = {
|
|
2755
|
+
user_status: [ 'PENDING', 'APPROVED', 'BANNED', 'FROZEN', 'BLOCKED' ]
|
|
2756
|
+
};
|
|
2757
|
+
|
|
2758
|
+
|
|
2759
|
+
/**
|
|
2760
|
+
*
|
|
2761
|
+
* @param {object|false|undefined} data
|
|
2762
|
+
*/
|
|
2763
|
+
constructor(data = false)
|
|
2764
|
+
{
|
|
2765
|
+
super();
|
|
2766
|
+
|
|
2767
|
+
if (data && is_object(data))
|
|
2768
|
+
{
|
|
2769
|
+
_.mapObject(data, (value, key) =>
|
|
2770
|
+
{
|
|
2771
|
+
if (this.hasOwnProperty(key))
|
|
2772
|
+
{
|
|
2773
|
+
this [ key ] = value;
|
|
2774
|
+
}
|
|
2775
|
+
});
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
return this;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
/**
|
|
2782
|
+
* базовый тип для всех служебных типов
|
|
2783
|
+
* @version v.0.1 (26/05/2024)
|
|
2784
|
+
*/
|
|
2785
|
+
class familyService
|
|
2786
|
+
{
|
|
2787
|
+
//
|
|
2788
|
+
}
|
|
2789
|
+
/**
|
|
2790
|
+
*
|
|
2791
|
+
* @version v.0.1 (26/01/2025)
|
|
2792
|
+
*/
|
|
2793
|
+
class typeFOR extends familyService
|
|
2794
|
+
{
|
|
2795
|
+
filter;
|
|
2796
|
+
object;
|
|
2797
|
+
response;
|
|
2798
|
+
|
|
2799
|
+
/**
|
|
2800
|
+
*
|
|
2801
|
+
* @version v.0.1 (26/01/2025)
|
|
2802
|
+
* @param data
|
|
2803
|
+
* @returns {typeFOR}
|
|
2804
|
+
*/
|
|
2805
|
+
constructor(data = false)
|
|
2806
|
+
{
|
|
2807
|
+
super();
|
|
2808
|
+
|
|
2809
|
+
if (data && typeof data === 'object')
|
|
2810
|
+
{
|
|
2811
|
+
_.mapObject(data, (value, key) =>
|
|
2812
|
+
{
|
|
2813
|
+
if (this.hasOwnProperty(key))
|
|
2814
|
+
{
|
|
2815
|
+
this [ key ] = value;
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
return this;
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Описание стандартного колбека типового для методов
|
|
2825
|
+
*
|
|
2826
|
+
* @version v.0.1 (26/05/2024)
|
|
2827
|
+
*/
|
|
2828
|
+
class typeFunctionCallback extends familyService
|
|
2829
|
+
{
|
|
2830
|
+
before;
|
|
2831
|
+
success;
|
|
2832
|
+
error;
|
|
2833
|
+
final;
|
|
2834
|
+
destroy;
|
|
2835
|
+
|
|
2836
|
+
|
|
2837
|
+
/**
|
|
2838
|
+
*
|
|
2839
|
+
* @version v.0.1 (26/05/2024)
|
|
2840
|
+
* @param {object|false} data
|
|
2841
|
+
* @return {typeFunctionCallback}
|
|
2842
|
+
*/
|
|
2843
|
+
constructor(data = false)
|
|
2844
|
+
{
|
|
2845
|
+
super();
|
|
2846
|
+
|
|
2847
|
+
if (data && typeof data === 'object')
|
|
2848
|
+
{
|
|
2849
|
+
_.mapObject(data, (value, key) =>
|
|
2850
|
+
{
|
|
2851
|
+
if (this.hasOwnProperty(key))
|
|
2852
|
+
{
|
|
2853
|
+
this [ key ] = value;
|
|
2854
|
+
}
|
|
2855
|
+
});
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2858
|
+
return this;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
/**
|
|
2862
|
+
* Уведомления
|
|
2863
|
+
* Как будто это абстрактный интерфейс
|
|
2864
|
+
* А внутри уже разные настроенные пользователем методы
|
|
2865
|
+
*
|
|
2866
|
+
*/
|
|
2867
|
+
class typeNotification extends familyService
|
|
2868
|
+
{
|
|
2869
|
+
|
|
2870
|
+
// пока не понятно
|
|
2871
|
+
|
|
2872
|
+
/**
|
|
2873
|
+
*
|
|
2874
|
+
* @param {object|false|undefined} data
|
|
2875
|
+
*/
|
|
2876
|
+
constructor(data = false)
|
|
2877
|
+
{
|
|
2878
|
+
super();
|
|
2879
|
+
|
|
2880
|
+
if (data && is_object(data))
|
|
2881
|
+
{
|
|
2882
|
+
_.mapObject(data, (value, key) =>
|
|
2883
|
+
{
|
|
2884
|
+
if (this.hasOwnProperty(key))
|
|
2885
|
+
{
|
|
2886
|
+
this [ key ] = value;
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
return this;
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
/**
|
|
2895
|
+
*
|
|
2896
|
+
* @version v.0.1 (02/07/2024)
|
|
2897
|
+
*/
|
|
2898
|
+
class abstractMockData
|
|
2899
|
+
{
|
|
2900
|
+
mock_data_type = 'correct';
|
|
2901
|
+
|
|
2902
|
+
constructor(mock_data_type = 'correct')
|
|
2903
|
+
{
|
|
2904
|
+
this.mock_data_type = mock_data_type;
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
/**
|
|
2909
|
+
* @version v.0.1 (02/07/2024)
|
|
2910
|
+
*/
|
|
2911
|
+
class MockDataTypeProject extends abstractMockData
|
|
2912
|
+
{
|
|
2913
|
+
correct = [ {
|
|
2914
|
+
project_id : 11,
|
|
2915
|
+
project_name : 'Demo Project #11',
|
|
2916
|
+
project_description: 'Description – это мета тег, представляющий собой описание. Он находится под заголовком (title) и ссылкой на сайт. Целью тега является вывод страницы в топ. Это в свою очередь привлечет больше целевых пользователей. Можно составить description самостоятельно.',
|
|
2917
|
+
project_status : 'OPEN',
|
|
2918
|
+
team_id : 0,
|
|
2919
|
+
}, {
|
|
2920
|
+
project_id : 22,
|
|
2921
|
+
project_name : 'Demo Project #22',
|
|
2922
|
+
project_description: 'Однако есть риск допустить ошибку. Если использовать не те фразы и длину предложения, то успеха не достичь.',
|
|
2923
|
+
project_status : 'OPEN',
|
|
2924
|
+
team_id : 0,
|
|
2925
|
+
}, {
|
|
2926
|
+
project_id : 33,
|
|
2927
|
+
project_name : 'Perspective project № 1',
|
|
2928
|
+
project_description: 'Чтобы сделать онлайн контент план, нужно ввести тематику блога. На основании данных генератор подберет темы.',
|
|
2929
|
+
project_status : 'PLANNED',
|
|
2930
|
+
team_id : 0,
|
|
2931
|
+
}, {
|
|
2932
|
+
project_id : 44,
|
|
2933
|
+
project_name : 'Perspective project № 2',
|
|
2934
|
+
project_description: 'Укажите любые детали вашей веб-страницы: вставьте сам текст или укажите тему/ключевые слова;',
|
|
2935
|
+
project_status : 'PLANNED',
|
|
2936
|
+
team_id : 0,
|
|
2937
|
+
}, {
|
|
2938
|
+
project_id : 55,
|
|
2939
|
+
project_name : 'Closed project № 1',
|
|
2940
|
+
project_description: 'Протестируйте бесплатно',
|
|
2941
|
+
project_status : 'PLANNED',
|
|
2942
|
+
team_id : 0,
|
|
2943
|
+
}, {
|
|
2944
|
+
project_id : 66,
|
|
2945
|
+
project_name : 'Closed project № 1',
|
|
2946
|
+
project_description: 'Создать теги онлайн можно бесплатно. Для этого вставьте всю информацию в специальную форму. Генератор быстро сформирует результат. Вы сможете убедиться в его скорости и эффективности. Создатель тегов – быстрый и удобный сервис.',
|
|
2947
|
+
project_status : 'PLANNED',
|
|
2948
|
+
team_id : 0,
|
|
2949
|
+
},
|
|
2950
|
+
];
|
|
2951
|
+
|
|
2952
|
+
static last_index = {
|
|
2953
|
+
correct: 0
|
|
2954
|
+
};
|
|
2955
|
+
|
|
2956
|
+
|
|
2957
|
+
/**
|
|
2958
|
+
*
|
|
2959
|
+
* @version v.0.1 (02/07/2024)
|
|
2960
|
+
* @param mock_data_type
|
|
2961
|
+
*/
|
|
2962
|
+
constructor(mock_data_type = 'correct')
|
|
2963
|
+
{
|
|
2964
|
+
super();
|
|
2965
|
+
|
|
2966
|
+
let response = false;
|
|
2967
|
+
if (mock_data_type === 'correct')
|
|
2968
|
+
{
|
|
2969
|
+
if (is_object(this.correct[ MockDataTypeProject.last_index[ mock_data_type ] ]))
|
|
2970
|
+
{
|
|
2971
|
+
response = this.correct[ MockDataTypeProject.last_index[ mock_data_type ] ];
|
|
2972
|
+
}
|
|
2973
|
+
else
|
|
2974
|
+
{
|
|
2975
|
+
MockDataTypeProject.last_index[ mock_data_type ] = 0;
|
|
2976
|
+
response = this.correct[ MockDataTypeProject.last_index[ mock_data_type ] ];
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
if (count(this[ mock_data_type ]) >= MockDataTypeProject.last_index[ mock_data_type ])
|
|
2981
|
+
{
|
|
2982
|
+
MockDataTypeProject.last_index[ mock_data_type ]++;
|
|
2983
|
+
}
|
|
2984
|
+
else
|
|
2985
|
+
{
|
|
2986
|
+
MockDataTypeProject.last_index[ mock_data_type ] = 0;
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
return response;
|
|
2990
|
+
}
|
|
2991
|
+
}
|