@nyaruka/temba-components 0.129.3 → 0.129.4
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/.eslintrc.js +1 -0
- package/.github/workflows/build.yml +135 -3
- package/CHANGELOG.md +18 -0
- package/demo/data/flows/sample-flow.json +110 -87
- package/demo/field-config-demo.html +135 -0
- package/dist/temba-components.js +1257 -675
- package/dist/temba-components.js.map +1 -1
- package/docs/ActionEditor-Migration.md +118 -0
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/{EditorNode.js → CanvasNode.js} +345 -42
- package/out-tsc/src/flow/CanvasNode.js.map +1 -0
- package/out-tsc/src/flow/Editor.js +107 -3
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +1200 -0
- package/out-tsc/src/flow/NodeEditor.js.map +1 -0
- package/out-tsc/src/flow/Plumber.js +0 -6
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +40 -0
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -0
- package/out-tsc/src/flow/actions/add_contact_urn.js +16 -0
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -0
- package/out-tsc/src/flow/actions/add_input_labels.js +11 -0
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -0
- package/out-tsc/src/flow/actions/call_classifier.js +11 -0
- package/out-tsc/src/flow/actions/call_classifier.js.map +1 -0
- package/out-tsc/src/flow/actions/call_llm.js +11 -0
- package/out-tsc/src/flow/actions/call_llm.js.map +1 -0
- package/out-tsc/src/flow/actions/call_resthook.js +11 -0
- package/out-tsc/src/flow/actions/call_resthook.js.map +1 -0
- package/out-tsc/src/flow/actions/call_webhook.js +122 -0
- package/out-tsc/src/flow/actions/call_webhook.js.map +1 -0
- package/out-tsc/src/flow/actions/enter_flow.js +14 -0
- package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
- package/out-tsc/src/flow/actions/open_ticket.js +11 -0
- package/out-tsc/src/flow/actions/open_ticket.js.map +1 -0
- package/out-tsc/src/flow/actions/play_audio.js +11 -0
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -0
- package/out-tsc/src/flow/actions/remove_contact_groups.js +62 -0
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -0
- package/out-tsc/src/flow/actions/request_optin.js +11 -0
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -0
- package/out-tsc/src/flow/actions/say_msg.js +11 -0
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -0
- package/out-tsc/src/flow/actions/send_broadcast.js +33 -0
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -0
- package/out-tsc/src/flow/actions/send_email.js +56 -0
- package/out-tsc/src/flow/actions/send_email.js.map +1 -0
- package/out-tsc/src/flow/actions/send_msg.js +55 -0
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_channel.js +12 -0
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_field.js +12 -0
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_language.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_name.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -0
- package/out-tsc/src/flow/actions/set_contact_status.js +10 -0
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -0
- package/out-tsc/src/flow/actions/set_run_result.js +10 -0
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -0
- package/out-tsc/src/flow/actions/split_by_expression_example.js +77 -0
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -0
- package/out-tsc/src/flow/actions/start_session.js +11 -0
- package/out-tsc/src/flow/actions/start_session.js.map +1 -0
- package/out-tsc/src/flow/actions/transfer_airtime.js +11 -0
- package/out-tsc/src/flow/actions/transfer_airtime.js.map +1 -0
- package/out-tsc/src/flow/config.js +88 -193
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/execute_actions.js +4 -0
- package/out-tsc/src/flow/nodes/execute_actions.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_expression.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_groups.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_random.js +10 -0
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_scheme.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_subflow.js +9 -0
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_webhook.js +18 -0
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_image.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_location.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_menu.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_video.js +7 -0
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -0
- package/out-tsc/src/flow/types.js +79 -0
- package/out-tsc/src/flow/types.js.map +1 -0
- package/out-tsc/src/flow/utils.js +65 -0
- package/out-tsc/src/flow/utils.js.map +1 -0
- package/out-tsc/src/form/ArrayEditor.js +199 -0
- package/out-tsc/src/form/ArrayEditor.js.map +1 -0
- package/out-tsc/src/form/BaseListEditor.js +128 -0
- package/out-tsc/src/form/BaseListEditor.js.map +1 -0
- package/out-tsc/src/form/Checkbox.js +17 -2
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/Completion.js +6 -0
- package/out-tsc/src/form/Completion.js.map +1 -1
- package/out-tsc/src/form/FormField.js +110 -11
- package/out-tsc/src/form/FormField.js.map +1 -1
- package/out-tsc/src/form/KeyValueEditor.js +223 -0
- package/out-tsc/src/form/KeyValueEditor.js.map +1 -0
- package/out-tsc/src/form/select/Select.js +77 -32
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/interfaces.js +6 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +2 -76
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/temba-modules.js +9 -2
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +116 -0
- package/out-tsc/test/ActionHelper.js.map +1 -0
- package/out-tsc/test/actions/add_contact_groups.test.js +66 -0
- package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js +226 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -0
- package/out-tsc/test/actions/send_email.test.js +160 -0
- package/out-tsc/test/actions/send_email.test.js.map +1 -0
- package/out-tsc/test/actions/send_msg.test.js +95 -0
- package/out-tsc/test/actions/send_msg.test.js.map +1 -0
- package/out-tsc/test/temba-action-editing-integration.test.js +183 -0
- package/out-tsc/test/temba-action-editing-integration.test.js.map +1 -0
- package/out-tsc/test/temba-checkbox.test.js +1 -1
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-field-config.test.js +133 -0
- package/out-tsc/test/temba-field-config.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +14 -14
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +283 -0
- package/out-tsc/test/temba-node-editor.test.js.map +1 -0
- package/out-tsc/test/temba-select.test.js +85 -0
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/package.json +1 -1
- 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/editor/router.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/editor/wait.png +0 -0
- package/screenshots/truth/formfield/markdown-errors.png +0 -0
- package/screenshots/truth/formfield/plain-text-errors.png +0 -0
- package/screenshots/truth/formfield/widget-only-markdown-errors.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
- package/src/events.ts +1 -40
- package/src/flow/{EditorNode.ts → CanvasNode.ts} +424 -48
- package/src/flow/Editor.ts +140 -4
- package/src/flow/NodeEditor.ts +1443 -0
- package/src/flow/Plumber.ts +0 -9
- package/src/flow/actions/add_contact_groups.ts +42 -0
- package/src/flow/actions/add_contact_urn.ts +17 -0
- package/src/flow/actions/add_input_labels.ts +12 -0
- package/src/flow/actions/call_classifier.ts +12 -0
- package/src/flow/actions/call_llm.ts +12 -0
- package/src/flow/actions/call_resthook.ts +12 -0
- package/src/flow/actions/call_webhook.ts +133 -0
- package/src/flow/actions/enter_flow.ts +15 -0
- package/src/flow/actions/open_ticket.ts +12 -0
- package/src/flow/actions/play_audio.ts +12 -0
- package/src/flow/actions/remove_contact_groups.ts +66 -0
- package/src/flow/actions/request_optin.ts +12 -0
- package/src/flow/actions/say_msg.ts +12 -0
- package/src/flow/actions/send_broadcast.ts +35 -0
- package/src/flow/actions/send_email.ts +60 -0
- package/src/flow/actions/send_msg.ts +58 -0
- package/src/flow/actions/set_contact_channel.ts +13 -0
- package/src/flow/actions/set_contact_field.ts +13 -0
- package/src/flow/actions/set_contact_language.ts +11 -0
- package/src/flow/actions/set_contact_name.ts +11 -0
- package/src/flow/actions/set_contact_status.ts +11 -0
- package/src/flow/actions/set_run_result.ts +11 -0
- package/src/flow/actions/split_by_expression_example.ts +88 -0
- package/src/flow/actions/start_session.ts +12 -0
- package/src/flow/actions/transfer_airtime.ts +12 -0
- package/src/flow/config.ts +93 -232
- package/src/flow/nodes/execute_actions.ts +5 -0
- package/src/flow/nodes/split_by_airtime.ts +9 -0
- package/src/flow/nodes/split_by_contact_field.ts +7 -0
- package/src/flow/nodes/split_by_expression.ts +7 -0
- package/src/flow/nodes/split_by_groups.ts +7 -0
- package/src/flow/nodes/split_by_random.ts +10 -0
- package/src/flow/nodes/split_by_run_result.ts +7 -0
- package/src/flow/nodes/split_by_scheme.ts +7 -0
- package/src/flow/nodes/split_by_subflow.ts +9 -0
- package/src/flow/nodes/split_by_webhook.ts +19 -0
- package/src/flow/nodes/wait_for_audio.ts +7 -0
- package/src/flow/nodes/wait_for_digits.ts +7 -0
- package/src/flow/nodes/wait_for_image.ts +7 -0
- package/src/flow/nodes/wait_for_location.ts +7 -0
- package/src/flow/nodes/wait_for_menu.ts +7 -0
- package/src/flow/nodes/wait_for_response.ts +7 -0
- package/src/flow/nodes/wait_for_video.ts +7 -0
- package/src/flow/types.ts +352 -0
- package/src/flow/utils.ts +76 -0
- package/src/form/ArrayEditor.ts +240 -0
- package/src/form/BaseListEditor.ts +177 -0
- package/src/form/Checkbox.ts +22 -3
- package/src/form/Completion.ts +6 -0
- package/src/form/FormField.ts +115 -11
- package/src/form/KeyValueEditor.ts +251 -0
- package/src/form/select/Select.ts +89 -32
- package/src/interfaces.ts +7 -2
- package/src/live/ContactChat.ts +3 -97
- package/src/store/flow-definition.d.ts +6 -1
- package/static/api/contacts.json +30 -0
- package/static/api/groups.json +4 -426
- package/static/api/locations.json +24 -0
- package/static/api/media.json +5 -0
- package/static/api/optins.json +16 -0
- package/static/api/orgs.json +13 -0
- package/static/api/topics.json +21 -0
- package/static/api/users.json +26 -0
- package/static/css/temba-components.css +3 -6
- package/temba-modules.ts +9 -2
- package/test/ActionHelper.ts +142 -0
- package/test/actions/add_contact_groups.test.ts +89 -0
- package/test/actions/remove_contact_groups.test.ts +265 -0
- package/test/actions/send_email.test.ts +214 -0
- package/test/actions/send_msg.test.ts +130 -0
- package/test/temba-action-editing-integration.test.ts +240 -0
- package/test/temba-checkbox.test.ts +1 -1
- package/test/temba-field-config.test.ts +152 -0
- package/test/temba-flow-editor-node.test.ts +18 -18
- package/test/temba-node-editor.test.ts +353 -0
- package/test/temba-select.test.ts +127 -0
- package/test-assets/contacts/history.json +11 -33
- package/web-dev-server.config.mjs +34 -0
- package/.github/workflows/coverage.yml +0 -80
- package/demo/sticky-note-demo.html +0 -155
- package/out-tsc/src/flow/EditorNode.js.map +0 -1
- package/out-tsc/src/flow/render.js +0 -358
- package/out-tsc/src/flow/render.js.map +0 -1
- package/out-tsc/test/temba-flow-render.test.js +0 -794
- package/out-tsc/test/temba-flow-render.test.js.map +0 -1
- package/src/flow/render.ts +0 -443
- package/test/temba-flow-render.test.ts +0 -1003
|
@@ -1,794 +0,0 @@
|
|
|
1
|
-
import { html, fixture, expect } from '@open-wc/testing';
|
|
2
|
-
import { renderAddContactUrn, renderAddInputLabels, renderAddToGroups, renderCallClassifier, renderCallLLM, renderCallResthook, renderCallWebhook, renderEnterFlow, renderOpenTicket, renderPlayAudio, renderRemoveFromGroups, renderRequestOptin, renderSayMsg, renderSendBroadcast, renderSendEmail, renderSendMsg, renderSetContactChannel, renderSetContactField, renderSetContactLanguage, renderSetContactName, renderSetContactStatus, renderSetRunResult, renderStartSession, renderTransferAirtime, renderWaitForAudio, renderWaitForDigits, renderWaitForImage, renderWaitForLocation, renderWaitForMenu, renderWaitForResponse, renderWaitForVideo } from '../src/flow/render';
|
|
3
|
-
describe('Flow Render Functions', () => {
|
|
4
|
-
const mockNode = {
|
|
5
|
-
uuid: 'test-node-uuid',
|
|
6
|
-
actions: [],
|
|
7
|
-
exits: []
|
|
8
|
-
};
|
|
9
|
-
describe('renderSendMsg', () => {
|
|
10
|
-
it('renders message text with line breaks', async () => {
|
|
11
|
-
const action = {
|
|
12
|
-
type: 'send_msg',
|
|
13
|
-
uuid: 'action-uuid-1',
|
|
14
|
-
text: 'Hello world\nThis is a new line',
|
|
15
|
-
quick_replies: []
|
|
16
|
-
};
|
|
17
|
-
const result = renderSendMsg(mockNode, action);
|
|
18
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
19
|
-
expect(container.innerHTML).to.contain('Hello world<br>This is a new line');
|
|
20
|
-
});
|
|
21
|
-
it('renders quick replies when present', async () => {
|
|
22
|
-
const action = {
|
|
23
|
-
type: 'send_msg',
|
|
24
|
-
uuid: 'action-uuid-2',
|
|
25
|
-
text: 'Choose an option:',
|
|
26
|
-
quick_replies: ['Yes', 'No', 'Maybe']
|
|
27
|
-
};
|
|
28
|
-
const result = renderSendMsg(mockNode, action);
|
|
29
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
30
|
-
expect(container.innerHTML).to.contain('Choose an option:');
|
|
31
|
-
expect(container.innerHTML).to.contain('quick-replies');
|
|
32
|
-
expect(container.innerHTML).to.contain('Yes');
|
|
33
|
-
expect(container.innerHTML).to.contain('No');
|
|
34
|
-
expect(container.innerHTML).to.contain('Maybe');
|
|
35
|
-
});
|
|
36
|
-
it('renders without quick replies when none provided', async () => {
|
|
37
|
-
const action = {
|
|
38
|
-
type: 'send_msg',
|
|
39
|
-
uuid: 'action-uuid-3',
|
|
40
|
-
text: 'Simple message',
|
|
41
|
-
quick_replies: []
|
|
42
|
-
};
|
|
43
|
-
const result = renderSendMsg(mockNode, action);
|
|
44
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
45
|
-
expect(container.innerHTML).to.contain('Simple message');
|
|
46
|
-
expect(container.innerHTML).to.not.contain('quick-replies');
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
describe('renderSetContactName', () => {
|
|
50
|
-
it('renders contact name setting', async () => {
|
|
51
|
-
const action = {
|
|
52
|
-
type: 'set_contact_name',
|
|
53
|
-
uuid: 'action-uuid-4',
|
|
54
|
-
name: 'John Doe'
|
|
55
|
-
};
|
|
56
|
-
const result = renderSetContactName(mockNode, action);
|
|
57
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
58
|
-
expect(container.textContent).to.contain('Set contact name to');
|
|
59
|
-
expect(container.textContent).to.contain('John Doe');
|
|
60
|
-
expect(container.querySelector('b')).to.exist;
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
describe('renderSetRunResult', () => {
|
|
64
|
-
it('renders run result setting', async () => {
|
|
65
|
-
const action = {
|
|
66
|
-
type: 'set_run_result',
|
|
67
|
-
uuid: 'action-uuid-5',
|
|
68
|
-
category: 'success',
|
|
69
|
-
name: 'favorite_color',
|
|
70
|
-
value: 'blue'
|
|
71
|
-
};
|
|
72
|
-
const result = renderSetRunResult(mockNode, action);
|
|
73
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
74
|
-
expect(container.textContent).to.contain('Save blue as');
|
|
75
|
-
expect(container.textContent).to.contain('favorite_color');
|
|
76
|
-
expect(container.querySelector('b')).to.exist;
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
describe('renderCallWebhook', () => {
|
|
80
|
-
it('renders webhook URL', async () => {
|
|
81
|
-
const action = {
|
|
82
|
-
type: 'call_webhook',
|
|
83
|
-
uuid: 'action-uuid-6',
|
|
84
|
-
url: 'https://example.com/webhook'
|
|
85
|
-
};
|
|
86
|
-
const result = renderCallWebhook(mockNode, action);
|
|
87
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
88
|
-
expect(container.innerHTML).to.contain('https://example.com/webhook');
|
|
89
|
-
expect(container.querySelector('div')).to.have.style('word-break', 'break-all');
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
describe('renderAddToGroups', () => {
|
|
93
|
-
it('renders groups with icons', async () => {
|
|
94
|
-
const action = {
|
|
95
|
-
type: 'add_contact_groups',
|
|
96
|
-
uuid: 'action-uuid-7',
|
|
97
|
-
groups: [
|
|
98
|
-
{
|
|
99
|
-
uuid: 'group1',
|
|
100
|
-
name: 'VIP Customers',
|
|
101
|
-
status: 'active',
|
|
102
|
-
system: false,
|
|
103
|
-
query: '',
|
|
104
|
-
count: 10
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
uuid: 'group2',
|
|
108
|
-
name: 'Newsletter Subscribers',
|
|
109
|
-
status: 'active',
|
|
110
|
-
system: false,
|
|
111
|
-
query: '',
|
|
112
|
-
count: 25
|
|
113
|
-
}
|
|
114
|
-
]
|
|
115
|
-
};
|
|
116
|
-
const result = renderAddToGroups(mockNode, action);
|
|
117
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
118
|
-
expect(container.innerHTML).to.contain('VIP Customers');
|
|
119
|
-
expect(container.innerHTML).to.contain('Newsletter Subscribers');
|
|
120
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(2);
|
|
121
|
-
const icons = container.querySelectorAll('temba-icon');
|
|
122
|
-
icons.forEach((icon) => {
|
|
123
|
-
expect(icon.getAttribute('name')).to.equal('group');
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
it('renders empty groups array', async () => {
|
|
127
|
-
const action = {
|
|
128
|
-
type: 'add_contact_groups',
|
|
129
|
-
uuid: 'action-uuid-8',
|
|
130
|
-
groups: []
|
|
131
|
-
};
|
|
132
|
-
const result = renderAddToGroups(mockNode, action);
|
|
133
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
134
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(0);
|
|
135
|
-
});
|
|
136
|
-
it('renders groups without icons when undefined', async () => {
|
|
137
|
-
// Test the renderNamedObjects function without an icon parameter
|
|
138
|
-
const action = {
|
|
139
|
-
type: 'add_contact_groups',
|
|
140
|
-
uuid: 'action-uuid-9',
|
|
141
|
-
groups: [
|
|
142
|
-
{
|
|
143
|
-
uuid: 'group1',
|
|
144
|
-
name: 'Test Group',
|
|
145
|
-
status: 'active',
|
|
146
|
-
system: false,
|
|
147
|
-
query: '',
|
|
148
|
-
count: 5
|
|
149
|
-
}
|
|
150
|
-
]
|
|
151
|
-
};
|
|
152
|
-
// Create a test version that calls renderNamedObjects without icon
|
|
153
|
-
// to cover the null case in the render.ts file
|
|
154
|
-
const namedObjects = action.groups;
|
|
155
|
-
// Create a test version that calls renderNamedObjects without icon
|
|
156
|
-
const testRender = (assets) => {
|
|
157
|
-
return assets.map((asset) => {
|
|
158
|
-
return html `<div style="display:flex;items-align:center">
|
|
159
|
-
${null /* This should trigger the null branch */}
|
|
160
|
-
<div>${asset.name}</div>
|
|
161
|
-
</div>`;
|
|
162
|
-
});
|
|
163
|
-
};
|
|
164
|
-
const result = testRender(namedObjects);
|
|
165
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
166
|
-
expect(container.innerHTML).to.contain('Test Group');
|
|
167
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(0);
|
|
168
|
-
});
|
|
169
|
-
it('renders groups with limit - shows +X more for 5+ items', async () => {
|
|
170
|
-
const action = {
|
|
171
|
-
type: 'add_contact_groups',
|
|
172
|
-
uuid: 'action-uuid-9b',
|
|
173
|
-
groups: [
|
|
174
|
-
{
|
|
175
|
-
uuid: 'group1',
|
|
176
|
-
name: 'Group 1',
|
|
177
|
-
status: 'active',
|
|
178
|
-
system: false,
|
|
179
|
-
query: '',
|
|
180
|
-
count: 1
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
uuid: 'group2',
|
|
184
|
-
name: 'Group 2',
|
|
185
|
-
status: 'active',
|
|
186
|
-
system: false,
|
|
187
|
-
query: '',
|
|
188
|
-
count: 1
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
uuid: 'group3',
|
|
192
|
-
name: 'Group 3',
|
|
193
|
-
status: 'active',
|
|
194
|
-
system: false,
|
|
195
|
-
query: '',
|
|
196
|
-
count: 1
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
uuid: 'group4',
|
|
200
|
-
name: 'Group 4',
|
|
201
|
-
status: 'active',
|
|
202
|
-
system: false,
|
|
203
|
-
query: '',
|
|
204
|
-
count: 1
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
uuid: 'group5',
|
|
208
|
-
name: 'Group 5',
|
|
209
|
-
status: 'active',
|
|
210
|
-
system: false,
|
|
211
|
-
query: '',
|
|
212
|
-
count: 1
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
};
|
|
216
|
-
const result = renderAddToGroups(mockNode, action);
|
|
217
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
218
|
-
expect(container.textContent).to.contain('Group 1');
|
|
219
|
-
expect(container.textContent).to.contain('Group 2');
|
|
220
|
-
expect(container.textContent).to.contain('Group 3');
|
|
221
|
-
expect(container.textContent).to.contain('+2 more');
|
|
222
|
-
expect(container.textContent).to.not.contain('Group 4');
|
|
223
|
-
expect(container.textContent).to.not.contain('Group 5');
|
|
224
|
-
});
|
|
225
|
-
it('renders all 4 groups when exactly 4 items', async () => {
|
|
226
|
-
const action = {
|
|
227
|
-
type: 'add_contact_groups',
|
|
228
|
-
uuid: 'action-uuid-9c',
|
|
229
|
-
groups: [
|
|
230
|
-
{
|
|
231
|
-
uuid: 'group1',
|
|
232
|
-
name: 'Group 1',
|
|
233
|
-
status: 'active',
|
|
234
|
-
system: false,
|
|
235
|
-
query: '',
|
|
236
|
-
count: 1
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
uuid: 'group2',
|
|
240
|
-
name: 'Group 2',
|
|
241
|
-
status: 'active',
|
|
242
|
-
system: false,
|
|
243
|
-
query: '',
|
|
244
|
-
count: 1
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
uuid: 'group3',
|
|
248
|
-
name: 'Group 3',
|
|
249
|
-
status: 'active',
|
|
250
|
-
system: false,
|
|
251
|
-
query: '',
|
|
252
|
-
count: 1
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
uuid: 'group4',
|
|
256
|
-
name: 'Group 4',
|
|
257
|
-
status: 'active',
|
|
258
|
-
system: false,
|
|
259
|
-
query: '',
|
|
260
|
-
count: 1
|
|
261
|
-
}
|
|
262
|
-
]
|
|
263
|
-
};
|
|
264
|
-
const result = renderAddToGroups(mockNode, action);
|
|
265
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
266
|
-
expect(container.textContent).to.contain('Group 1');
|
|
267
|
-
expect(container.textContent).to.contain('Group 2');
|
|
268
|
-
expect(container.textContent).to.contain('Group 3');
|
|
269
|
-
expect(container.textContent).to.contain('Group 4');
|
|
270
|
-
expect(container.textContent).to.not.contain('+');
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
describe('renderRemoveFromGroups', () => {
|
|
274
|
-
it('renders groups with icons for removal', async () => {
|
|
275
|
-
const action = {
|
|
276
|
-
type: 'remove_contact_groups',
|
|
277
|
-
uuid: 'action-uuid-10',
|
|
278
|
-
groups: [
|
|
279
|
-
{
|
|
280
|
-
uuid: 'group1',
|
|
281
|
-
name: 'VIP Customers',
|
|
282
|
-
status: 'active',
|
|
283
|
-
system: false,
|
|
284
|
-
query: '',
|
|
285
|
-
count: 10
|
|
286
|
-
}
|
|
287
|
-
]
|
|
288
|
-
};
|
|
289
|
-
const result = renderRemoveFromGroups(mockNode, action);
|
|
290
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
291
|
-
expect(container.innerHTML).to.contain('VIP Customers');
|
|
292
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(1);
|
|
293
|
-
const icon = container.querySelector('temba-icon');
|
|
294
|
-
expect(icon === null || icon === void 0 ? void 0 : icon.getAttribute('name')).to.equal('group');
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
describe('renderSetContactField', () => {
|
|
298
|
-
it('renders contact field setting', async () => {
|
|
299
|
-
const action = {
|
|
300
|
-
type: 'set_contact_field',
|
|
301
|
-
uuid: 'action-uuid-11',
|
|
302
|
-
field: { uuid: 'field1', name: 'Favorite Color' },
|
|
303
|
-
value: 'Blue'
|
|
304
|
-
};
|
|
305
|
-
const result = renderSetContactField(mockNode, action);
|
|
306
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
307
|
-
expect(container.textContent).to.contain('Set');
|
|
308
|
-
expect(container.textContent).to.contain('Favorite Color');
|
|
309
|
-
expect(container.textContent).to.contain('to');
|
|
310
|
-
expect(container.textContent).to.contain('Blue');
|
|
311
|
-
expect(container.querySelectorAll('b')).to.have.length(2);
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
describe('renderSetContactLanguage', () => {
|
|
315
|
-
it('renders contact language setting', async () => {
|
|
316
|
-
const action = {
|
|
317
|
-
type: 'set_contact_language',
|
|
318
|
-
uuid: 'action-uuid-12',
|
|
319
|
-
language: 'Spanish'
|
|
320
|
-
};
|
|
321
|
-
const result = renderSetContactLanguage(mockNode, action);
|
|
322
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
323
|
-
expect(container.textContent).to.contain('Set contact language to');
|
|
324
|
-
expect(container.textContent).to.contain('Spanish');
|
|
325
|
-
expect(container.querySelector('b')).to.exist;
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
describe('renderSetContactStatus', () => {
|
|
329
|
-
it('renders contact status setting', async () => {
|
|
330
|
-
const action = {
|
|
331
|
-
type: 'set_contact_status',
|
|
332
|
-
uuid: 'action-uuid-13',
|
|
333
|
-
status: 'blocked'
|
|
334
|
-
};
|
|
335
|
-
const result = renderSetContactStatus(mockNode, action);
|
|
336
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
337
|
-
expect(container.textContent).to.contain('Set contact status to');
|
|
338
|
-
expect(container.textContent).to.contain('blocked');
|
|
339
|
-
expect(container.querySelector('b')).to.exist;
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
describe('renderAddContactUrn', () => {
|
|
343
|
-
it('renders URN addition with friendly scheme names', async () => {
|
|
344
|
-
var _a;
|
|
345
|
-
const action = {
|
|
346
|
-
type: 'add_contact_urn',
|
|
347
|
-
uuid: 'action-uuid-14',
|
|
348
|
-
scheme: 'tel',
|
|
349
|
-
path: '+1234567890'
|
|
350
|
-
};
|
|
351
|
-
const result = renderAddContactUrn(mockNode, action);
|
|
352
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
353
|
-
expect(container.textContent).to.contain('Add');
|
|
354
|
-
expect(container.textContent).to.contain('Phone Number');
|
|
355
|
-
expect(container.textContent).to.contain('+1234567890');
|
|
356
|
-
// Only the phone number should be bold, not the scheme
|
|
357
|
-
expect(container.querySelectorAll('b')).to.have.length(1);
|
|
358
|
-
expect((_a = container.querySelector('b')) === null || _a === void 0 ? void 0 : _a.textContent).to.equal('+1234567890');
|
|
359
|
-
});
|
|
360
|
-
it('renders URN addition with unmapped scheme', async () => {
|
|
361
|
-
var _a;
|
|
362
|
-
const action = {
|
|
363
|
-
type: 'add_contact_urn',
|
|
364
|
-
uuid: 'action-uuid-14b',
|
|
365
|
-
scheme: 'unknown',
|
|
366
|
-
path: 'test123'
|
|
367
|
-
};
|
|
368
|
-
const result = renderAddContactUrn(mockNode, action);
|
|
369
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
370
|
-
expect(container.textContent).to.contain('Add');
|
|
371
|
-
expect(container.textContent).to.contain('unknown');
|
|
372
|
-
expect(container.textContent).to.contain('test123');
|
|
373
|
-
// Only the URN path should be bold
|
|
374
|
-
expect(container.querySelectorAll('b')).to.have.length(1);
|
|
375
|
-
expect((_a = container.querySelector('b')) === null || _a === void 0 ? void 0 : _a.textContent).to.equal('test123');
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
describe('renderSendEmail', () => {
|
|
379
|
-
it('renders email with subject and body', async () => {
|
|
380
|
-
const action = {
|
|
381
|
-
type: 'send_email',
|
|
382
|
-
uuid: 'action-uuid-15',
|
|
383
|
-
subject: 'Welcome!',
|
|
384
|
-
body: 'Thanks for signing up',
|
|
385
|
-
addresses: ['user@example.com', 'admin@example.com']
|
|
386
|
-
};
|
|
387
|
-
const result = renderSendEmail(mockNode, action);
|
|
388
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
389
|
-
// No longer expects "Send email to" prefix
|
|
390
|
-
expect(container.textContent).to.contain('user@example.com, admin@example.com');
|
|
391
|
-
expect(container.textContent).to.contain('Welcome!');
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
|
-
describe('renderSendBroadcast', () => {
|
|
395
|
-
it('renders broadcast with groups and contacts', async () => {
|
|
396
|
-
const action = {
|
|
397
|
-
type: 'send_broadcast',
|
|
398
|
-
uuid: 'action-uuid-16',
|
|
399
|
-
text: 'Important announcement',
|
|
400
|
-
groups: [
|
|
401
|
-
{
|
|
402
|
-
uuid: 'group1',
|
|
403
|
-
name: 'VIP Customers',
|
|
404
|
-
status: 'active',
|
|
405
|
-
system: false,
|
|
406
|
-
query: '',
|
|
407
|
-
count: 10
|
|
408
|
-
}
|
|
409
|
-
],
|
|
410
|
-
contacts: [{ uuid: 'contact1', name: 'John Doe' }]
|
|
411
|
-
};
|
|
412
|
-
const result = renderSendBroadcast(mockNode, action);
|
|
413
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
414
|
-
expect(container.textContent).to.contain('Important announcement');
|
|
415
|
-
expect(container.textContent).to.contain('Groups:');
|
|
416
|
-
expect(container.textContent).to.contain('VIP Customers');
|
|
417
|
-
expect(container.textContent).to.contain('Contacts:');
|
|
418
|
-
expect(container.textContent).to.contain('John Doe');
|
|
419
|
-
});
|
|
420
|
-
it('renders broadcast with text only', async () => {
|
|
421
|
-
const action = {
|
|
422
|
-
type: 'send_broadcast',
|
|
423
|
-
uuid: 'action-uuid-17',
|
|
424
|
-
text: 'Simple broadcast',
|
|
425
|
-
groups: [],
|
|
426
|
-
contacts: []
|
|
427
|
-
};
|
|
428
|
-
const result = renderSendBroadcast(mockNode, action);
|
|
429
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
430
|
-
expect(container.textContent).to.contain('Simple broadcast');
|
|
431
|
-
expect(container.textContent).to.not.contain('Groups:');
|
|
432
|
-
expect(container.textContent).to.not.contain('Contacts:');
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
describe('renderEnterFlow', () => {
|
|
436
|
-
it('renders flow entry', async () => {
|
|
437
|
-
const action = {
|
|
438
|
-
type: 'enter_flow',
|
|
439
|
-
uuid: 'action-uuid-18',
|
|
440
|
-
flow: { uuid: 'flow1', name: 'Registration Flow' }
|
|
441
|
-
};
|
|
442
|
-
const result = renderEnterFlow(mockNode, action);
|
|
443
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
444
|
-
expect(container.textContent).to.contain('Enter flow');
|
|
445
|
-
expect(container.textContent).to.contain('Registration Flow');
|
|
446
|
-
expect(container.querySelector('b')).to.exist;
|
|
447
|
-
});
|
|
448
|
-
});
|
|
449
|
-
describe('renderStartSession', () => {
|
|
450
|
-
it('renders session start with groups and contacts', async () => {
|
|
451
|
-
const action = {
|
|
452
|
-
type: 'start_session',
|
|
453
|
-
uuid: 'action-uuid-19',
|
|
454
|
-
flow: { uuid: 'flow1', name: 'Survey Flow' },
|
|
455
|
-
groups: [
|
|
456
|
-
{
|
|
457
|
-
uuid: 'group1',
|
|
458
|
-
name: 'Subscribers',
|
|
459
|
-
status: 'active',
|
|
460
|
-
system: false,
|
|
461
|
-
query: '',
|
|
462
|
-
count: 50
|
|
463
|
-
}
|
|
464
|
-
],
|
|
465
|
-
contacts: [{ uuid: 'contact1', name: 'Jane Smith' }]
|
|
466
|
-
};
|
|
467
|
-
const result = renderStartSession(mockNode, action);
|
|
468
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
469
|
-
expect(container.textContent).to.contain('Subscribers');
|
|
470
|
-
expect(container.textContent).to.contain('Jane Smith');
|
|
471
|
-
expect(container.textContent).to.contain('Survey Flow');
|
|
472
|
-
});
|
|
473
|
-
});
|
|
474
|
-
describe('renderTransferAirtime', () => {
|
|
475
|
-
it('renders airtime transfer', async () => {
|
|
476
|
-
const action = {
|
|
477
|
-
type: 'transfer_airtime',
|
|
478
|
-
uuid: 'action-uuid-20',
|
|
479
|
-
amounts: [100, 200, 500],
|
|
480
|
-
result_name: 'airtime_result'
|
|
481
|
-
};
|
|
482
|
-
const result = renderTransferAirtime(mockNode, action);
|
|
483
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
484
|
-
expect(container.textContent).to.contain('Transfer airtime amounts:');
|
|
485
|
-
expect(container.textContent).to.contain('100, 200, 500');
|
|
486
|
-
expect(container.textContent).to.contain('Save result as');
|
|
487
|
-
expect(container.textContent).to.contain('airtime_result');
|
|
488
|
-
});
|
|
489
|
-
});
|
|
490
|
-
describe('renderCallClassifier', () => {
|
|
491
|
-
it('renders classifier call', async () => {
|
|
492
|
-
const action = {
|
|
493
|
-
type: 'call_classifier',
|
|
494
|
-
uuid: 'action-uuid-21',
|
|
495
|
-
classifier: { uuid: 'classifier1', name: 'Intent Classifier' },
|
|
496
|
-
input: 'User message text',
|
|
497
|
-
result_name: 'intent_result'
|
|
498
|
-
};
|
|
499
|
-
const result = renderCallClassifier(mockNode, action);
|
|
500
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
501
|
-
expect(container.textContent).to.contain('Call classifier');
|
|
502
|
-
expect(container.textContent).to.contain('Intent Classifier');
|
|
503
|
-
expect(container.textContent).to.contain('Input:');
|
|
504
|
-
expect(container.textContent).to.contain('User message text');
|
|
505
|
-
expect(container.textContent).to.contain('Save result as');
|
|
506
|
-
expect(container.textContent).to.contain('intent_result');
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
describe('renderCallResthook', () => {
|
|
510
|
-
it('renders resthook call', async () => {
|
|
511
|
-
const action = {
|
|
512
|
-
type: 'call_resthook',
|
|
513
|
-
uuid: 'action-uuid-22',
|
|
514
|
-
resthook: 'survey-complete',
|
|
515
|
-
result_name: 'webhook_result'
|
|
516
|
-
};
|
|
517
|
-
const result = renderCallResthook(mockNode, action);
|
|
518
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
519
|
-
expect(container.textContent).to.contain('Call resthook');
|
|
520
|
-
expect(container.textContent).to.contain('survey-complete');
|
|
521
|
-
expect(container.textContent).to.contain('Save result as');
|
|
522
|
-
expect(container.textContent).to.contain('webhook_result');
|
|
523
|
-
});
|
|
524
|
-
});
|
|
525
|
-
describe('renderCallLLM', () => {
|
|
526
|
-
it('renders LLM call', async () => {
|
|
527
|
-
const action = {
|
|
528
|
-
type: 'call_llm',
|
|
529
|
-
uuid: 'action-uuid-23',
|
|
530
|
-
llm: { uuid: 'llm1', name: 'GPT-4' },
|
|
531
|
-
instructions: 'Analyze this text',
|
|
532
|
-
result_name: 'ai_result'
|
|
533
|
-
};
|
|
534
|
-
const result = renderCallLLM(mockNode, action);
|
|
535
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
536
|
-
// No longer expects "Call AI" prefix
|
|
537
|
-
expect(container.textContent).to.contain('GPT-4');
|
|
538
|
-
expect(container.textContent).to.contain('Analyze this text');
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
describe('renderOpenTicket', () => {
|
|
542
|
-
it('renders ticket with assignee and topic', async () => {
|
|
543
|
-
const action = {
|
|
544
|
-
type: 'open_ticket',
|
|
545
|
-
uuid: 'action-uuid-24',
|
|
546
|
-
subject: 'Support Request',
|
|
547
|
-
body: 'Customer needs help',
|
|
548
|
-
assignee: { uuid: 'user1', name: 'Support Agent' },
|
|
549
|
-
topic: { uuid: 'topic1', name: 'Technical Support' }
|
|
550
|
-
};
|
|
551
|
-
const result = renderOpenTicket(mockNode, action);
|
|
552
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
553
|
-
// No longer expects subject
|
|
554
|
-
expect(container.textContent).to.contain('Customer needs help');
|
|
555
|
-
expect(container.textContent).to.contain('Support Agent');
|
|
556
|
-
expect(container.textContent).to.contain('Technical Support');
|
|
557
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(2);
|
|
558
|
-
});
|
|
559
|
-
it('renders ticket without assignee or topic', async () => {
|
|
560
|
-
const action = {
|
|
561
|
-
type: 'open_ticket',
|
|
562
|
-
uuid: 'action-uuid-25',
|
|
563
|
-
subject: 'Basic Ticket',
|
|
564
|
-
body: 'Simple ticket content'
|
|
565
|
-
};
|
|
566
|
-
const result = renderOpenTicket(mockNode, action);
|
|
567
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
568
|
-
// No longer expects subject
|
|
569
|
-
expect(container.textContent).to.contain('Simple ticket content');
|
|
570
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(0);
|
|
571
|
-
});
|
|
572
|
-
});
|
|
573
|
-
describe('renderRequestOptin', () => {
|
|
574
|
-
it('renders optin request', async () => {
|
|
575
|
-
const action = {
|
|
576
|
-
type: 'request_optin',
|
|
577
|
-
uuid: 'action-uuid-26',
|
|
578
|
-
optin: { uuid: 'optin1', name: 'Newsletter Subscription' }
|
|
579
|
-
};
|
|
580
|
-
const result = renderRequestOptin(mockNode, action);
|
|
581
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
582
|
-
expect(container.textContent).to.contain('Request opt-in for');
|
|
583
|
-
expect(container.textContent).to.contain('Newsletter Subscription');
|
|
584
|
-
expect(container.querySelector('b')).to.exist;
|
|
585
|
-
});
|
|
586
|
-
});
|
|
587
|
-
describe('renderAddInputLabels', () => {
|
|
588
|
-
it('renders input labels', async () => {
|
|
589
|
-
const action = {
|
|
590
|
-
type: 'add_input_labels',
|
|
591
|
-
uuid: 'action-uuid-27',
|
|
592
|
-
labels: [
|
|
593
|
-
{ uuid: 'label1', name: 'Important' },
|
|
594
|
-
{ uuid: 'label2', name: 'Customer Service' }
|
|
595
|
-
]
|
|
596
|
-
};
|
|
597
|
-
const result = renderAddInputLabels(mockNode, action);
|
|
598
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
599
|
-
// No longer expects "Add labels to input:" prefix
|
|
600
|
-
expect(container.textContent).to.contain('Important');
|
|
601
|
-
expect(container.textContent).to.contain('Customer Service');
|
|
602
|
-
expect(container.querySelectorAll('temba-icon')).to.have.length(2);
|
|
603
|
-
});
|
|
604
|
-
});
|
|
605
|
-
describe('renderSayMsg', () => {
|
|
606
|
-
it('renders voice message with audio URL', async () => {
|
|
607
|
-
var _a;
|
|
608
|
-
const action = {
|
|
609
|
-
type: 'say_msg',
|
|
610
|
-
uuid: 'action-uuid-28',
|
|
611
|
-
text: 'Welcome to our service',
|
|
612
|
-
audio_url: 'https://example.com/audio.mp3'
|
|
613
|
-
};
|
|
614
|
-
const result = renderSayMsg(mockNode, action);
|
|
615
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
616
|
-
expect(container.textContent).to.contain('Welcome to our service');
|
|
617
|
-
expect(container.innerHTML).to.contain('https://example.com/audio.mp3');
|
|
618
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
619
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('audio');
|
|
620
|
-
});
|
|
621
|
-
it('renders voice message without audio URL', async () => {
|
|
622
|
-
const action = {
|
|
623
|
-
type: 'say_msg',
|
|
624
|
-
uuid: 'action-uuid-29',
|
|
625
|
-
text: 'Text only message'
|
|
626
|
-
};
|
|
627
|
-
const result = renderSayMsg(mockNode, action);
|
|
628
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
629
|
-
expect(container.textContent).to.contain('Text only message');
|
|
630
|
-
expect(container.querySelector('temba-icon')).to.not.exist;
|
|
631
|
-
});
|
|
632
|
-
});
|
|
633
|
-
describe('renderPlayAudio', () => {
|
|
634
|
-
it('renders audio playback', async () => {
|
|
635
|
-
var _a;
|
|
636
|
-
const action = {
|
|
637
|
-
type: 'play_audio',
|
|
638
|
-
uuid: 'action-uuid-30',
|
|
639
|
-
audio_url: 'https://example.com/music.mp3'
|
|
640
|
-
};
|
|
641
|
-
const result = renderPlayAudio(mockNode, action);
|
|
642
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
643
|
-
expect(container.innerHTML).to.contain('https://example.com/music.mp3');
|
|
644
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
645
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('audio');
|
|
646
|
-
});
|
|
647
|
-
});
|
|
648
|
-
describe('renderSetContactChannel', () => {
|
|
649
|
-
it('renders contact channel setting', async () => {
|
|
650
|
-
const action = {
|
|
651
|
-
type: 'set_contact_channel',
|
|
652
|
-
uuid: 'action-uuid-31',
|
|
653
|
-
channel: { uuid: 'channel1', name: 'WhatsApp Channel' }
|
|
654
|
-
};
|
|
655
|
-
const result = renderSetContactChannel(mockNode, action);
|
|
656
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
657
|
-
expect(container.textContent).to.contain('Set contact channel to');
|
|
658
|
-
expect(container.textContent).to.contain('WhatsApp Channel');
|
|
659
|
-
expect(container.querySelector('b')).to.exist;
|
|
660
|
-
});
|
|
661
|
-
});
|
|
662
|
-
describe('renderWaitForResponse', () => {
|
|
663
|
-
it('renders wait for response with timeout', async () => {
|
|
664
|
-
const action = {
|
|
665
|
-
type: 'wait_for_response',
|
|
666
|
-
uuid: 'action-uuid-32',
|
|
667
|
-
timeout: 300
|
|
668
|
-
};
|
|
669
|
-
const result = renderWaitForResponse(mockNode, action);
|
|
670
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
671
|
-
expect(container.textContent).to.contain('Wait for message response');
|
|
672
|
-
expect(container.textContent).to.contain('Timeout after');
|
|
673
|
-
expect(container.textContent).to.contain('300');
|
|
674
|
-
expect(container.textContent).to.contain('seconds');
|
|
675
|
-
});
|
|
676
|
-
it('renders wait for response without timeout', async () => {
|
|
677
|
-
const action = {
|
|
678
|
-
type: 'wait_for_response',
|
|
679
|
-
uuid: 'action-uuid-33'
|
|
680
|
-
};
|
|
681
|
-
const result = renderWaitForResponse(mockNode, action);
|
|
682
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
683
|
-
expect(container.textContent).to.contain('Wait for message response');
|
|
684
|
-
expect(container.textContent).to.not.contain('Timeout');
|
|
685
|
-
});
|
|
686
|
-
});
|
|
687
|
-
describe('renderWaitForMenu', () => {
|
|
688
|
-
it('renders wait for menu with timeout', async () => {
|
|
689
|
-
const action = {
|
|
690
|
-
type: 'wait_for_menu',
|
|
691
|
-
uuid: 'action-uuid-34',
|
|
692
|
-
menu: { uuid: 'menu1', name: 'Main Menu' },
|
|
693
|
-
timeout: 120
|
|
694
|
-
};
|
|
695
|
-
const result = renderWaitForMenu(mockNode, action);
|
|
696
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
697
|
-
expect(container.textContent).to.contain('Wait for menu selection:');
|
|
698
|
-
expect(container.textContent).to.contain('Main Menu');
|
|
699
|
-
expect(container.textContent).to.contain('Timeout after');
|
|
700
|
-
expect(container.textContent).to.contain('120');
|
|
701
|
-
});
|
|
702
|
-
});
|
|
703
|
-
describe('renderWaitForDigits', () => {
|
|
704
|
-
it('renders wait for single digit', async () => {
|
|
705
|
-
const action = {
|
|
706
|
-
type: 'wait_for_digits',
|
|
707
|
-
uuid: 'action-uuid-35',
|
|
708
|
-
count: 1,
|
|
709
|
-
timeout: 60
|
|
710
|
-
};
|
|
711
|
-
const result = renderWaitForDigits(mockNode, action);
|
|
712
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
713
|
-
expect(container.textContent).to.contain('Wait for');
|
|
714
|
-
expect(container.textContent).to.contain('1');
|
|
715
|
-
expect(container.textContent).to.contain('digit');
|
|
716
|
-
expect(container.textContent).to.not.contain('digits');
|
|
717
|
-
expect(container.textContent).to.contain('Timeout after 60');
|
|
718
|
-
});
|
|
719
|
-
it('renders wait for multiple digits', async () => {
|
|
720
|
-
const action = {
|
|
721
|
-
type: 'wait_for_digits',
|
|
722
|
-
uuid: 'action-uuid-36',
|
|
723
|
-
count: 4
|
|
724
|
-
};
|
|
725
|
-
const result = renderWaitForDigits(mockNode, action);
|
|
726
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
727
|
-
expect(container.textContent).to.contain('Wait for');
|
|
728
|
-
expect(container.textContent).to.contain('4');
|
|
729
|
-
expect(container.textContent).to.contain('digits');
|
|
730
|
-
expect(container.textContent).to.not.contain('Timeout');
|
|
731
|
-
});
|
|
732
|
-
});
|
|
733
|
-
describe('renderWaitForAudio', () => {
|
|
734
|
-
it('renders wait for audio with icon', async () => {
|
|
735
|
-
var _a;
|
|
736
|
-
const action = {
|
|
737
|
-
type: 'wait_for_audio',
|
|
738
|
-
uuid: 'action-uuid-37',
|
|
739
|
-
timeout: 180
|
|
740
|
-
};
|
|
741
|
-
const result = renderWaitForAudio(mockNode, action);
|
|
742
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
743
|
-
expect(container.textContent).to.contain('Wait for audio recording');
|
|
744
|
-
expect(container.textContent).to.contain('Timeout after 180');
|
|
745
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
746
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('audio');
|
|
747
|
-
});
|
|
748
|
-
});
|
|
749
|
-
describe('renderWaitForVideo', () => {
|
|
750
|
-
it('renders wait for video with icon', async () => {
|
|
751
|
-
var _a;
|
|
752
|
-
const action = {
|
|
753
|
-
type: 'wait_for_video',
|
|
754
|
-
uuid: 'action-uuid-38'
|
|
755
|
-
};
|
|
756
|
-
const result = renderWaitForVideo(mockNode, action);
|
|
757
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
758
|
-
expect(container.textContent).to.contain('Wait for video recording');
|
|
759
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
760
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('video');
|
|
761
|
-
});
|
|
762
|
-
});
|
|
763
|
-
describe('renderWaitForImage', () => {
|
|
764
|
-
it('renders wait for image with icon', async () => {
|
|
765
|
-
var _a;
|
|
766
|
-
const action = {
|
|
767
|
-
type: 'wait_for_image',
|
|
768
|
-
uuid: 'action-uuid-39',
|
|
769
|
-
timeout: 240
|
|
770
|
-
};
|
|
771
|
-
const result = renderWaitForImage(mockNode, action);
|
|
772
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
773
|
-
expect(container.textContent).to.contain('Wait for image');
|
|
774
|
-
expect(container.textContent).to.contain('Timeout after 240');
|
|
775
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
776
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('image');
|
|
777
|
-
});
|
|
778
|
-
});
|
|
779
|
-
describe('renderWaitForLocation', () => {
|
|
780
|
-
it('renders wait for location with icon', async () => {
|
|
781
|
-
var _a;
|
|
782
|
-
const action = {
|
|
783
|
-
type: 'wait_for_location',
|
|
784
|
-
uuid: 'action-uuid-40'
|
|
785
|
-
};
|
|
786
|
-
const result = renderWaitForLocation(mockNode, action);
|
|
787
|
-
const container = await fixture(html `<div>${result}</div>`);
|
|
788
|
-
expect(container.textContent).to.contain('Wait for location');
|
|
789
|
-
expect(container.querySelector('temba-icon')).to.exist;
|
|
790
|
-
expect((_a = container.querySelector('temba-icon')) === null || _a === void 0 ? void 0 : _a.getAttribute('name')).to.equal('location');
|
|
791
|
-
});
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
//# sourceMappingURL=temba-flow-render.test.js.map
|