feed-common 1.10.5 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1458 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
2
+ import { describe, test, expect } from 'vitest';
3
+ import {
4
+ checkRuleAlwaysness,
5
+ checkRuleDeadlocks,
6
+ checkRuleDuplication,
7
+ compareMappings,
8
+ compareRules,
9
+ detectProfileChange,
10
+ getOperatorCounterpart,
11
+ hasRules,
12
+ sanitizeUploadProfile,
13
+ sortMappings,
14
+ } from '../src/utils/profile.js';
15
+ import { ProductUploadMapSource, ProductUploadMapping, ProductUploadProfile } from '../src/types/profile.types.js';
16
+
17
+ describe('Rules duplication', () => {
18
+ test('no match', () => {
19
+ const rulesList = [
20
+ { id: '1', attribute: 'attr1', operator: 'eq', value: '1' },
21
+ { id: '2', attribute: 'attr1', operator: 'eq', value: '2' },
22
+ ];
23
+
24
+ expect(checkRuleDuplication(rulesList)).toEqual([]);
25
+ });
26
+
27
+ test('match', () => {
28
+ const rulesList = [
29
+ { id: '1', attribute: 'attr1', operator: 'eq', value: '2' },
30
+ { id: '2', attribute: 'attr1', operator: 'eq', value: '2' },
31
+ ];
32
+
33
+ expect(checkRuleDuplication(rulesList)).toEqual(['1', '2']);
34
+ });
35
+ });
36
+
37
+ describe('Alwaysness', () => {
38
+ test('no match #1', () => {
39
+ const rulesList = [
40
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
41
+ { id: '2', attribute: 'attr1', operator: 'equals', value: '2' },
42
+ ];
43
+
44
+ expect(checkRuleAlwaysness(rulesList)).toEqual([]);
45
+ });
46
+
47
+ test('no match #2', () => {
48
+ const rulesList = [
49
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
50
+ { id: '2', attribute: 'attr1', operator: 'notEquals', value: '2' },
51
+ ];
52
+
53
+ expect(checkRuleAlwaysness(rulesList)).toEqual([]);
54
+ });
55
+
56
+ test('match', () => {
57
+ const rulesList = [
58
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
59
+ { id: '2', attribute: 'attr1', operator: 'equals', value: '3' },
60
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '5' },
61
+ { id: '4', attribute: 'attr1', operator: 'notEquals', value: '1' },
62
+ ];
63
+
64
+ expect(checkRuleAlwaysness(rulesList)).toEqual(['1', '4']);
65
+ });
66
+
67
+ test('error', () => {
68
+ const rulesList = [
69
+ { id: '1', attribute: 'attr1', operator: 'equalss', value: '1' },
70
+ { id: '2', attribute: 'attr1', operator: 'equals', value: '3' },
71
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '5' },
72
+ { id: '4', attribute: 'attr1', operator: 'notEquals', value: '1' },
73
+ ];
74
+
75
+ expect(() => checkRuleAlwaysness(rulesList)).toThrowError();
76
+ });
77
+ });
78
+
79
+ describe('Rules deadlock', () => {
80
+ test('match #1', () => {
81
+ const rulesList = [
82
+ { ruleItems: [{ id: '1', attribute: 'attr1', operator: 'equals', value: '1' }] },
83
+ { ruleItems: [{ id: '5', attribute: 'attr1', operator: 'notEquals', value: '1' }] },
84
+ ];
85
+
86
+ expect(checkRuleDeadlocks(rulesList)).toEqual(['1', '5']);
87
+ });
88
+
89
+ test('match #2', () => {
90
+ const rulesList = [
91
+ {
92
+ ruleItems: [
93
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
94
+ { id: '2', attribute: 'attr3', operator: 'equals', value: '1' },
95
+ ],
96
+ },
97
+ {
98
+ ruleItems: [
99
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '1' },
100
+ { id: '4', attribute: 'attr2', operator: 'notEquals', value: '1' },
101
+ ],
102
+ },
103
+ {
104
+ ruleItems: [
105
+ { id: '5', attribute: 'attr2', operator: 'equals', value: '1' },
106
+ { id: '6', attribute: 'attr3', operator: 'notEquals', value: '1' },
107
+ ],
108
+ },
109
+ ];
110
+
111
+ expect(checkRuleDeadlocks(rulesList)).toEqual(['1', '3', '2', '6', '4', '5']);
112
+ });
113
+
114
+ test('match #3', () => {
115
+ const rulesList = [
116
+ {
117
+ ruleItems: [
118
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
119
+ { id: '2', attribute: 'attr3', operator: 'equals', value: '1' },
120
+ { id: '7', attribute: 'attr4', operator: 'equals', value: '1' },
121
+ ],
122
+ },
123
+ {
124
+ ruleItems: [
125
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '1' },
126
+ { id: '4', attribute: 'attr2', operator: 'notEquals', value: '1' },
127
+ ],
128
+ },
129
+ {
130
+ ruleItems: [
131
+ { id: '5', attribute: 'attr2', operator: 'equals', value: '1' },
132
+ { id: '6', attribute: 'attr3', operator: 'notEquals', value: '1' },
133
+ ],
134
+ },
135
+ ];
136
+
137
+ expect(checkRuleDeadlocks(rulesList)).toEqual(['1', '3', '2', '6', '4', '5']);
138
+ });
139
+
140
+ test('match #4', () => {
141
+ const rulesList = [
142
+ {
143
+ ruleItems: [
144
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
145
+ { id: '2', attribute: 'attr3', operator: 'equals', value: '1' },
146
+ { id: '7', attribute: 'attr4', operator: 'equals', value: '1' },
147
+ ],
148
+ },
149
+ {
150
+ ruleItems: [
151
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '1' },
152
+ { id: '4', attribute: 'attr2', operator: 'notEquals', value: '1' },
153
+ { id: '8', attribute: 'attr5', operator: 'notEquals', value: '1' },
154
+ ],
155
+ },
156
+ {
157
+ ruleItems: [
158
+ { id: '5', attribute: 'attr2', operator: 'equals', value: '1' },
159
+ { id: '6', attribute: 'attr3', operator: 'notEquals', value: '1' },
160
+ ],
161
+ },
162
+ ];
163
+
164
+ expect(checkRuleDeadlocks(rulesList)).toEqual(['1', '3', '2', '6', '4', '5']);
165
+ });
166
+
167
+ test('no match', () => {
168
+ const rulesList = [
169
+ {
170
+ ruleItems: [
171
+ { id: '1', attribute: 'attr1', operator: 'equals', value: '1' },
172
+ { id: '2', attribute: 'attr3', operator: 'equals', value: '1' },
173
+ { id: '7', attribute: 'attr4', operator: 'equals', value: '1' },
174
+ ],
175
+ },
176
+ {
177
+ ruleItems: [
178
+ { id: '3', attribute: 'attr1', operator: 'notEquals', value: '1' },
179
+ { id: '4', attribute: 'attr2', operator: 'notEquals', value: '1' },
180
+ { id: '8', attribute: 'attr5', operator: 'notEquals', value: '1' },
181
+ ],
182
+ },
183
+ {
184
+ ruleItems: [
185
+ { id: '5', attribute: 'attr2', operator: 'equals', value: '1' },
186
+ { id: '6', attribute: 'attr3', operator: 'notEquals', value: '1' },
187
+ { id: '9', attribute: 'attr7', operator: 'notEquals', value: '1' },
188
+ ],
189
+ },
190
+ ];
191
+
192
+ expect(checkRuleDeadlocks(rulesList)).toEqual([]);
193
+ });
194
+ });
195
+
196
+ describe('Operators counterpart', () => {
197
+ test('Test', () => {
198
+ expect(getOperatorCounterpart('equals')).toBe('notEquals');
199
+ expect(getOperatorCounterpart('notEquals')).toBe('equals');
200
+ expect(getOperatorCounterpart('contains')).toBe('notContains');
201
+ expect(getOperatorCounterpart('notContains')).toBe('contains');
202
+ expect(getOperatorCounterpart('startsWith')).toBe('notStartsWith');
203
+ expect(getOperatorCounterpart('notStartsWith')).toBe('startsWith');
204
+ expect(getOperatorCounterpart('endsWith')).toBe('notEndsWith');
205
+ expect(getOperatorCounterpart('notEndsWith')).toBe('endsWith');
206
+ expect(getOperatorCounterpart('in')).toBe('notIn');
207
+ expect(getOperatorCounterpart('notIn')).toBe('in');
208
+ expect(getOperatorCounterpart('greater')).toBe('less');
209
+ expect(getOperatorCounterpart('less')).toBe('greater');
210
+ expect(getOperatorCounterpart('greaterOrEqual')).toBe('lessOrEqual');
211
+ expect(getOperatorCounterpart('lessOrEqual')).toBe('greaterOrEqual');
212
+ // @ts-ignore
213
+ expect(() => getOperatorCounterpart('unknown')).toThrowError();
214
+ });
215
+ });
216
+
217
+ describe('Mappings sort', () => {
218
+ test('Test', () => {
219
+ expect(
220
+ [
221
+ {} as ProductUploadMapping,
222
+ { attribute: 'contentLanguage' } as ProductUploadMapping,
223
+ { attribute: 'targetCountry' } as ProductUploadMapping,
224
+ { attribute: 'title' } as ProductUploadMapping,
225
+ { attribute: 'adult' } as ProductUploadMapping,
226
+ { attribute: 'ageGroup' } as ProductUploadMapping,
227
+ { attribute: 'availability' } as ProductUploadMapping,
228
+ { attribute: 'title' } as ProductUploadMapping,
229
+ ]
230
+ .sort(sortMappings)
231
+ .map(m => m.attribute)
232
+ ).toEqual([
233
+ 'availability',
234
+ 'contentLanguage',
235
+ 'targetCountry',
236
+ 'adult',
237
+ 'ageGroup',
238
+ 'title',
239
+ 'title',
240
+ undefined,
241
+ ]);
242
+ });
243
+ });
244
+
245
+ describe('Has rules', () => {
246
+ test('match', () => {
247
+ expect(
248
+ hasRules({
249
+ sections: [{ ruleItems: [] }, { ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] }],
250
+ })
251
+ ).toBe(true);
252
+ });
253
+
254
+ test('no match', () => {
255
+ expect(hasRules({ sections: [{ ruleItems: [] }, { ruleItems: [] }] })).toBe(false);
256
+ });
257
+ });
258
+
259
+ describe('Compare rules', () => {
260
+ test('match #1', () => {
261
+ expect(
262
+ compareRules(
263
+ { sections: [{ ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] }] },
264
+ { sections: [{ ruleItems: [{ id: '2', attribute: 'a', operator: 'b', value: 'c' }] }] }
265
+ )
266
+ ).toBe(true);
267
+ });
268
+
269
+ test('match #2', () => {
270
+ expect(
271
+ compareRules(
272
+ {
273
+ sections: [
274
+ { ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] },
275
+ { ruleItems: [] },
276
+ ],
277
+ },
278
+ { sections: [{ ruleItems: [{ id: '2', attribute: 'a', operator: 'b', value: 'c' }] }] }
279
+ )
280
+ ).toBe(true);
281
+ });
282
+
283
+ test('match #3', () => {
284
+ expect(
285
+ compareRules(
286
+ {
287
+ sections: [
288
+ { ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] },
289
+ { ruleItems: [] },
290
+ ],
291
+ },
292
+ {
293
+ sections: [
294
+ { ruleItems: [{ id: '2', attribute: 'a', operator: 'b', value: 'c' }] },
295
+ { ruleItems: [] },
296
+ ],
297
+ }
298
+ )
299
+ ).toBe(true);
300
+ });
301
+
302
+ test('match #4', () => {
303
+ expect(
304
+ compareRules(
305
+ {
306
+ sections: [{ ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] }],
307
+ },
308
+ {
309
+ sections: [
310
+ { ruleItems: [{ id: '2', attribute: 'a', operator: 'b', value: 'c' }] },
311
+ { ruleItems: [] },
312
+ ],
313
+ }
314
+ )
315
+ ).toBe(true);
316
+ });
317
+
318
+ test('match #5', () => {
319
+ expect(
320
+ compareRules(
321
+ {
322
+ sections: [
323
+ { ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }] },
324
+ { ruleItems: [{ id: '2', attribute: 'b', operator: 'c', value: 'd' }] },
325
+ { ruleItems: [] },
326
+ ],
327
+ },
328
+ {
329
+ sections: [
330
+ { ruleItems: [{ id: '3', attribute: 'a', operator: 'b', value: 'c' }] },
331
+ { ruleItems: [{ id: '4', attribute: 'b', operator: 'c', value: 'd' }] },
332
+ ],
333
+ }
334
+ )
335
+ ).toBe(true);
336
+ });
337
+
338
+ test('match #5', () => {
339
+ expect(
340
+ compareRules(
341
+ {
342
+ sections: [
343
+ {
344
+ ruleItems: [
345
+ { id: '1', attribute: 'a', operator: 'b', value: ['c', 'd'] },
346
+ { id: '5', attribute: 'c', operator: 'd', value: 'e' },
347
+ ],
348
+ },
349
+ { ruleItems: [{ id: '2', attribute: 'b', operator: 'c', value: 'd' }] },
350
+ { ruleItems: [] },
351
+ ],
352
+ },
353
+ {
354
+ sections: [
355
+ {
356
+ ruleItems: [
357
+ { id: '3', attribute: 'a', operator: 'b', value: ['d', 'c'] },
358
+ { id: '6', attribute: 'c', operator: 'd', value: 'e' },
359
+ ],
360
+ },
361
+ { ruleItems: [{ id: '4', attribute: 'b', operator: 'c', value: 'd' }] },
362
+ ],
363
+ }
364
+ )
365
+ ).toBe(true);
366
+ });
367
+
368
+ test('no match #1', () => {
369
+ expect(
370
+ compareRules(
371
+ {
372
+ sections: [
373
+ {
374
+ ruleItems: [{ id: '1', attribute: 'a', operator: 'b', value: 'c' }],
375
+ },
376
+ {
377
+ ruleItems: [
378
+ { id: '2', attribute: 'b', operator: 'c', value: 'd' },
379
+ { id: '5', attribute: 'c', operator: 'd', value: 'e' },
380
+ ],
381
+ },
382
+ { ruleItems: [] },
383
+ ],
384
+ },
385
+ {
386
+ sections: [
387
+ {
388
+ ruleItems: [
389
+ { id: '3', attribute: 'a', operator: 'b', value: 'c' },
390
+ { id: '6', attribute: 'c', operator: 'd', value: 'e' },
391
+ ],
392
+ },
393
+ { ruleItems: [{ id: '4', attribute: 'b', operator: 'c', value: 'd' }] },
394
+ ],
395
+ }
396
+ )
397
+ ).toBe(false);
398
+ });
399
+
400
+ test('no match #2', () => {
401
+ expect(
402
+ compareRules(
403
+ {
404
+ sections: [
405
+ {
406
+ ruleItems: [
407
+ { id: '1', attribute: 'a', operator: 'b', value: 'c' },
408
+ { id: '5', attribute: 'c', operator: 'd', value: 'e' },
409
+ ],
410
+ },
411
+ {
412
+ ruleItems: [
413
+ { id: '2', attribute: 'b', operator: 'c', value: 'd' },
414
+ { id: '8', attribute: 'c', operator: 'd', value: 'e' },
415
+ ],
416
+ },
417
+ { ruleItems: [] },
418
+ ],
419
+ },
420
+ {
421
+ sections: [
422
+ {
423
+ ruleItems: [
424
+ { id: '3', attribute: 'a', operator: 'b', value: 'c' },
425
+ { id: '6', attribute: 'c', operator: 'd', value: 'e' },
426
+ ],
427
+ },
428
+ { ruleItems: [{ id: '4', attribute: 'b', operator: 'c', value: 'd' }] },
429
+ ],
430
+ }
431
+ )
432
+ ).toBe(false);
433
+ });
434
+
435
+ test('no match #3', () => {
436
+ expect(
437
+ compareRules(
438
+ {
439
+ sections: [
440
+ {
441
+ ruleItems: [
442
+ { id: '1', attribute: 'a', operator: 'b', value: 'c' },
443
+ { id: '5', attribute: 'c', operator: 'd', value: 'e' },
444
+ ],
445
+ },
446
+ {
447
+ ruleItems: [{ id: '2', attribute: 'b', operator: 'c', value: 'd' }],
448
+ },
449
+ { ruleItems: [{ id: '10', attribute: 'a', operator: 'b', value: 'c' }] },
450
+ ],
451
+ },
452
+ {
453
+ sections: [
454
+ {
455
+ ruleItems: [
456
+ { id: '3', attribute: 'a', operator: 'b', value: 'c' },
457
+ { id: '6', attribute: 'c', operator: 'd', value: 'e' },
458
+ ],
459
+ },
460
+ { ruleItems: [{ id: '4', attribute: 'b', operator: 'c', value: 'd' }] },
461
+ ],
462
+ }
463
+ )
464
+ ).toBe(false);
465
+ });
466
+ });
467
+
468
+ describe('Compare mappings', () => {
469
+ test('match #1', () => {
470
+ const mappingsA = [
471
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
472
+ ] as ProductUploadMapping[];
473
+
474
+ const mappingsB = [
475
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
476
+ ] as ProductUploadMapping[];
477
+
478
+ expect(compareMappings(mappingsA, mappingsB)).toBe(true);
479
+ });
480
+
481
+ test('match #2', () => {
482
+ const mappingsA = [
483
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
484
+ {
485
+ attribute: 'contentLanguage',
486
+ value: 'uk',
487
+ rules: { sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }] },
488
+ },
489
+ ] as ProductUploadMapping[];
490
+
491
+ const mappingsB = [
492
+ {
493
+ attribute: 'contentLanguage',
494
+ value: 'uk',
495
+ rules: { sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }] },
496
+ },
497
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
498
+ ] as ProductUploadMapping[];
499
+
500
+ expect(compareMappings(mappingsA, mappingsB)).toBe(true);
501
+ });
502
+
503
+ test('match #3', () => {
504
+ const mappingsA = [
505
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
506
+ {
507
+ attribute: 'contentLanguage',
508
+ value: 'uk',
509
+ rules: {
510
+ sections: [
511
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
512
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
513
+ ],
514
+ },
515
+ },
516
+ ] as ProductUploadMapping[];
517
+
518
+ const mappingsB = [
519
+ {
520
+ attribute: 'contentLanguage',
521
+ value: 'uk',
522
+ rules: {
523
+ sections: [
524
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
525
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
526
+ ],
527
+ },
528
+ },
529
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
530
+ ] as ProductUploadMapping[];
531
+
532
+ expect(compareMappings(mappingsA, mappingsB)).toBe(true);
533
+ });
534
+
535
+ test('no match #1', () => {
536
+ const mappingsA = [
537
+ { attribute: 'contentLanguage', value: 'uk', rules: { sections: [{ ruleItems: [] }] } },
538
+ ] as ProductUploadMapping[];
539
+
540
+ const mappingsB = [
541
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
542
+ ] as ProductUploadMapping[];
543
+
544
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
545
+ });
546
+
547
+ test('no match #2', () => {
548
+ const mappingsA = [
549
+ { attribute: 'title', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
550
+ ] as ProductUploadMapping[];
551
+
552
+ const mappingsB = [
553
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
554
+ ] as ProductUploadMapping[];
555
+
556
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
557
+ });
558
+
559
+ test('no match #3', () => {
560
+ const mappingsA = [
561
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
562
+ {
563
+ attribute: 'contentLanguage',
564
+ value: 'uk',
565
+ rules: {
566
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] }],
567
+ },
568
+ },
569
+ ] as ProductUploadMapping[];
570
+
571
+ const mappingsB = [
572
+ {
573
+ attribute: 'contentLanguage',
574
+ value: 'uk',
575
+ rules: { sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }] },
576
+ },
577
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
578
+ ] as ProductUploadMapping[];
579
+
580
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
581
+ });
582
+
583
+ test('no match #4', () => {
584
+ const mappingsA = [
585
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
586
+ {
587
+ attribute: 'contentLanguage',
588
+ value: 'uk',
589
+ rules: {
590
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'notIn', value: ['title1'] }] }],
591
+ },
592
+ },
593
+ ] as ProductUploadMapping[];
594
+
595
+ const mappingsB = [
596
+ {
597
+ attribute: 'contentLanguage',
598
+ value: 'uk',
599
+ rules: { sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }] },
600
+ },
601
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
602
+ ] as ProductUploadMapping[];
603
+
604
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
605
+ });
606
+
607
+ test('no match #5', () => {
608
+ const mappingsA = [
609
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
610
+ {
611
+ attribute: 'contentLanguage',
612
+ value: 'uk',
613
+ rules: {
614
+ sections: [
615
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
616
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
617
+ ],
618
+ },
619
+ },
620
+ ] as ProductUploadMapping[];
621
+
622
+ const mappingsB = [
623
+ {
624
+ attribute: 'contentLanguage',
625
+ value: 'uk',
626
+ rules: {
627
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
628
+ },
629
+ },
630
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
631
+ ] as ProductUploadMapping[];
632
+
633
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
634
+ });
635
+
636
+ test('no match #6', () => {
637
+ const mappingsA = [
638
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
639
+ {
640
+ attribute: 'contentLanguage',
641
+ value: 'uk',
642
+ rules: {
643
+ sections: [
644
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
645
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
646
+ ],
647
+ },
648
+ },
649
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
650
+ ] as ProductUploadMapping[];
651
+
652
+ const mappingsB = [
653
+ {
654
+ attribute: 'contentLanguage',
655
+ value: 'uk',
656
+ rules: {
657
+ sections: [
658
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
659
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
660
+ ],
661
+ },
662
+ },
663
+ { attribute: 'contentLanguage', value: 'en', rules: { sections: [{ ruleItems: [] }] } },
664
+ ] as ProductUploadMapping[];
665
+
666
+ expect(compareMappings(mappingsA, mappingsB)).toBe(false);
667
+ });
668
+ });
669
+
670
+ describe('Detect profile change', () => {
671
+ test('No changes', () => {
672
+ const profileA = {
673
+ id: '1',
674
+ profileIdTemplate: '1',
675
+ name: 'profileA',
676
+ rules: {
677
+ sections: [
678
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
679
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
680
+ ],
681
+ },
682
+ mappings: [
683
+ {
684
+ attribute: 'contentLanguage',
685
+ value: 'en',
686
+ rules: {
687
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
688
+ },
689
+ },
690
+ {
691
+ attribute: 'ageGroup',
692
+ value: 'newborn',
693
+ rules: {
694
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
695
+ },
696
+ },
697
+ ],
698
+ } as ProductUploadProfile;
699
+
700
+ const profileB = {
701
+ id: '1',
702
+ profileIdTemplate: '1',
703
+ name: 'profileA',
704
+ rules: {
705
+ sections: [
706
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
707
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
708
+ ],
709
+ },
710
+ mappings: [
711
+ {
712
+ attribute: 'contentLanguage',
713
+ value: 'en',
714
+ rules: {
715
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
716
+ },
717
+ },
718
+ {
719
+ attribute: 'ageGroup',
720
+ value: 'newborn',
721
+ rules: {
722
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
723
+ },
724
+ },
725
+ ],
726
+ } as ProductUploadProfile;
727
+
728
+ expect(detectProfileChange(profileA, profileB)).toEqual({
729
+ name: false,
730
+ rules: false,
731
+ mappings: false,
732
+ id: false,
733
+ });
734
+ });
735
+
736
+ test('Name change', () => {
737
+ const profileA = {
738
+ id: '1',
739
+ profileIdTemplate: '1',
740
+ name: 'profileA',
741
+ rules: {
742
+ sections: [
743
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
744
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
745
+ ],
746
+ },
747
+ mappings: [
748
+ {
749
+ attribute: 'contentLanguage',
750
+ value: 'en',
751
+ rules: {
752
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
753
+ },
754
+ },
755
+ {
756
+ attribute: 'ageGroup',
757
+ value: 'newborn',
758
+ rules: {
759
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
760
+ },
761
+ },
762
+ ],
763
+ } as ProductUploadProfile;
764
+
765
+ const profileB = {
766
+ id: '1',
767
+ profileIdTemplate: '1',
768
+ name: 'profileB',
769
+ rules: {
770
+ sections: [
771
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
772
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
773
+ ],
774
+ },
775
+ mappings: [
776
+ {
777
+ attribute: 'contentLanguage',
778
+ value: 'en',
779
+ rules: {
780
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
781
+ },
782
+ },
783
+ {
784
+ attribute: 'ageGroup',
785
+ value: 'newborn',
786
+ rules: {
787
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
788
+ },
789
+ },
790
+ ],
791
+ } as ProductUploadProfile;
792
+
793
+ expect(detectProfileChange(profileA, profileB)).toEqual({
794
+ name: true,
795
+ rules: false,
796
+ mappings: false,
797
+ id: false,
798
+ });
799
+ });
800
+
801
+ test('Mappings change #1', () => {
802
+ const profileA = {
803
+ id: '1',
804
+ profileIdTemplate: '1',
805
+ name: 'profileA',
806
+ rules: {
807
+ sections: [
808
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
809
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
810
+ ],
811
+ },
812
+ mappings: [
813
+ {
814
+ attribute: 'contentLanguage',
815
+ value: 'en',
816
+ rules: {
817
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
818
+ },
819
+ },
820
+ {
821
+ attribute: 'ageGroup',
822
+ value: 'newborn',
823
+ rules: {
824
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
825
+ },
826
+ },
827
+ ],
828
+ } as ProductUploadProfile;
829
+
830
+ const profileB = {
831
+ id: '1',
832
+ profileIdTemplate: '1',
833
+ name: 'profileA',
834
+ rules: {
835
+ sections: [
836
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
837
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
838
+ ],
839
+ },
840
+ mappings: [
841
+ {
842
+ attribute: 'contentLanguage',
843
+ value: 'en',
844
+ rules: {
845
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
846
+ },
847
+ },
848
+ {
849
+ attribute: 'brand',
850
+ value: 'Voxhall',
851
+ rules: {
852
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
853
+ },
854
+ },
855
+ ],
856
+ } as ProductUploadProfile;
857
+
858
+ expect(detectProfileChange(profileA, profileB)).toEqual({
859
+ name: false,
860
+ rules: false,
861
+ mappings: true,
862
+ id: false,
863
+ });
864
+ });
865
+
866
+ test('Mappings change #2', () => {
867
+ const profileA = {
868
+ id: '1',
869
+ profileIdTemplate: '1',
870
+ name: 'profileA',
871
+ rules: {
872
+ sections: [
873
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
874
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
875
+ ],
876
+ },
877
+ mappings: [
878
+ {
879
+ attribute: 'contentLanguage',
880
+ value: 'en',
881
+ rules: {
882
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
883
+ },
884
+ },
885
+ {
886
+ attribute: 'ageGroup',
887
+ value: 'newborn',
888
+ rules: {
889
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
890
+ },
891
+ },
892
+ ],
893
+ } as ProductUploadProfile;
894
+
895
+ const profileB = {
896
+ id: '1',
897
+ profileIdTemplate: '1',
898
+ name: 'profileA',
899
+ rules: {
900
+ sections: [
901
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
902
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
903
+ ],
904
+ },
905
+ mappings: [
906
+ {
907
+ attribute: 'contentLanguage',
908
+ value: 'en',
909
+ rules: {
910
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
911
+ },
912
+ },
913
+ {
914
+ attribute: 'ageGroup',
915
+ value: 'newborn',
916
+ rules: {
917
+ sections: [
918
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
919
+ ],
920
+ },
921
+ },
922
+ ],
923
+ } as ProductUploadProfile;
924
+
925
+ expect(detectProfileChange(profileA, profileB)).toEqual({
926
+ name: false,
927
+ rules: false,
928
+ mappings: true,
929
+ id: false,
930
+ });
931
+ });
932
+
933
+ test('ID section change #1', () => {
934
+ const profileA = {
935
+ id: '1',
936
+ profileIdTemplate: '1',
937
+ name: 'profileA',
938
+ rules: {
939
+ sections: [
940
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
941
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
942
+ ],
943
+ },
944
+ mappings: [
945
+ {
946
+ attribute: 'contentLanguage',
947
+ value: 'en',
948
+ rules: {
949
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
950
+ },
951
+ },
952
+ {
953
+ attribute: 'ageGroup',
954
+ value: 'newborn',
955
+ rules: {
956
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
957
+ },
958
+ },
959
+ ],
960
+ } as ProductUploadProfile;
961
+
962
+ const profileB = {
963
+ id: '1',
964
+ profileIdTemplate: '1',
965
+ name: 'profileA',
966
+ rules: {
967
+ sections: [
968
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
969
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
970
+ ],
971
+ },
972
+ mappings: [
973
+ {
974
+ attribute: 'gender',
975
+ value: 'male',
976
+ rules: {
977
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
978
+ },
979
+ },
980
+ {
981
+ attribute: 'ageGroup',
982
+ value: 'newborn',
983
+ rules: {
984
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
985
+ },
986
+ },
987
+ ],
988
+ } as ProductUploadProfile;
989
+
990
+ expect(detectProfileChange(profileA, profileB)).toEqual({
991
+ name: false,
992
+ rules: false,
993
+ mappings: true,
994
+ id: true,
995
+ });
996
+ });
997
+
998
+ test('ID section change #2', () => {
999
+ const profileA = {
1000
+ id: '1',
1001
+ profileIdTemplate: '1',
1002
+ name: 'profileA',
1003
+ rules: {
1004
+ sections: [
1005
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1006
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1007
+ ],
1008
+ },
1009
+ mappings: [
1010
+ {
1011
+ attribute: 'contentLanguage',
1012
+ value: 'en',
1013
+ rules: {
1014
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1015
+ },
1016
+ },
1017
+ {
1018
+ attribute: 'ageGroup',
1019
+ value: 'newborn',
1020
+ rules: {
1021
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1022
+ },
1023
+ },
1024
+ ],
1025
+ } as ProductUploadProfile;
1026
+
1027
+ const profileB = {
1028
+ id: '1',
1029
+ profileIdTemplate: '1',
1030
+ name: 'profileA',
1031
+ rules: {
1032
+ sections: [
1033
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1034
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1035
+ ],
1036
+ },
1037
+ mappings: [
1038
+ {
1039
+ attribute: 'contentLanguage',
1040
+ value: 'en',
1041
+ rules: {
1042
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title2'] }] }],
1043
+ },
1044
+ },
1045
+ {
1046
+ attribute: 'ageGroup',
1047
+ value: 'newborn',
1048
+ rules: {
1049
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1050
+ },
1051
+ },
1052
+ ],
1053
+ } as ProductUploadProfile;
1054
+
1055
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1056
+ name: false,
1057
+ rules: false,
1058
+ mappings: false,
1059
+ id: true,
1060
+ });
1061
+ });
1062
+
1063
+ test('Mapping change #1', () => {
1064
+ const profileA = {
1065
+ id: '1',
1066
+ profileIdTemplate: '1',
1067
+ name: 'profileA',
1068
+ rules: {
1069
+ sections: [
1070
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1071
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1072
+ ],
1073
+ },
1074
+ mappings: [
1075
+ {
1076
+ attribute: 'contentLanguage',
1077
+ value: 'en',
1078
+ rules: {
1079
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1080
+ },
1081
+ },
1082
+ {
1083
+ attribute: 'ageGroup',
1084
+ value: 'newborn',
1085
+ rules: {
1086
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1087
+ },
1088
+ },
1089
+ ],
1090
+ } as ProductUploadProfile;
1091
+
1092
+ const profileB = {
1093
+ id: '1',
1094
+ profileIdTemplate: '1',
1095
+ name: 'profileA',
1096
+ rules: {
1097
+ sections: [
1098
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1099
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1100
+ ],
1101
+ },
1102
+ mappings: [
1103
+ {
1104
+ attribute: 'contentLanguage',
1105
+ value: 'en',
1106
+ rules: {
1107
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1108
+ },
1109
+ },
1110
+ {
1111
+ attribute: 'ageGroup',
1112
+ value: 'newborn',
1113
+ rules: {
1114
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1115
+ },
1116
+ },
1117
+ {
1118
+ attribute: 'adult',
1119
+ value: true,
1120
+ rules: {
1121
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1122
+ },
1123
+ },
1124
+ ],
1125
+ } as ProductUploadProfile;
1126
+
1127
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1128
+ name: false,
1129
+ rules: false,
1130
+ mappings: true,
1131
+ id: false,
1132
+ });
1133
+ });
1134
+
1135
+ test('Mapping change #2', () => {
1136
+ const profileA = {
1137
+ id: '1',
1138
+ profileIdTemplate: '1',
1139
+ name: 'profileA',
1140
+ rules: {
1141
+ sections: [
1142
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1143
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1144
+ ],
1145
+ },
1146
+ mappings: [
1147
+ {
1148
+ attribute: 'contentLanguage',
1149
+ value: 'en',
1150
+ rules: {
1151
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1152
+ },
1153
+ },
1154
+ {
1155
+ attribute: 'ageGroup',
1156
+ value: 'newborn',
1157
+ rules: {
1158
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1159
+ },
1160
+ },
1161
+ ],
1162
+ } as ProductUploadProfile;
1163
+
1164
+ const profileB = {
1165
+ id: '1',
1166
+ profileIdTemplate: '1',
1167
+ name: 'profileA',
1168
+ rules: {
1169
+ sections: [
1170
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1171
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1172
+ ],
1173
+ },
1174
+ mappings: [
1175
+ {
1176
+ attribute: 'contentLanguage',
1177
+ value: 'en',
1178
+ rules: {
1179
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1180
+ },
1181
+ },
1182
+ {
1183
+ attribute: 'adult',
1184
+ value: true,
1185
+ rules: {
1186
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1187
+ },
1188
+ },
1189
+ ],
1190
+ } as ProductUploadProfile;
1191
+
1192
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1193
+ name: false,
1194
+ rules: false,
1195
+ mappings: true,
1196
+ id: false,
1197
+ });
1198
+ });
1199
+
1200
+ test('Mappings change #3', () => {
1201
+ const profileA = {
1202
+ id: '1',
1203
+ profileIdTemplate: '1',
1204
+ name: 'profileA',
1205
+ rules: {
1206
+ sections: [
1207
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1208
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1209
+ ],
1210
+ },
1211
+ mappings: [
1212
+ {
1213
+ attribute: 'contentLanguage',
1214
+ value: 'en',
1215
+ rules: {
1216
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1217
+ },
1218
+ },
1219
+ {
1220
+ attribute: 'ageGroup',
1221
+ value: 'newborn',
1222
+ rules: {
1223
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1224
+ },
1225
+ },
1226
+ ],
1227
+ } as ProductUploadProfile;
1228
+
1229
+ const profileB = {
1230
+ id: '1',
1231
+ profileIdTemplate: '1',
1232
+ name: 'profileA',
1233
+ rules: {
1234
+ sections: [
1235
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1236
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1237
+ ],
1238
+ },
1239
+ mappings: [
1240
+ {
1241
+ attribute: 'contentLanguage',
1242
+ value: 'en',
1243
+ rules: {
1244
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1245
+ },
1246
+ },
1247
+ {
1248
+ attribute: 'ageGroup',
1249
+ value: 'newborn',
1250
+ rules: {
1251
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: 'title1' }] }],
1252
+ },
1253
+ },
1254
+ ],
1255
+ } as ProductUploadProfile;
1256
+
1257
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1258
+ name: false,
1259
+ rules: false,
1260
+ mappings: true,
1261
+ id: false,
1262
+ });
1263
+ });
1264
+
1265
+ test('Rules change', () => {
1266
+ const profileA = {
1267
+ id: '1',
1268
+ profileIdTemplate: '1',
1269
+ name: 'profileA',
1270
+ rules: {
1271
+ sections: [
1272
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1273
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1274
+ ],
1275
+ },
1276
+ mappings: [
1277
+ {
1278
+ attribute: 'contentLanguage',
1279
+ value: 'en',
1280
+ rules: {
1281
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1282
+ },
1283
+ },
1284
+ {
1285
+ attribute: 'ageGroup',
1286
+ value: 'newborn',
1287
+ rules: {
1288
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1289
+ },
1290
+ },
1291
+ ],
1292
+ } as ProductUploadProfile;
1293
+
1294
+ const profileB = {
1295
+ id: '1',
1296
+ profileIdTemplate: '1',
1297
+ name: 'profileA',
1298
+ rules: {
1299
+ sections: [
1300
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1301
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 101 }] },
1302
+ ],
1303
+ },
1304
+ mappings: [
1305
+ {
1306
+ attribute: 'contentLanguage',
1307
+ value: 'en',
1308
+ rules: {
1309
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1310
+ },
1311
+ },
1312
+ {
1313
+ attribute: 'ageGroup',
1314
+ value: 'newborn',
1315
+ rules: {
1316
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1317
+ },
1318
+ },
1319
+ ],
1320
+ } as ProductUploadProfile;
1321
+
1322
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1323
+ name: false,
1324
+ rules: true,
1325
+ mappings: false,
1326
+ id: false,
1327
+ });
1328
+ });
1329
+
1330
+ test('All changed', () => {
1331
+ const profileA = {
1332
+ id: '1',
1333
+ profileIdTemplate: '1',
1334
+ name: 'profileA',
1335
+ rules: {
1336
+ sections: [
1337
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1338
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1339
+ ],
1340
+ },
1341
+ mappings: [
1342
+ {
1343
+ attribute: 'contentLanguage',
1344
+ value: 'en',
1345
+ rules: {
1346
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1347
+ },
1348
+ },
1349
+ {
1350
+ attribute: 'ageGroup',
1351
+ value: 'newborn',
1352
+ rules: {
1353
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1354
+ },
1355
+ },
1356
+ ],
1357
+ } as ProductUploadProfile;
1358
+
1359
+ const profileB = {
1360
+ id: '1',
1361
+ profileIdTemplate: '1',
1362
+ name: 'profileB',
1363
+ rules: {
1364
+ sections: [
1365
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1366
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 101 }] },
1367
+ ],
1368
+ },
1369
+ mappings: [
1370
+ {
1371
+ attribute: 'contentLanguage',
1372
+ value: 'en',
1373
+ rules: {
1374
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title2'] }] }],
1375
+ },
1376
+ },
1377
+ {
1378
+ attribute: 'ageGroup',
1379
+ value: 'newborn',
1380
+ rules: {
1381
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title2'] }] }],
1382
+ },
1383
+ },
1384
+ ],
1385
+ } as ProductUploadProfile;
1386
+
1387
+ expect(detectProfileChange(profileA, profileB)).toEqual({
1388
+ name: true,
1389
+ rules: true,
1390
+ mappings: true,
1391
+ id: true,
1392
+ });
1393
+ });
1394
+ });
1395
+
1396
+ describe('Sanitize upload profile', () => {
1397
+ test('Test #1', () => {
1398
+ expect(
1399
+ sanitizeUploadProfile({
1400
+ id: '1',
1401
+ profileIdTemplate: '1',
1402
+ name: 'profileA',
1403
+ rules: {
1404
+ sections: [
1405
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1406
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1407
+ { ruleItems: [] },
1408
+ ],
1409
+ },
1410
+ mappings: [
1411
+ {
1412
+ attribute: 'contentLanguage',
1413
+ value: 'en',
1414
+ rules: {
1415
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1416
+ },
1417
+ },
1418
+ {
1419
+ attribute: 'ageGroup',
1420
+ value: 'newborn',
1421
+ rules: {
1422
+ sections: [
1423
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] },
1424
+ { ruleItems: [] },
1425
+ ],
1426
+ },
1427
+ },
1428
+ ],
1429
+ } as ProductUploadProfile)
1430
+ ).toEqual({
1431
+ id: '1',
1432
+ profileIdTemplate: '1',
1433
+ name: 'profileA',
1434
+ rules: {
1435
+ sections: [
1436
+ { ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1', 'title2'] }] },
1437
+ { ruleItems: [{ attribute: 'price', operator: 'less', value: 100 }] },
1438
+ ],
1439
+ },
1440
+ mappings: [
1441
+ {
1442
+ attribute: 'contentLanguage',
1443
+ value: 'en',
1444
+ rules: {
1445
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1446
+ },
1447
+ },
1448
+ {
1449
+ attribute: 'ageGroup',
1450
+ value: 'newborn',
1451
+ rules: {
1452
+ sections: [{ ruleItems: [{ attribute: 'title', operator: 'in', value: ['title1'] }] }],
1453
+ },
1454
+ },
1455
+ ],
1456
+ });
1457
+ });
1458
+ });