@nyaruka/temba-components 0.130.5 → 0.131.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/CHANGELOG.md +3 -20
- package/dist/temba-components.js +65 -64
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +1 -0
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +254 -65
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +195 -2
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/select/Omnibox.js +4 -0
- package/out-tsc/src/form/select/Omnibox.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +373 -8
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/src/flow/nodes/split_by_random.ts +1 -0
- package/src/flow/nodes/wait_for_response.ts +327 -72
- package/src/form/ArrayEditor.ts +260 -2
- package/src/form/select/Omnibox.ts +3 -0
- package/test/nodes/wait_for_response.test.ts +426 -8
|
@@ -49,14 +49,25 @@ describe('wait_for_response node config', () => {
|
|
|
49
49
|
},
|
|
50
50
|
result_name: 'response',
|
|
51
51
|
categories: [
|
|
52
|
+
{
|
|
53
|
+
uuid: 'all-responses-cat-1',
|
|
54
|
+
name: 'All Responses',
|
|
55
|
+
exit_uuid: 'all-responses-exit-1'
|
|
56
|
+
},
|
|
52
57
|
{
|
|
53
58
|
uuid: 'timeout-cat-1',
|
|
54
59
|
name: 'No Response',
|
|
55
60
|
exit_uuid: 'timeout-exit-1'
|
|
56
61
|
}
|
|
57
|
-
]
|
|
62
|
+
],
|
|
63
|
+
cases: [],
|
|
64
|
+
operand: '@input.text',
|
|
65
|
+
default_category_uuid: 'all-responses-cat-1'
|
|
58
66
|
},
|
|
59
|
-
exits: [
|
|
67
|
+
exits: [
|
|
68
|
+
{ uuid: 'all-responses-exit-1', destination_uuid: null },
|
|
69
|
+
{ uuid: 'timeout-exit-1', destination_uuid: null }
|
|
70
|
+
]
|
|
60
71
|
} as Node,
|
|
61
72
|
{ type: 'wait_for_response' },
|
|
62
73
|
'basic-wait'
|
|
@@ -79,14 +90,25 @@ describe('wait_for_response node config', () => {
|
|
|
79
90
|
},
|
|
80
91
|
result_name: 'user_input',
|
|
81
92
|
categories: [
|
|
93
|
+
{
|
|
94
|
+
uuid: 'all-responses-cat-2',
|
|
95
|
+
name: 'All Responses',
|
|
96
|
+
exit_uuid: 'all-responses-exit-2'
|
|
97
|
+
},
|
|
82
98
|
{
|
|
83
99
|
uuid: 'timeout-cat-2',
|
|
84
100
|
name: 'No Response',
|
|
85
101
|
exit_uuid: 'timeout-exit-2'
|
|
86
102
|
}
|
|
87
|
-
]
|
|
103
|
+
],
|
|
104
|
+
cases: [],
|
|
105
|
+
operand: '@input.text',
|
|
106
|
+
default_category_uuid: 'all-responses-cat-2'
|
|
88
107
|
},
|
|
89
|
-
exits: [
|
|
108
|
+
exits: [
|
|
109
|
+
{ uuid: 'all-responses-exit-2', destination_uuid: null },
|
|
110
|
+
{ uuid: 'timeout-exit-2', destination_uuid: null }
|
|
111
|
+
]
|
|
90
112
|
} as Node,
|
|
91
113
|
{ type: 'wait_for_response' },
|
|
92
114
|
'custom-result-name'
|
|
@@ -109,14 +131,25 @@ describe('wait_for_response node config', () => {
|
|
|
109
131
|
},
|
|
110
132
|
result_name: 'quick_response',
|
|
111
133
|
categories: [
|
|
134
|
+
{
|
|
135
|
+
uuid: 'all-responses-cat-3',
|
|
136
|
+
name: 'All Responses',
|
|
137
|
+
exit_uuid: 'all-responses-exit-3'
|
|
138
|
+
},
|
|
112
139
|
{
|
|
113
140
|
uuid: 'timeout-cat-3',
|
|
114
141
|
name: 'No Response',
|
|
115
142
|
exit_uuid: 'timeout-exit-3'
|
|
116
143
|
}
|
|
117
|
-
]
|
|
144
|
+
],
|
|
145
|
+
cases: [],
|
|
146
|
+
operand: '@input.text',
|
|
147
|
+
default_category_uuid: 'all-responses-cat-3'
|
|
118
148
|
},
|
|
119
|
-
exits: [
|
|
149
|
+
exits: [
|
|
150
|
+
{ uuid: 'all-responses-exit-3', destination_uuid: null },
|
|
151
|
+
{ uuid: 'timeout-exit-3', destination_uuid: null }
|
|
152
|
+
]
|
|
120
153
|
} as Node,
|
|
121
154
|
{ type: 'wait_for_response' },
|
|
122
155
|
'short-timeout'
|
|
@@ -135,9 +168,18 @@ describe('wait_for_response node config', () => {
|
|
|
135
168
|
// No timeout specified
|
|
136
169
|
},
|
|
137
170
|
result_name: 'response',
|
|
138
|
-
categories: [
|
|
171
|
+
categories: [
|
|
172
|
+
{
|
|
173
|
+
uuid: 'all-responses-cat-4',
|
|
174
|
+
name: 'All Responses',
|
|
175
|
+
exit_uuid: 'all-responses-exit-4'
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
cases: [],
|
|
179
|
+
operand: '@input.text',
|
|
180
|
+
default_category_uuid: 'all-responses-cat-4'
|
|
139
181
|
},
|
|
140
|
-
exits: []
|
|
182
|
+
exits: [{ uuid: 'all-responses-exit-4', destination_uuid: null }]
|
|
141
183
|
} as Node,
|
|
142
184
|
{ type: 'wait_for_response' },
|
|
143
185
|
'no-timeout'
|
|
@@ -450,6 +492,247 @@ describe('wait_for_response node config', () => {
|
|
|
450
492
|
'timeout-cat'
|
|
451
493
|
);
|
|
452
494
|
});
|
|
495
|
+
|
|
496
|
+
it('ensures user categories never share UUIDs with system categories', () => {
|
|
497
|
+
const formData = {
|
|
498
|
+
uuid: 'test-node',
|
|
499
|
+
result_name: 'response',
|
|
500
|
+
rules: [
|
|
501
|
+
{
|
|
502
|
+
operator: 'has_any_word',
|
|
503
|
+
value1: 'hello',
|
|
504
|
+
value2: '',
|
|
505
|
+
category: 'Greeting'
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
// Original node with existing system categories
|
|
511
|
+
const originalNode: Node = {
|
|
512
|
+
uuid: 'test-node',
|
|
513
|
+
actions: [],
|
|
514
|
+
exits: [
|
|
515
|
+
{ uuid: 'system-other-exit', destination_uuid: null },
|
|
516
|
+
{ uuid: 'system-all-responses-exit', destination_uuid: null }
|
|
517
|
+
],
|
|
518
|
+
router: {
|
|
519
|
+
type: 'switch',
|
|
520
|
+
result_name: 'response',
|
|
521
|
+
categories: [
|
|
522
|
+
{
|
|
523
|
+
uuid: 'system-other-uuid',
|
|
524
|
+
name: 'Other',
|
|
525
|
+
exit_uuid: 'system-other-exit'
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
uuid: 'system-all-responses-uuid',
|
|
529
|
+
name: 'All Responses',
|
|
530
|
+
exit_uuid: 'system-all-responses-exit'
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const result = wait_for_response.fromFormData!(formData, originalNode);
|
|
537
|
+
|
|
538
|
+
// Get all category UUIDs
|
|
539
|
+
const categoryUUIDs = result.router!.categories.map((cat) => cat.uuid);
|
|
540
|
+
const exitUUIDs = result.exits.map((exit) => exit.uuid);
|
|
541
|
+
|
|
542
|
+
// Find user category (Greeting)
|
|
543
|
+
const userCategory = result.router!.categories.find(
|
|
544
|
+
(cat) => cat.name === 'Greeting'
|
|
545
|
+
);
|
|
546
|
+
const systemOtherCategory = result.router!.categories.find(
|
|
547
|
+
(cat) => cat.name === 'Other'
|
|
548
|
+
);
|
|
549
|
+
|
|
550
|
+
expect(userCategory).to.exist;
|
|
551
|
+
expect(systemOtherCategory).to.exist;
|
|
552
|
+
|
|
553
|
+
// Verify that user category UUID is different from any system category UUID
|
|
554
|
+
expect(userCategory!.uuid).to.not.equal('system-other-uuid');
|
|
555
|
+
expect(userCategory!.uuid).to.not.equal('system-all-responses-uuid');
|
|
556
|
+
expect(userCategory!.exit_uuid).to.not.equal('system-other-exit');
|
|
557
|
+
expect(userCategory!.exit_uuid).to.not.equal('system-all-responses-exit');
|
|
558
|
+
|
|
559
|
+
// Verify all UUIDs are unique
|
|
560
|
+
expect(new Set(categoryUUIDs)).to.have.lengthOf(categoryUUIDs.length);
|
|
561
|
+
expect(new Set(exitUUIDs)).to.have.lengthOf(exitUUIDs.length);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('removes No Response category when timeout is disabled and no user rules', () => {
|
|
565
|
+
// Start with a node that has timeout enabled and No Response category
|
|
566
|
+
const originalNode: Node = {
|
|
567
|
+
uuid: 'test-node',
|
|
568
|
+
actions: [],
|
|
569
|
+
exits: [
|
|
570
|
+
{ uuid: 'all-responses-exit', destination_uuid: null },
|
|
571
|
+
{ uuid: 'no-response-exit', destination_uuid: null }
|
|
572
|
+
],
|
|
573
|
+
router: {
|
|
574
|
+
type: 'switch',
|
|
575
|
+
result_name: 'response',
|
|
576
|
+
categories: [
|
|
577
|
+
{
|
|
578
|
+
uuid: 'all-responses-cat',
|
|
579
|
+
name: 'All Responses',
|
|
580
|
+
exit_uuid: 'all-responses-exit'
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
uuid: 'no-response-cat',
|
|
584
|
+
name: 'No Response',
|
|
585
|
+
exit_uuid: 'no-response-exit'
|
|
586
|
+
}
|
|
587
|
+
],
|
|
588
|
+
cases: [],
|
|
589
|
+
operand: '@input.text',
|
|
590
|
+
default_category_uuid: 'all-responses-cat',
|
|
591
|
+
wait: {
|
|
592
|
+
type: 'msg',
|
|
593
|
+
timeout: {
|
|
594
|
+
seconds: 300,
|
|
595
|
+
category_uuid: 'no-response-cat'
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
// Form data with timeout disabled and no user rules
|
|
602
|
+
const formData = {
|
|
603
|
+
uuid: 'test-node',
|
|
604
|
+
result_name: 'response',
|
|
605
|
+
rules: [], // No user rules
|
|
606
|
+
timeout_enabled: false, // Timeout disabled
|
|
607
|
+
timeout_duration: null
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
const result = wait_for_response.fromFormData!(formData, originalNode);
|
|
611
|
+
|
|
612
|
+
// Should only have "All Responses" category, not "No Response"
|
|
613
|
+
expect(result.router?.categories).to.have.length(1);
|
|
614
|
+
expect(result.router?.categories[0].name).to.equal('All Responses');
|
|
615
|
+
expect(result.exits).to.have.length(1);
|
|
616
|
+
expect(result.exits[0].uuid).to.equal('all-responses-exit');
|
|
617
|
+
|
|
618
|
+
// Should not have timeout configuration
|
|
619
|
+
expect(result.router?.wait?.timeout).to.be.undefined;
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('adds No Response category when timeout is enabled and no user rules', () => {
|
|
623
|
+
// Start with a node that has no timeout and only "All Responses"
|
|
624
|
+
const originalNode: Node = {
|
|
625
|
+
uuid: 'test-node',
|
|
626
|
+
actions: [],
|
|
627
|
+
exits: [{ uuid: 'all-responses-exit', destination_uuid: null }],
|
|
628
|
+
router: {
|
|
629
|
+
type: 'switch',
|
|
630
|
+
result_name: 'response',
|
|
631
|
+
categories: [
|
|
632
|
+
{
|
|
633
|
+
uuid: 'all-responses-cat',
|
|
634
|
+
name: 'All Responses',
|
|
635
|
+
exit_uuid: 'all-responses-exit'
|
|
636
|
+
}
|
|
637
|
+
],
|
|
638
|
+
cases: [],
|
|
639
|
+
operand: '@input.text',
|
|
640
|
+
default_category_uuid: 'all-responses-cat',
|
|
641
|
+
wait: {
|
|
642
|
+
type: 'msg'
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
// Form data with timeout enabled and no user rules
|
|
648
|
+
const formData = {
|
|
649
|
+
uuid: 'test-node',
|
|
650
|
+
result_name: 'response',
|
|
651
|
+
rules: [], // No user rules
|
|
652
|
+
timeout_enabled: true, // Timeout enabled
|
|
653
|
+
timeout_duration: { value: '300', name: '5 minutes' }
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const result = wait_for_response.fromFormData!(formData, originalNode);
|
|
657
|
+
|
|
658
|
+
// Should have both "All Responses" and "No Response" categories
|
|
659
|
+
expect(result.router?.categories).to.have.length(2);
|
|
660
|
+
const categoryNames = result.router!.categories.map((cat) => cat.name);
|
|
661
|
+
expect(categoryNames).to.include.members([
|
|
662
|
+
'All Responses',
|
|
663
|
+
'No Response'
|
|
664
|
+
]);
|
|
665
|
+
|
|
666
|
+
// Should have 2 exits
|
|
667
|
+
expect(result.exits).to.have.length(2);
|
|
668
|
+
|
|
669
|
+
// Should have timeout configuration
|
|
670
|
+
expect(result.router?.wait?.timeout).to.exist;
|
|
671
|
+
expect(result.router?.wait?.timeout?.seconds).to.equal(300);
|
|
672
|
+
|
|
673
|
+
// Timeout should point to "No Response" category
|
|
674
|
+
const noResponseCategory = result.router!.categories.find(
|
|
675
|
+
(cat) => cat.name === 'No Response'
|
|
676
|
+
);
|
|
677
|
+
expect(result.router?.wait?.timeout?.category_uuid).to.equal(
|
|
678
|
+
noResponseCategory?.uuid
|
|
679
|
+
);
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('handles enabling timeout on node with non-extensible exits array', () => {
|
|
683
|
+
// Create a node with a frozen/sealed exits array to simulate the error condition
|
|
684
|
+
const exitArray = [
|
|
685
|
+
{ uuid: 'all-responses-exit', destination_uuid: null }
|
|
686
|
+
];
|
|
687
|
+
Object.freeze(exitArray); // This makes the array non-extensible
|
|
688
|
+
|
|
689
|
+
const originalNode: Node = {
|
|
690
|
+
uuid: 'test-node',
|
|
691
|
+
actions: [],
|
|
692
|
+
exits: exitArray, // This array is now frozen
|
|
693
|
+
router: {
|
|
694
|
+
type: 'switch',
|
|
695
|
+
result_name: 'response',
|
|
696
|
+
categories: [
|
|
697
|
+
{
|
|
698
|
+
uuid: 'all-responses-cat',
|
|
699
|
+
name: 'All Responses',
|
|
700
|
+
exit_uuid: 'all-responses-exit'
|
|
701
|
+
}
|
|
702
|
+
],
|
|
703
|
+
cases: [],
|
|
704
|
+
operand: '@input.text',
|
|
705
|
+
default_category_uuid: 'all-responses-cat',
|
|
706
|
+
wait: {
|
|
707
|
+
type: 'msg'
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
// Form data with timeout being enabled (this should trigger the error)
|
|
713
|
+
const formData = {
|
|
714
|
+
uuid: 'test-node',
|
|
715
|
+
result_name: 'response',
|
|
716
|
+
rules: [], // No user rules
|
|
717
|
+
timeout_enabled: true, // Enable timeout (this is the key change)
|
|
718
|
+
timeout_duration: { value: '300', name: '5 minutes' }
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// This should not throw an error even with a frozen exits array
|
|
722
|
+
expect(() => {
|
|
723
|
+
const result = wait_for_response.fromFormData!(formData, originalNode);
|
|
724
|
+
|
|
725
|
+
// Verify the result is correct
|
|
726
|
+
expect(result.router?.categories).to.have.length(2);
|
|
727
|
+
const categoryNames = result.router!.categories.map((cat) => cat.name);
|
|
728
|
+
expect(categoryNames).to.include.members([
|
|
729
|
+
'All Responses',
|
|
730
|
+
'No Response'
|
|
731
|
+
]);
|
|
732
|
+
expect(result.exits).to.have.length(2);
|
|
733
|
+
expect(result.router?.wait?.timeout).to.exist;
|
|
734
|
+
}).to.not.throw();
|
|
735
|
+
});
|
|
453
736
|
});
|
|
454
737
|
|
|
455
738
|
describe('validation', () => {
|
|
@@ -938,4 +1221,139 @@ describe('wait_for_response node config', () => {
|
|
|
938
1221
|
expect(categoryNames).to.deep.equal(['Shared', 'Different', 'Other']);
|
|
939
1222
|
});
|
|
940
1223
|
});
|
|
1224
|
+
|
|
1225
|
+
describe('category auto-population', () => {
|
|
1226
|
+
it('auto-populates fixed category names for operators with no operands', () => {
|
|
1227
|
+
// Test with has_text operator (0 operands)
|
|
1228
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1229
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1230
|
+
|
|
1231
|
+
const items = [
|
|
1232
|
+
{ operator: 'has_text', value1: '', value2: '', category: '' }
|
|
1233
|
+
];
|
|
1234
|
+
const result = onItemChange(0, 'operator', 'has_text', items);
|
|
1235
|
+
|
|
1236
|
+
expect(result[0].category).to.equal('Has Text');
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
it('auto-populates category name for single operand operators', () => {
|
|
1240
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1241
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1242
|
+
|
|
1243
|
+
// Test has_any_word - should capitalize first letter
|
|
1244
|
+
const items = [
|
|
1245
|
+
{ operator: 'has_any_word', value1: '', value2: '', category: '' }
|
|
1246
|
+
];
|
|
1247
|
+
let result = onItemChange(0, 'value1', 'red', items);
|
|
1248
|
+
expect(result[0].category).to.equal('Red');
|
|
1249
|
+
|
|
1250
|
+
// Test has_number_lt - should include < symbol
|
|
1251
|
+
const items2 = [
|
|
1252
|
+
{ operator: 'has_number_lt', value1: '', value2: '', category: '' }
|
|
1253
|
+
];
|
|
1254
|
+
result = onItemChange(0, 'value1', '5', items2);
|
|
1255
|
+
expect(result[0].category).to.equal('< 5');
|
|
1256
|
+
|
|
1257
|
+
// Test has_number_eq - should include = symbol
|
|
1258
|
+
const items3 = [
|
|
1259
|
+
{ operator: 'has_number_eq', value1: '', value2: '', category: '' }
|
|
1260
|
+
];
|
|
1261
|
+
result = onItemChange(0, 'value1', '10', items3);
|
|
1262
|
+
expect(result[0].category).to.equal('= 10');
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
it('auto-populates category name for two operand operators', () => {
|
|
1266
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1267
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1268
|
+
|
|
1269
|
+
// Test has_number_between - should format as range
|
|
1270
|
+
const items = [
|
|
1271
|
+
{ operator: 'has_number_between', value1: '', value2: '', category: '' }
|
|
1272
|
+
];
|
|
1273
|
+
let result = onItemChange(0, 'value1', '45', items);
|
|
1274
|
+
// Should not populate yet (need both values)
|
|
1275
|
+
expect(result[0].category).to.equal('');
|
|
1276
|
+
|
|
1277
|
+
result = onItemChange(0, 'value2', '85', result);
|
|
1278
|
+
expect(result[0].category).to.equal('45 - 85');
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
it('auto-populates category name for date operators with relative expressions', () => {
|
|
1282
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1283
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1284
|
+
|
|
1285
|
+
// Test has_date_gt - should format as "After today + X days"
|
|
1286
|
+
let items = [
|
|
1287
|
+
{ operator: 'has_date_gt', value1: '', value2: '', category: '' }
|
|
1288
|
+
];
|
|
1289
|
+
let result = onItemChange(0, 'value1', 'today + 5', items);
|
|
1290
|
+
expect(result[0].category).to.equal('After today + 5 days');
|
|
1291
|
+
|
|
1292
|
+
// Test has_date_lt with single day - should use "day" not "days"
|
|
1293
|
+
items = [
|
|
1294
|
+
{ operator: 'has_date_lt', value1: '', value2: '', category: '' }
|
|
1295
|
+
];
|
|
1296
|
+
result = onItemChange(0, 'value1', 'today + 1', items);
|
|
1297
|
+
expect(result[0].category).to.equal('Before today + 1 day');
|
|
1298
|
+
|
|
1299
|
+
// Test has_date_eq
|
|
1300
|
+
items = [
|
|
1301
|
+
{ operator: 'has_date_eq', value1: '', value2: '', category: '' }
|
|
1302
|
+
];
|
|
1303
|
+
result = onItemChange(0, 'value1', 'today - 3', items);
|
|
1304
|
+
expect(result[0].category).to.equal('today - 3 days');
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
it('updates category name when value changes if category matches old default', () => {
|
|
1308
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1309
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1310
|
+
|
|
1311
|
+
// Start with "red"
|
|
1312
|
+
const items = [
|
|
1313
|
+
{ operator: 'has_any_word', value1: 'red', value2: '', category: 'Red' }
|
|
1314
|
+
];
|
|
1315
|
+
|
|
1316
|
+
// Change to "blue" - category should update since it matches old default
|
|
1317
|
+
const result = onItemChange(0, 'value1', 'blue', items);
|
|
1318
|
+
expect(result[0].category).to.equal('Blue');
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
it('does not update category name when value changes if user customized it', () => {
|
|
1322
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1323
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1324
|
+
|
|
1325
|
+
// Start with "red" but custom category "Color"
|
|
1326
|
+
const items = [
|
|
1327
|
+
{
|
|
1328
|
+
operator: 'has_any_word',
|
|
1329
|
+
value1: 'red',
|
|
1330
|
+
value2: '',
|
|
1331
|
+
category: 'Color'
|
|
1332
|
+
}
|
|
1333
|
+
];
|
|
1334
|
+
|
|
1335
|
+
// Change to "blue" - category should NOT update (user customized it)
|
|
1336
|
+
const result = onItemChange(0, 'value1', 'blue', items);
|
|
1337
|
+
expect(result[0].category).to.equal('Color');
|
|
1338
|
+
});
|
|
1339
|
+
|
|
1340
|
+
it('updates category when operator changes', () => {
|
|
1341
|
+
const rulesConfig = wait_for_response.form.rules as any;
|
|
1342
|
+
const onItemChange = rulesConfig.onItemChange;
|
|
1343
|
+
|
|
1344
|
+
// Start with has_any_word
|
|
1345
|
+
const items = [
|
|
1346
|
+
{
|
|
1347
|
+
operator: 'has_any_word',
|
|
1348
|
+
value1: 'test',
|
|
1349
|
+
value2: '',
|
|
1350
|
+
category: 'Test'
|
|
1351
|
+
}
|
|
1352
|
+
];
|
|
1353
|
+
|
|
1354
|
+
// Change to has_text (0 operands) - category should update to fixed name
|
|
1355
|
+
const result = onItemChange(0, 'operator', 'has_text', items);
|
|
1356
|
+
expect(result[0].category).to.equal('Has Text');
|
|
1357
|
+
});
|
|
1358
|
+
});
|
|
941
1359
|
});
|