@nyaruka/temba-components 0.130.0 → 0.130.2
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 +34 -4
- package/DEV_DATA.md +89 -0
- package/demo/data/flows/food-order.json +4 -4
- package/demo/data/flows/sample-flow.json +132 -147
- package/dist/temba-components.js +764 -628
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +5 -3
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +83 -78
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1 -0
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +47 -3
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +13 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +1 -0
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +17 -14
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +12 -12
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +609 -6
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/operators.js +194 -0
- package/out-tsc/src/flow/operators.js.map +1 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +84 -19
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/Checkbox.js +12 -0
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +13 -3
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/TextInput.js +20 -1
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +14 -1
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +3 -4
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/list/RunList.js +2 -2
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +114 -34
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/live/ContactDetails.js +7 -0
- package/out-tsc/src/live/ContactDetails.js.map +1 -1
- package/out-tsc/src/live/ContactNameFetch.js +1 -1
- package/out-tsc/src/live/ContactNameFetch.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +25 -27
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +12 -4
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js +101 -91
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_random.test.js +120 -112
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_digits.test.js +131 -111
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +549 -85
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-checkbox.test.js +32 -32
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +2 -1
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +0 -4
- package/out-tsc/test/temba-dropdown.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +9 -4
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-integration-markdown.test.js +13 -15
- package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +5 -38
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-run-list.test.js +2 -2
- package/out-tsc/test/temba-run-list.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +6 -2
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-whitespace-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
- package/screenshots/truth/checkbox/checked.png +0 -0
- package/screenshots/truth/checkbox/default.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/integration/textinput-markdown-errors.png +0 -0
- package/screenshots/truth/lightbox/img-zoomed.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- 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/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.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/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/wait-for-response/rules-editor.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor-unchecked.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor.png +0 -0
- package/scripts/dev-data-sync.mjs +182 -0
- package/src/display/Chat.ts +6 -4
- package/src/events.ts +6 -5
- package/src/flow/CanvasNode.ts +89 -79
- package/src/flow/Editor.ts +1 -0
- package/src/flow/NodeEditor.ts +55 -3
- package/src/flow/actions/add_contact_groups.ts +16 -1
- package/src/flow/actions/add_contact_urn.ts +1 -1
- package/src/flow/actions/add_input_labels.ts +1 -0
- package/src/flow/actions/set_contact_channel.ts +1 -1
- package/src/flow/actions/set_contact_field.ts +2 -1
- package/src/flow/actions/set_contact_language.ts +3 -1
- package/src/flow/actions/set_contact_name.ts +1 -1
- package/src/flow/actions/set_contact_status.ts +18 -18
- package/src/flow/actions/set_run_result.ts +1 -1
- package/src/flow/nodes/split_by_llm.ts +14 -13
- package/src/flow/nodes/wait_for_response.ts +717 -5
- package/src/flow/operators.ts +215 -0
- package/src/flow/types.ts +10 -2
- package/src/form/ArrayEditor.ts +117 -37
- package/src/form/Checkbox.ts +12 -0
- package/src/form/FieldRenderer.ts +24 -3
- package/src/form/TextInput.ts +19 -1
- package/src/form/select/Select.ts +15 -4
- package/src/interfaces.ts +1 -1
- package/src/layout/Dialog.ts +4 -4
- package/src/list/RunList.ts +2 -2
- package/src/live/ContactChat.ts +144 -58
- package/src/live/ContactDetails.ts +7 -0
- package/src/live/ContactNameFetch.ts +1 -1
- package/static/api/labels.json +6 -1
- package/test/NodeHelper.ts +38 -40
- package/test/nodes/split_by_llm.test.ts +43 -32
- package/test/nodes/split_by_llm_categorize.test.ts +130 -120
- package/test/nodes/split_by_random.test.ts +136 -128
- package/test/nodes/wait_for_digits.test.ts +147 -127
- package/test/nodes/wait_for_response.test.ts +657 -104
- package/test/temba-checkbox.test.ts +36 -32
- package/test/temba-contact-chat.test.ts +2 -1
- package/test/temba-dropdown.test.ts +0 -12
- package/test/temba-flow-editor-node.test.ts +11 -4
- package/test/temba-integration-markdown.test.ts +16 -17
- package/test/temba-node-editor.test.ts +5 -43
- package/test/temba-run-list.test.ts +2 -2
- package/test/utils.test.ts +2 -1
- package/test-assets/list/runs.json +8 -8
- package/web-dev-mock.mjs +86 -30
- package/web-dev-server.config.mjs +272 -31
- package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { html, fixture, expect } from '@open-wc/testing';
|
|
2
2
|
import { Checkbox } from '../src/form/Checkbox';
|
|
3
|
-
import { assertScreenshot, getClip } from './utils.test';
|
|
3
|
+
import { assertScreenshot, getClip, getComponent } from './utils.test';
|
|
4
|
+
|
|
5
|
+
const getCheckbox = async (props: any) => {
|
|
6
|
+
return (await getComponent('temba-checkbox', props)) as Checkbox;
|
|
7
|
+
};
|
|
4
8
|
|
|
5
9
|
describe('temba-checkbox', () => {
|
|
6
10
|
it('renders default checkbox', async () => {
|
|
7
|
-
const el
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const el = await getCheckbox({
|
|
12
|
+
label: 'My Checkbox'
|
|
13
|
+
});
|
|
10
14
|
|
|
11
15
|
expect(el.label).to.equal('My Checkbox');
|
|
12
16
|
await assertScreenshot('checkbox/default', getClip(el));
|
|
13
17
|
});
|
|
14
18
|
|
|
15
19
|
it('can select by clicking on the label', async () => {
|
|
16
|
-
const el: Checkbox = await
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
></temba-checkbox>
|
|
21
|
-
`);
|
|
20
|
+
const el: Checkbox = await getCheckbox({
|
|
21
|
+
label: 'My Checkbox',
|
|
22
|
+
animatechange: false
|
|
23
|
+
});
|
|
22
24
|
|
|
23
25
|
(el.shadowRoot.querySelector('.checkbox-label') as HTMLDivElement).click();
|
|
24
26
|
expect(el.checked).to.equal(true);
|
|
@@ -28,9 +30,9 @@ describe('temba-checkbox', () => {
|
|
|
28
30
|
it('fires change event on click', async () => {
|
|
29
31
|
// eslint-disable-next-line no-async-promise-executor
|
|
30
32
|
return new Promise<void>(async (resolve) => {
|
|
31
|
-
const checkbox
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const checkbox = await getCheckbox({
|
|
34
|
+
label: 'My Checkbox'
|
|
35
|
+
});
|
|
34
36
|
|
|
35
37
|
checkbox.addEventListener('change', () => {
|
|
36
38
|
resolve();
|
|
@@ -41,17 +43,19 @@ describe('temba-checkbox', () => {
|
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
it('checks via click method', async () => {
|
|
44
|
-
const checkbox
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
const checkbox = await getCheckbox({
|
|
47
|
+
label: 'My Checkbox'
|
|
48
|
+
});
|
|
47
49
|
checkbox.click();
|
|
48
50
|
expect(checkbox.checked).to.equal(true);
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
it('has background hover effect when label is set', async () => {
|
|
52
|
-
const el: Checkbox = await
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const el: Checkbox = await getCheckbox({
|
|
55
|
+
label: 'My Label',
|
|
56
|
+
name: 'My Checkbox'
|
|
57
|
+
});
|
|
58
|
+
|
|
55
59
|
expect(el.label).to.equal('My Label');
|
|
56
60
|
//the ".wrapper.label" style results in the background hover effect
|
|
57
61
|
const wrapperDivEl = el.shadowRoot.querySelector(
|
|
@@ -68,9 +72,10 @@ describe('temba-checkbox', () => {
|
|
|
68
72
|
//but this is the expected behavior if the label value is still empty,
|
|
69
73
|
//upon rendering the component
|
|
70
74
|
it('has no background hover effect when label is empty', async () => {
|
|
71
|
-
const el: Checkbox = await
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
const el: Checkbox = await getCheckbox({
|
|
76
|
+
name: 'My Checkbox'
|
|
77
|
+
});
|
|
78
|
+
|
|
74
79
|
expect(el.label).to.equal(undefined);
|
|
75
80
|
//the ".wrapper.label" style results in the background hover effect
|
|
76
81
|
const wrapperDivEl = el.shadowRoot.querySelector(
|
|
@@ -84,9 +89,11 @@ describe('temba-checkbox', () => {
|
|
|
84
89
|
});
|
|
85
90
|
|
|
86
91
|
it('has no background hover effect when label is whitespace', async () => {
|
|
87
|
-
const el: Checkbox = await
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
const el: Checkbox = await getCheckbox({
|
|
93
|
+
name: 'My Checkbox',
|
|
94
|
+
label: ''
|
|
95
|
+
});
|
|
96
|
+
|
|
90
97
|
expect(el.label).to.equal('');
|
|
91
98
|
//the ".wrapper.label" style results in the background hover effect
|
|
92
99
|
const wrapperDivEl = el.shadowRoot.querySelector(
|
|
@@ -167,13 +174,10 @@ describe('temba-checkbox', () => {
|
|
|
167
174
|
});
|
|
168
175
|
|
|
169
176
|
it('aligns help text with label when both are present', async () => {
|
|
170
|
-
const el: Checkbox = await
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
>
|
|
175
|
-
</temba-checkbox>
|
|
176
|
-
`);
|
|
177
|
+
const el: Checkbox = (await getCheckbox({
|
|
178
|
+
label: 'Checkbox with help',
|
|
179
|
+
help_text: 'This help text should align with the label text'
|
|
180
|
+
})) as unknown as Checkbox;
|
|
177
181
|
|
|
178
182
|
expect(el.label).to.equal('Checkbox with help');
|
|
179
183
|
expect(el.helpText).to.equal(
|
|
@@ -73,7 +73,8 @@ describe('temba-contact-chat', () => {
|
|
|
73
73
|
mockedNow.restore();
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
// temporarily disabled as it's too flaky in CI
|
|
77
|
+
xit('show history and show chatbox if contact is active', async () => {
|
|
77
78
|
// we are a StoreElement, so load a store first
|
|
78
79
|
await loadStore();
|
|
79
80
|
const chat: ContactChat = await getContactChat({
|
|
@@ -289,12 +289,6 @@ describe(TAG, () => {
|
|
|
289
289
|
|
|
290
290
|
// Verify position was adjusted for right edge
|
|
291
291
|
expect(dropdown.dropdownStyle).to.have.property('left');
|
|
292
|
-
|
|
293
|
-
// Screenshot positioned dropdown
|
|
294
|
-
await assertScreenshot(
|
|
295
|
-
'dropdown/right-edge-collision',
|
|
296
|
-
getDropdownClip(dropdown)
|
|
297
|
-
);
|
|
298
292
|
} finally {
|
|
299
293
|
// Restore original method
|
|
300
294
|
dropdownDiv.getBoundingClientRect = originalGetBoundingClientRect;
|
|
@@ -343,12 +337,6 @@ describe(TAG, () => {
|
|
|
343
337
|
expect(dropdown.dropdownStyle).to.have.property('top');
|
|
344
338
|
expect(dropdown.arrowStyle).to.have.property('transform');
|
|
345
339
|
expect(dropdown.arrowStyle['transform']).to.include('rotate(180deg)');
|
|
346
|
-
|
|
347
|
-
// Screenshot positioned dropdown
|
|
348
|
-
await assertScreenshot(
|
|
349
|
-
'dropdown/bottom-edge-collision',
|
|
350
|
-
getDropdownClip(dropdown)
|
|
351
|
-
);
|
|
352
340
|
} finally {
|
|
353
341
|
// Restore original method
|
|
354
342
|
dropdownDiv.getBoundingClientRect = originalGetBoundingClientRect;
|
|
@@ -223,12 +223,19 @@ describe('EditorNode', () => {
|
|
|
223
223
|
color: '#ff0000'
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
-
const
|
|
226
|
+
const mockAction: Action = {
|
|
227
|
+
type: 'send_msg',
|
|
228
|
+
uuid: 'test-action'
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const result = (editorNode as any).renderTitle(config, mockAction, 0);
|
|
227
232
|
const container = await fixture(html`<div>${result}</div>`);
|
|
228
233
|
|
|
229
|
-
const title = container.querySelector('.title');
|
|
234
|
+
const title = container.querySelector('.cn-title');
|
|
230
235
|
expect(title).to.exist;
|
|
231
|
-
|
|
236
|
+
|
|
237
|
+
const nameElement = title?.querySelector('.name');
|
|
238
|
+
expect(nameElement?.textContent?.trim()).to.equal('Test Action');
|
|
232
239
|
expect(title?.getAttribute('style')).to.contain('background:#ff0000');
|
|
233
240
|
});
|
|
234
241
|
});
|
|
@@ -1046,7 +1053,7 @@ describe('EditorNode', () => {
|
|
|
1046
1053
|
expect(actionElement?.classList.contains('removing')).to.be.true;
|
|
1047
1054
|
|
|
1048
1055
|
// Check that title shows "Remove?"
|
|
1049
|
-
const titleElement = container.querySelector('.title .name');
|
|
1056
|
+
const titleElement = container.querySelector('.cn-title .name');
|
|
1050
1057
|
expect(titleElement?.textContent?.trim()).to.equal('Remove?');
|
|
1051
1058
|
});
|
|
1052
1059
|
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
import { assertScreenshot, getClip, getComponent } from './utils.test';
|
|
3
|
+
import { TextInput } from '../src/form/TextInput';
|
|
4
4
|
|
|
5
5
|
describe('FormElement markdown integration', () => {
|
|
6
|
-
it('renders
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.errors=${[
|
|
11
|
-
'Please read the **terms and conditions** at [this link](https://example.com)',
|
|
12
|
-
'This field *requires* acceptance'
|
|
13
|
-
]}
|
|
14
|
-
></temba-checkbox>
|
|
15
|
-
`);
|
|
6
|
+
it('renders textinput with markdown errors', async () => {
|
|
7
|
+
const el: TextInput = (await getComponent('temba-textinput', {
|
|
8
|
+
name: 'my_textinput'
|
|
9
|
+
})) as TextInput;
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
el.errors = [
|
|
12
|
+
'You must agree to the **terms and conditions** at [this link](https://example.com)',
|
|
13
|
+
'This field *requires* a value'
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
await el.updateComplete;
|
|
18
17
|
|
|
19
18
|
// Check that errors are rendered with markdown directly in checkbox shadow root
|
|
20
|
-
const errorElements =
|
|
19
|
+
const errorElements = el.shadowRoot.querySelectorAll('.alert-error');
|
|
21
20
|
expect(errorElements.length).to.equal(2);
|
|
22
21
|
|
|
23
22
|
// First error should have bold text and link
|
|
@@ -36,8 +35,8 @@ describe('FormElement markdown integration', () => {
|
|
|
36
35
|
expect(italicElement.textContent).to.equal('requires');
|
|
37
36
|
|
|
38
37
|
await assertScreenshot(
|
|
39
|
-
'integration/
|
|
40
|
-
getClip(
|
|
38
|
+
'integration/textinput-markdown-errors',
|
|
39
|
+
getClip(el)
|
|
41
40
|
);
|
|
42
41
|
});
|
|
43
42
|
});
|
|
@@ -18,7 +18,11 @@ const assertDialogScreenshot = async (
|
|
|
18
18
|
const dialog = el.shadowRoot
|
|
19
19
|
.querySelector('temba-dialog')
|
|
20
20
|
.shadowRoot.querySelector('.dialog-container') as HTMLElement;
|
|
21
|
-
|
|
21
|
+
const clip = getClip(dialog);
|
|
22
|
+
// Adjust width to show full dialog with proper padding
|
|
23
|
+
const dialogRect = dialog.getBoundingClientRect();
|
|
24
|
+
clip.width = dialogRect.width + 20; // 10px padding on each side
|
|
25
|
+
await assertScreenshot(screenshotName, clip);
|
|
22
26
|
};
|
|
23
27
|
|
|
24
28
|
describe('temba-node-editor', () => {
|
|
@@ -337,48 +341,6 @@ describe('temba-node-editor', () => {
|
|
|
337
341
|
expect(shadowRoot).to.not.be.null;
|
|
338
342
|
});
|
|
339
343
|
|
|
340
|
-
it('renders different action types correctly', async () => {
|
|
341
|
-
const actionTypes = [
|
|
342
|
-
{
|
|
343
|
-
type: 'send_msg',
|
|
344
|
-
data: { text: 'Message', quick_replies: [] }
|
|
345
|
-
},
|
|
346
|
-
{
|
|
347
|
-
type: 'set_run_result',
|
|
348
|
-
data: { name: 'result', value: 'value' }
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
type: 'set_contact_name',
|
|
352
|
-
data: { name: 'John Doe' }
|
|
353
|
-
},
|
|
354
|
-
{
|
|
355
|
-
type: 'set_contact_language',
|
|
356
|
-
data: { language: 'eng' }
|
|
357
|
-
}
|
|
358
|
-
];
|
|
359
|
-
|
|
360
|
-
for (const actionType of actionTypes) {
|
|
361
|
-
const action = {
|
|
362
|
-
uuid: `test-${actionType.type}`,
|
|
363
|
-
type: actionType.type,
|
|
364
|
-
...actionType.data
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
const el = (await fixture(html`
|
|
368
|
-
<temba-node-editor
|
|
369
|
-
.action=${action}
|
|
370
|
-
.isOpen=${true}
|
|
371
|
-
></temba-node-editor>
|
|
372
|
-
`)) as NodeEditorElement;
|
|
373
|
-
|
|
374
|
-
await el.updateComplete;
|
|
375
|
-
expect(el.shadowRoot).to.not.be.null;
|
|
376
|
-
expect(el.action.type).to.equal(actionType.type);
|
|
377
|
-
|
|
378
|
-
await assertDialogScreenshot(el, `editor/${actionType.type}`);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
|
|
382
344
|
it('displays bubble count for group value counts', async () => {
|
|
383
345
|
const action = {
|
|
384
346
|
uuid: 'test-action-uuid',
|
|
@@ -572,7 +572,7 @@ describe('temba-run-list', () => {
|
|
|
572
572
|
contact: {
|
|
573
573
|
name: 'John Doe',
|
|
574
574
|
urn: 'tel:+1234567890',
|
|
575
|
-
|
|
575
|
+
ref: 'E2E6MX'
|
|
576
576
|
},
|
|
577
577
|
modified_on: '2023-12-01T10:30:00.000Z',
|
|
578
578
|
exited_on: '2023-12-01T10:30:00.000Z',
|
|
@@ -591,7 +591,7 @@ describe('temba-run-list', () => {
|
|
|
591
591
|
contact: {
|
|
592
592
|
name: null,
|
|
593
593
|
urn: 'tel:+1234567890',
|
|
594
|
-
|
|
594
|
+
ref: 'E2E6MX'
|
|
595
595
|
},
|
|
596
596
|
modified_on: '2023-12-01T10:30:00.000Z',
|
|
597
597
|
exited_on: null,
|
package/test/utils.test.ts
CHANGED
|
@@ -110,7 +110,7 @@ const getResponse = (endpoint: string, options = { method: 'GET' }) => {
|
|
|
110
110
|
before(async () => {
|
|
111
111
|
normalFetch = window.fetch;
|
|
112
112
|
stub(window, 'fetch').callsFake(getResponse);
|
|
113
|
-
await setViewport({ width:
|
|
113
|
+
await setViewport({ width: 1920, height: 1080, deviceScaleFactor: 2 });
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
after(() => {
|
|
@@ -253,6 +253,7 @@ export const getClip = (ele: HTMLElement) => {
|
|
|
253
253
|
clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
// add some padding
|
|
256
257
|
const padding = 10;
|
|
257
258
|
const width = clip.width + padding * 2;
|
|
258
259
|
const height = clip.height + padding * 2;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"uuid": "contact-uuid-1",
|
|
10
10
|
"name": "John Doe",
|
|
11
11
|
"urn": "tel:+1234567890",
|
|
12
|
-
"
|
|
12
|
+
"ref": "E2E6MX"
|
|
13
13
|
},
|
|
14
14
|
"flow": {
|
|
15
15
|
"uuid": "flow-uuid-1",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"values": {
|
|
24
24
|
"name": {
|
|
25
25
|
"name": "Name",
|
|
26
|
-
"key": "name",
|
|
26
|
+
"key": "name",
|
|
27
27
|
"value": "John Doe",
|
|
28
28
|
"category": "Text"
|
|
29
29
|
},
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"id": 2,
|
|
40
|
-
"uuid": "run-uuid-2",
|
|
40
|
+
"uuid": "run-uuid-2",
|
|
41
41
|
"contact": {
|
|
42
42
|
"uuid": "contact-uuid-2",
|
|
43
43
|
"name": "Jane Smith",
|
|
44
44
|
"urn": "tel:+1987654321",
|
|
45
|
-
"
|
|
45
|
+
"ref": "3MWB69"
|
|
46
46
|
},
|
|
47
47
|
"flow": {
|
|
48
48
|
"uuid": "flow-uuid-1",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"id": 3,
|
|
60
60
|
"uuid": "run-uuid-3",
|
|
61
61
|
"contact": {
|
|
62
|
-
"uuid": "contact-uuid-3",
|
|
62
|
+
"uuid": "contact-uuid-3",
|
|
63
63
|
"name": null,
|
|
64
64
|
"urn": "tel:+1122334455",
|
|
65
|
-
"
|
|
65
|
+
"ref": "Q3GP9G"
|
|
66
66
|
},
|
|
67
67
|
"flow": {
|
|
68
68
|
"uuid": "flow-uuid-1",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"uuid": "contact-uuid-4",
|
|
90
90
|
"name": "Active User",
|
|
91
91
|
"urn": "tel:+1555666777",
|
|
92
|
-
"
|
|
92
|
+
"ref": "U6Y6T5"
|
|
93
93
|
},
|
|
94
94
|
"flow": {
|
|
95
95
|
"uuid": "flow-uuid-1",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"uuid": "contact-uuid-5",
|
|
110
110
|
"name": "Pending User",
|
|
111
111
|
"urn": "tel:+1888999000",
|
|
112
|
-
"
|
|
112
|
+
"ref": "SJPWLU"
|
|
113
113
|
},
|
|
114
114
|
"flow": {
|
|
115
115
|
"uuid": "flow-uuid-1",
|
package/web-dev-mock.mjs
CHANGED
|
@@ -440,8 +440,63 @@ export function handleMinioUpload(context) {
|
|
|
440
440
|
});
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
-
//
|
|
444
|
-
|
|
443
|
+
// Entity creation configurations
|
|
444
|
+
const ENTITY_CONFIGS = {
|
|
445
|
+
labels: {
|
|
446
|
+
filePath: './static/api/labels.json',
|
|
447
|
+
createEntity: (name) => ({
|
|
448
|
+
uuid: uuidv4(),
|
|
449
|
+
name: name.trim(),
|
|
450
|
+
count: 0
|
|
451
|
+
}),
|
|
452
|
+
nameField: 'name',
|
|
453
|
+
entityType: 'Label'
|
|
454
|
+
},
|
|
455
|
+
fields: {
|
|
456
|
+
filePath: './static/api/fields.json',
|
|
457
|
+
createEntity: (name) => ({
|
|
458
|
+
key: name.trim().toLowerCase().replace(/\s+/g, '_'),
|
|
459
|
+
name: name.trim(),
|
|
460
|
+
type: 'text',
|
|
461
|
+
featured: false,
|
|
462
|
+
priority: 0,
|
|
463
|
+
usages: {
|
|
464
|
+
flows: 0,
|
|
465
|
+
groups: 0,
|
|
466
|
+
campaign_events: 0
|
|
467
|
+
},
|
|
468
|
+
agent_access: 'view',
|
|
469
|
+
label: name.trim(),
|
|
470
|
+
value_type: 'text'
|
|
471
|
+
}),
|
|
472
|
+
nameField: 'name',
|
|
473
|
+
uniqueField: 'key', // check uniqueness by key for fields
|
|
474
|
+
entityType: 'Field'
|
|
475
|
+
},
|
|
476
|
+
groups: {
|
|
477
|
+
filePath: './static/api/groups.json',
|
|
478
|
+
createEntity: (name) => ({
|
|
479
|
+
uuid: uuidv4(),
|
|
480
|
+
name: name.trim(),
|
|
481
|
+
query: null,
|
|
482
|
+
status: 'ready',
|
|
483
|
+
count: 0
|
|
484
|
+
}),
|
|
485
|
+
nameField: 'name',
|
|
486
|
+
entityType: 'Group'
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// Generic entity creation handler for labels, fields, and groups
|
|
491
|
+
export function handleEntityCreation(entityType, context) {
|
|
492
|
+
const config = ENTITY_CONFIGS[entityType];
|
|
493
|
+
|
|
494
|
+
if (!config) {
|
|
495
|
+
context.status = 400;
|
|
496
|
+
context.body = JSON.stringify({ error: `Unsupported entity type: ${entityType}` });
|
|
497
|
+
return Promise.resolve();
|
|
498
|
+
}
|
|
499
|
+
|
|
445
500
|
return new Promise((resolve) => {
|
|
446
501
|
let body = '';
|
|
447
502
|
|
|
@@ -452,67 +507,67 @@ export function handleLabelCreation(context) {
|
|
|
452
507
|
context.req.on('end', () => {
|
|
453
508
|
try {
|
|
454
509
|
const requestData = JSON.parse(body);
|
|
455
|
-
const
|
|
510
|
+
const entityName = requestData[config.nameField] || '';
|
|
456
511
|
|
|
457
|
-
if (!
|
|
512
|
+
if (!entityName.trim()) {
|
|
458
513
|
context.status = 400;
|
|
459
|
-
context.body = JSON.stringify({ error:
|
|
514
|
+
context.body = JSON.stringify({ error: `${config.entityType} name is required` });
|
|
460
515
|
resolve();
|
|
461
516
|
return;
|
|
462
517
|
}
|
|
463
518
|
|
|
464
|
-
// Read existing
|
|
465
|
-
|
|
466
|
-
let labelsData;
|
|
519
|
+
// Read existing data file
|
|
520
|
+
let entityData;
|
|
467
521
|
|
|
468
522
|
try {
|
|
469
|
-
|
|
523
|
+
entityData = JSON.parse(fs.readFileSync(config.filePath, 'utf-8'));
|
|
470
524
|
} catch (error) {
|
|
471
525
|
// If file doesn't exist, create basic structure
|
|
472
|
-
|
|
526
|
+
entityData = {
|
|
473
527
|
next: null,
|
|
474
528
|
previous: null,
|
|
475
529
|
results: []
|
|
476
530
|
};
|
|
477
531
|
}
|
|
478
532
|
|
|
479
|
-
// Check if
|
|
480
|
-
const
|
|
481
|
-
|
|
533
|
+
// Check if entity already exists
|
|
534
|
+
const uniqueField = config.uniqueField || config.nameField;
|
|
535
|
+
const checkValue = uniqueField === 'key'
|
|
536
|
+
? entityName.trim().toLowerCase().replace(/\s+/g, '_')
|
|
537
|
+
: entityName.trim().toLowerCase();
|
|
538
|
+
|
|
539
|
+
const existingEntity = entityData.results.find(
|
|
540
|
+
entity => entity[uniqueField].toLowerCase() === checkValue
|
|
482
541
|
);
|
|
483
542
|
|
|
484
|
-
if (
|
|
485
|
-
// Return existing
|
|
543
|
+
if (existingEntity) {
|
|
544
|
+
// Return existing entity
|
|
486
545
|
context.contentType = 'application/json';
|
|
487
|
-
context.body = JSON.stringify(
|
|
546
|
+
context.body = JSON.stringify(existingEntity);
|
|
488
547
|
resolve();
|
|
489
548
|
return;
|
|
490
549
|
}
|
|
491
550
|
|
|
492
|
-
// Create new
|
|
493
|
-
const
|
|
494
|
-
uuid: uuidv4(),
|
|
495
|
-
name: labelName.trim(),
|
|
496
|
-
count: 0
|
|
497
|
-
};
|
|
551
|
+
// Create new entity
|
|
552
|
+
const newEntity = config.createEntity(entityName);
|
|
498
553
|
|
|
499
|
-
// Add to
|
|
500
|
-
|
|
554
|
+
// Add to entity data
|
|
555
|
+
entityData.results.push(newEntity);
|
|
501
556
|
|
|
502
557
|
// Write back to file
|
|
503
|
-
fs.writeFileSync(
|
|
558
|
+
fs.writeFileSync(config.filePath, JSON.stringify(entityData, null, 2));
|
|
504
559
|
|
|
505
|
-
// Return the new
|
|
560
|
+
// Return the new entity
|
|
506
561
|
context.contentType = 'application/json';
|
|
507
|
-
context.body = JSON.stringify(
|
|
562
|
+
context.body = JSON.stringify(newEntity);
|
|
508
563
|
|
|
509
|
-
console.log(
|
|
564
|
+
console.log(`📝 ${config.entityType} created:`, newEntity);
|
|
510
565
|
|
|
511
566
|
} catch (error) {
|
|
512
|
-
console.error(
|
|
567
|
+
console.error(`${config.entityType} creation error:`, error);
|
|
513
568
|
context.status = 500;
|
|
514
569
|
context.body = JSON.stringify({
|
|
515
|
-
error:
|
|
570
|
+
error: `${config.entityType} creation failed`,
|
|
516
571
|
details: error.message
|
|
517
572
|
});
|
|
518
573
|
}
|
|
@@ -521,3 +576,4 @@ export function handleLabelCreation(context) {
|
|
|
521
576
|
});
|
|
522
577
|
});
|
|
523
578
|
}
|
|
579
|
+
|