@nyaruka/temba-components 0.129.2 → 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 +141 -8
- package/CHANGELOG.md +40 -0
- package/README.md +6 -0
- package/check-coverage.js +133 -0
- package/demo/data/flows/sample-flow.json +158 -128
- package/demo/field-config-demo.html +135 -0
- package/dist/temba-components.js +1750 -751
- package/dist/temba-components.js.map +1 -1
- package/docs/ActionEditor-Migration.md +118 -0
- package/generate-coverage-badge.sh +69 -0
- package/out-tsc/src/{vectoricon/index.js → Icons.js} +1 -1
- package/out-tsc/src/Icons.js.map +1 -0
- package/out-tsc/src/display/Alert.js.map +1 -0
- package/out-tsc/src/display/Anchor.js.map +1 -0
- package/out-tsc/src/display/Button.js.map +1 -0
- package/out-tsc/src/{charcount → display}/CharCount.js +159 -2
- package/out-tsc/src/display/CharCount.js.map +1 -0
- package/out-tsc/src/display/Chat.js.map +1 -0
- package/out-tsc/src/display/ContactName.js.map +1 -0
- package/out-tsc/src/display/ContactUrn.js.map +1 -0
- package/out-tsc/src/display/Dropdown.js.map +1 -0
- package/out-tsc/src/{vectoricon/VectorIcon.js → display/Icon.js} +2 -2
- package/out-tsc/src/display/Icon.js.map +1 -0
- package/out-tsc/src/display/Label.js.map +1 -0
- package/out-tsc/src/{leafletmap → display}/LeafletMap.js +16 -1
- package/out-tsc/src/display/LeafletMap.js.map +1 -0
- package/out-tsc/src/display/Lightbox.js.map +1 -0
- package/out-tsc/src/{loading → display}/Loading.js.map +1 -1
- package/out-tsc/src/{options → display}/Options.js.map +1 -1
- package/out-tsc/src/display/ProgressBar.js.map +1 -0
- package/out-tsc/src/display/TembaDate.js.map +1 -0
- package/out-tsc/src/display/TembaUser.js.map +1 -0
- package/out-tsc/src/display/Thumbnail.js.map +1 -0
- package/out-tsc/src/{tip → display}/Tip.js +1 -2
- package/out-tsc/src/display/Tip.js.map +1 -0
- package/out-tsc/src/display/Toast.js.map +1 -0
- package/out-tsc/src/display/sms/gsmsplitter.js.map +1 -0
- package/out-tsc/src/display/sms/gsmvalidator.js.map +1 -0
- package/out-tsc/src/display/sms/index.js.map +1 -0
- package/out-tsc/src/display/sms/unicodesplitter.js.map +1 -0
- package/out-tsc/src/events.js +2 -0
- package/out-tsc/src/events.js.map +1 -0
- package/out-tsc/src/excellent/ExcellentParser.js.map +1 -0
- package/out-tsc/src/excellent/helpers.js.map +1 -0
- package/out-tsc/src/flow/CanvasNode.js +861 -0
- package/out-tsc/src/flow/CanvasNode.js.map +1 -0
- package/out-tsc/src/flow/Editor.js +640 -143
- 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 +148 -74
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +153 -9
- package/out-tsc/src/flow/StickyNote.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 -123
- 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/{checkbox → form}/Checkbox.js +19 -4
- package/out-tsc/src/form/Checkbox.js.map +1 -0
- package/out-tsc/src/{colorpicker → form}/ColorPicker.js +1 -1
- package/out-tsc/src/form/ColorPicker.js.map +1 -0
- package/out-tsc/src/{completion → form}/Completion.js +8 -2
- package/out-tsc/src/form/Completion.js.map +1 -0
- package/out-tsc/src/{compose → form}/Compose.js +1 -1
- package/out-tsc/src/form/Compose.js.map +1 -0
- package/out-tsc/src/{contactsearch → form}/ContactSearch.js +2 -2
- package/out-tsc/src/form/ContactSearch.js.map +1 -0
- package/out-tsc/src/form/CroppieCSS.js.map +1 -0
- package/out-tsc/src/{datepicker → form}/DatePicker.js +1 -1
- package/out-tsc/src/form/DatePicker.js.map +1 -0
- package/out-tsc/src/{FormElement.js → form/FormElement.js} +1 -1
- package/out-tsc/src/form/FormElement.js.map +1 -0
- package/out-tsc/src/form/FormField.js +243 -0
- package/out-tsc/src/form/FormField.js.map +1 -0
- package/out-tsc/src/{imagepicker → form}/ImagePicker.js +2 -2
- package/out-tsc/src/form/ImagePicker.js.map +1 -0
- package/out-tsc/src/form/KeyValueEditor.js +223 -0
- package/out-tsc/src/form/KeyValueEditor.js.map +1 -0
- package/out-tsc/src/{mediapicker → form}/MediaPicker.js +1 -1
- package/out-tsc/src/form/MediaPicker.js.map +1 -0
- package/out-tsc/src/form/RangePicker.js.map +1 -0
- package/out-tsc/src/{slider → form}/TembaSlider.js +1 -1
- package/out-tsc/src/form/TembaSlider.js.map +1 -0
- package/out-tsc/src/{templates → form}/TemplateEditor.js +1 -1
- package/out-tsc/src/form/TemplateEditor.js.map +1 -0
- package/out-tsc/src/{textinput → form}/TextInput.js +3 -3
- package/out-tsc/src/form/TextInput.js.map +1 -0
- package/out-tsc/src/{omnibox → form/select}/Omnibox.js +2 -2
- package/out-tsc/src/form/select/Omnibox.js.map +1 -0
- package/out-tsc/src/{select → form/select}/PopupSelect.js +1 -1
- package/out-tsc/src/form/select/PopupSelect.js.map +1 -0
- package/out-tsc/src/{select → form/select}/Select.js +157 -113
- package/out-tsc/src/form/select/Select.js.map +1 -0
- package/out-tsc/src/{select → form/select}/UserSelect.js +1 -1
- package/out-tsc/src/form/select/UserSelect.js.map +1 -0
- package/out-tsc/src/{select → form/select}/WorkspaceSelect.js +1 -1
- package/out-tsc/src/form/select/WorkspaceSelect.js.map +1 -0
- package/out-tsc/src/interfaces.js +7 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js.map +1 -0
- package/out-tsc/src/layout/Mask.js.map +1 -0
- package/out-tsc/src/{dialog → layout}/Modax.js.map +1 -1
- package/out-tsc/src/layout/Resizer.js.map +1 -0
- package/out-tsc/src/layout/Tab.js.map +1 -0
- package/out-tsc/src/layout/TabPane.js.map +1 -0
- package/out-tsc/src/list/NotificationList.js +1 -1
- package/out-tsc/src/list/NotificationList.js.map +1 -1
- package/out-tsc/src/list/RunList.js +1 -1
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/list/ShortcutList.js.map +1 -1
- package/out-tsc/src/list/TembaMenu.js +1 -1
- package/out-tsc/src/list/TembaMenu.js.map +1 -1
- package/out-tsc/src/list/TicketList.js +1 -1
- package/out-tsc/src/list/TicketList.js.map +1 -1
- package/out-tsc/src/{aliaseditor → live}/AliasEditor.js +1 -1
- package/out-tsc/src/live/AliasEditor.js.map +1 -0
- package/out-tsc/src/{contacts → live}/ContactBadges.js +1 -1
- package/out-tsc/src/live/ContactBadges.js.map +1 -0
- package/out-tsc/src/{contacts → live}/ContactChat.js +80 -78
- package/out-tsc/src/live/ContactChat.js.map +1 -0
- package/out-tsc/src/{contacts → live}/ContactDetails.js +1 -1
- package/out-tsc/src/live/ContactDetails.js.map +1 -0
- package/out-tsc/src/{contacts → live}/ContactFieldEditor.js +2 -2
- package/out-tsc/src/live/ContactFieldEditor.js.map +1 -0
- package/out-tsc/src/live/ContactFields.js.map +1 -0
- package/out-tsc/src/live/ContactNameFetch.js.map +1 -0
- package/out-tsc/src/{contacts → live}/ContactNotepad.js +1 -1
- package/out-tsc/src/{contacts → live}/ContactNotepad.js.map +1 -1
- package/out-tsc/src/{contacts → live}/ContactPending.js +1 -1
- package/out-tsc/src/live/ContactPending.js.map +1 -0
- package/out-tsc/src/live/ContactStoreElement.js.map +1 -0
- package/out-tsc/src/live/FieldManager.js.map +1 -0
- package/out-tsc/src/live/StartProgress.js.map +1 -0
- package/out-tsc/src/live/TembaChart.js.map +1 -0
- package/out-tsc/src/store/AppState.js +54 -24
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/store/Store.js +1 -1
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/{utils/index.js → utils.js} +22 -1
- package/out-tsc/src/utils.js.map +1 -0
- package/out-tsc/src/webchat/WebChat.js +1 -1
- package/out-tsc/src/webchat/WebChat.js.map +1 -1
- package/out-tsc/temba-components.js +2 -2
- package/out-tsc/temba-components.js.map +1 -1
- package/out-tsc/temba-modules.js +63 -56
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/temba-webchat.js +2 -2
- package/out-tsc/temba-webchat.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-alert.test.js +1 -1
- package/out-tsc/test/temba-alert.test.js.map +1 -1
- package/out-tsc/test/temba-appstate-language.test.js +90 -0
- package/out-tsc/test/temba-appstate-language.test.js.map +1 -1
- package/out-tsc/test/temba-charcount.test.js.map +1 -1
- package/out-tsc/test/temba-chart.test.js +1 -1
- package/out-tsc/test/temba-chart.test.js.map +1 -1
- 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-color-picker.test.js +1 -1
- package/out-tsc/test/temba-color-picker.test.js.map +1 -1
- package/out-tsc/test/temba-completion.test.js +1 -1
- package/out-tsc/test/temba-completion.test.js.map +1 -1
- package/out-tsc/test/temba-compose.test.js +1 -1
- package/out-tsc/test/temba-compose.test.js.map +1 -1
- package/out-tsc/test/temba-contact-badges.test.js +1 -1
- package/out-tsc/test/temba-contact-badges.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +3 -1
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-contact-details.test.js +1 -1
- package/out-tsc/test/temba-contact-details.test.js.map +1 -1
- package/out-tsc/test/temba-contact-fields.test.js +1 -1
- package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
- package/out-tsc/test/temba-contact-search.test.js +1 -1
- package/out-tsc/test/temba-contact-search.test.js.map +1 -1
- package/out-tsc/test/temba-date.test.js +5 -1
- package/out-tsc/test/temba-date.test.js.map +1 -1
- package/out-tsc/test/temba-datepicker.test.js +1 -1
- package/out-tsc/test/temba-datepicker.test.js.map +1 -1
- package/out-tsc/test/temba-dialog.test.js +1 -1
- package/out-tsc/test/temba-dialog.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +1 -1
- package/out-tsc/test/temba-dropdown.test.js.map +1 -1
- package/out-tsc/test/temba-excellent-helpers.test.js +316 -0
- package/out-tsc/test/temba-excellent-helpers.test.js.map +1 -0
- 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-field-manager.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +426 -13
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +185 -0
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +113 -0
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -0
- package/out-tsc/test/temba-flow-plumber.test.js +73 -93
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-flow-self-routing.test.js +172 -0
- package/out-tsc/test/temba-flow-self-routing.test.js.map +1 -0
- package/out-tsc/test/temba-formfield.test.js.map +1 -1
- package/out-tsc/test/temba-icon.test.js +1 -1
- package/out-tsc/test/temba-icon.test.js.map +1 -1
- package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-label.test.js +1 -1
- package/out-tsc/test/temba-label.test.js.map +1 -1
- package/out-tsc/test/temba-lightbox.test.js +1 -1
- package/out-tsc/test/temba-lightbox.test.js.map +1 -1
- package/out-tsc/test/temba-markdown.test.js +127 -0
- package/out-tsc/test/temba-markdown.test.js.map +1 -0
- package/out-tsc/test/temba-menu.test.js +1 -1
- package/out-tsc/test/temba-menu.test.js.map +1 -1
- package/out-tsc/test/temba-modax.test.js +1 -1
- package/out-tsc/test/temba-modax.test.js.map +1 -1
- package/out-tsc/test/temba-modules.test.js +47 -0
- package/out-tsc/test/temba-modules.test.js.map +1 -0
- 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-omnibox.test.js +1 -1
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-options.test.js.map +1 -1
- package/out-tsc/test/temba-range-picker.test.js +9 -2
- package/out-tsc/test/temba-range-picker.test.js.map +1 -1
- package/out-tsc/test/temba-rapid-element.test.js +273 -0
- package/out-tsc/test/temba-rapid-element.test.js.map +1 -0
- package/out-tsc/test/temba-resize-element.test.js +85 -0
- package/out-tsc/test/temba-resize-element.test.js.map +1 -0
- package/out-tsc/test/temba-select.test.js +87 -2
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/temba-slider.test.js.map +1 -1
- package/out-tsc/test/temba-sticky-note.test.js +194 -0
- package/out-tsc/test/temba-sticky-note.test.js.map +1 -0
- package/out-tsc/test/temba-template-editor.test.js.map +1 -1
- package/out-tsc/test/temba-textinput.test.js +1 -1
- package/out-tsc/test/temba-textinput.test.js.map +1 -1
- package/out-tsc/test/temba-tip.test.js +1 -1
- package/out-tsc/test/temba-tip.test.js.map +1 -1
- package/out-tsc/test/temba-toast.test.js +1 -1
- package/out-tsc/test/temba-toast.test.js.map +1 -1
- package/out-tsc/test/temba-utils-index.test.js +1 -1
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/out-tsc/test/temba-utils-uuid.test.js +38 -0
- package/out-tsc/test/temba-utils-uuid.test.js.map +1 -0
- package/out-tsc/test/temba-webchat.test.js +28 -12
- package/out-tsc/test/temba-webchat.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -6
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +18 -9
- package/rollup.components.mjs +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/datepicker/range-picker-all.png +0 -0
- package/screenshots/truth/datepicker/range-picker-button-states.png +0 -0
- package/screenshots/truth/datepicker/range-picker-default.png +0 -0
- package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
- package/screenshots/truth/datepicker/range-picker-initial-values.png +0 -0
- package/screenshots/truth/datepicker/range-picker-week.png +0 -0
- package/screenshots/truth/datepicker/range-picker-year.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/screenshots/truth/sticky-note/blue-color.png +0 -0
- package/screenshots/truth/sticky-note/blue.png +0 -0
- package/screenshots/truth/sticky-note/color-picker-expanded.png +0 -0
- package/screenshots/truth/sticky-note/default.png +0 -0
- package/screenshots/truth/sticky-note/gray-color.png +0 -0
- package/screenshots/truth/sticky-note/gray.png +0 -0
- package/screenshots/truth/sticky-note/green-color.png +0 -0
- package/screenshots/truth/sticky-note/green.png +0 -0
- package/screenshots/truth/sticky-note/pink-color.png +0 -0
- package/screenshots/truth/sticky-note/pink.png +0 -0
- package/screenshots/truth/sticky-note/yellow-color.png +0 -0
- package/screenshots/truth/sticky-note/yellow.png +0 -0
- package/src/{charcount → display}/CharCount.ts +164 -2
- package/src/{vectoricon/VectorIcon.ts → display/Icon.ts} +1 -1
- package/src/{leafletmap → display}/LeafletMap.ts +19 -1
- package/src/{thumbnail → display}/Thumbnail.ts +1 -1
- package/src/{tip → display}/Tip.ts +1 -2
- package/src/events.ts +108 -0
- package/src/flow/CanvasNode.ts +1009 -0
- package/src/flow/Editor.ts +795 -169
- package/src/flow/NodeEditor.ts +1443 -0
- package/src/flow/Plumber.ts +177 -79
- package/src/flow/StickyNote.ts +165 -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 -136
- 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/{checkbox → form}/Checkbox.ts +24 -5
- package/src/{colorpicker → form}/ColorPicker.ts +2 -2
- package/src/{completion → form}/Completion.ts +9 -3
- package/src/{compose → form}/Compose.ts +7 -7
- package/src/{contactsearch → form}/ContactSearch.ts +6 -6
- package/src/{datepicker → form}/DatePicker.ts +1 -1
- package/src/{FormElement.ts → form/FormElement.ts} +1 -1
- package/src/form/FormField.ts +238 -0
- package/src/{imagepicker → form}/ImagePicker.ts +2 -2
- package/src/form/KeyValueEditor.ts +251 -0
- package/src/{mediapicker → form}/MediaPicker.ts +1 -1
- package/src/{slider → form}/TembaSlider.ts +1 -1
- package/src/{templates → form}/TemplateEditor.ts +2 -2
- package/src/{textinput → form}/TextInput.ts +5 -5
- package/src/{omnibox → form/select}/Omnibox.ts +2 -2
- package/src/{select → form/select}/PopupSelect.ts +1 -1
- package/src/{select → form/select}/Select.ts +207 -152
- package/src/{select → form/select}/UserSelect.ts +1 -1
- package/src/{select → form/select}/WorkspaceSelect.ts +1 -1
- package/src/interfaces.ts +8 -2
- package/src/{dialog → layout}/Dialog.ts +1 -1
- package/src/list/NotificationList.ts +2 -2
- package/src/list/RunList.ts +3 -3
- package/src/list/ShortcutList.ts +1 -1
- package/src/list/TembaMenu.ts +2 -2
- package/src/list/TicketList.ts +1 -1
- package/src/{aliaseditor → live}/AliasEditor.ts +3 -3
- package/src/{contacts → live}/ContactBadges.ts +1 -1
- package/src/{contacts → live}/ContactChat.ts +120 -104
- package/src/{contacts → live}/ContactDetails.ts +1 -1
- package/src/{contacts → live}/ContactFieldEditor.ts +4 -4
- package/src/{contacts → live}/ContactFields.ts +1 -1
- package/src/{contacts → live}/ContactNotepad.ts +1 -1
- package/src/{contacts → live}/ContactPending.ts +1 -1
- package/src/{chart → live}/TembaChart.ts +1 -1
- package/src/store/AppState.ts +75 -29
- package/src/store/Store.ts +1 -1
- package/src/store/flow-definition.d.ts +131 -1
- package/src/{utils/index.ts → utils.ts} +26 -10
- package/src/webchat/WebChat.ts +1 -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 +4 -6
- package/svg.js +1 -4
- package/temba-components.ts +2 -2
- package/temba-modules.ts +63 -56
- package/temba-webchat.ts +2 -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-alert.test.ts +1 -1
- package/test/temba-appstate-language.test.ts +108 -0
- package/test/temba-charcount.test.ts +1 -1
- package/test/temba-chart.test.ts +1 -1
- package/test/temba-checkbox.test.ts +2 -2
- package/test/temba-color-picker.test.ts +1 -1
- package/test/temba-completion.test.ts +1 -1
- package/test/temba-compose.test.ts +1 -1
- package/test/temba-contact-badges.test.ts +1 -1
- package/test/temba-contact-chat.test.ts +6 -4
- package/test/temba-contact-details.test.ts +1 -1
- package/test/temba-contact-fields.test.ts +1 -1
- package/test/temba-contact-search.test.ts +2 -2
- package/test/temba-date.test.ts +8 -3
- package/test/temba-datepicker.test.ts +1 -1
- package/test/temba-dialog.test.ts +1 -1
- package/test/temba-dropdown.test.ts +1 -1
- package/test/temba-excellent-helpers.test.ts +417 -0
- package/test/temba-field-config.test.ts +152 -0
- package/test/temba-field-manager.test.ts +2 -2
- package/test/temba-flow-editor-node.test.ts +551 -16
- package/test/temba-flow-editor.test.ts +224 -0
- package/test/temba-flow-editor.test.ts.backup +563 -0
- package/test/temba-flow-plumber-connections.test.ts +142 -0
- package/test/temba-flow-plumber.test.ts +83 -120
- package/test/temba-flow-self-routing.test.ts +215 -0
- package/test/temba-formfield.test.ts +1 -1
- package/test/temba-icon.test.ts +1 -1
- package/test/temba-integration-markdown.test.ts +1 -1
- package/test/temba-label.test.ts +1 -1
- package/test/temba-lightbox.test.ts +1 -1
- package/test/temba-markdown.test.ts +162 -0
- package/test/temba-menu.test.ts +1 -1
- package/test/temba-modax.test.ts +2 -2
- package/test/temba-modules.test.ts +56 -0
- package/test/temba-node-editor.test.ts +353 -0
- package/test/temba-omnibox.test.ts +1 -1
- package/test/temba-options.test.ts +1 -1
- package/test/temba-range-picker.test.ts +17 -2
- package/test/temba-rapid-element.test.ts +341 -0
- package/test/temba-resize-element.test.ts +104 -0
- package/test/temba-select.test.ts +129 -2
- package/test/temba-slider.test.ts +1 -1
- package/test/temba-sticky-note.test.ts +281 -0
- package/test/temba-template-editor.test.ts +1 -1
- package/test/temba-textinput.test.ts +1 -1
- package/test/temba-tip.test.ts +1 -1
- package/test/temba-toast.test.ts +1 -1
- package/test/temba-utils-index.test.ts +1 -1
- package/test/temba-utils-index.test.ts.backup +1737 -0
- package/test/temba-utils-uuid.test.ts +48 -0
- package/test/temba-webchat.test.ts +30 -12
- package/test/utils.test.ts +5 -9
- package/test-assets/contacts/history.json +11 -33
- package/web-dev-server.config.mjs +35 -1
- package/demo/sticky-note-demo.html +0 -155
- package/out-tsc/src/FormElement.js.map +0 -1
- package/out-tsc/src/alert/Alert.js.map +0 -1
- package/out-tsc/src/aliaseditor/AliasEditor.js.map +0 -1
- package/out-tsc/src/anchor/Anchor.js.map +0 -1
- package/out-tsc/src/button/Button.js.map +0 -1
- package/out-tsc/src/charcount/CharCount.js.map +0 -1
- package/out-tsc/src/charcount/helpers.js +0 -159
- package/out-tsc/src/charcount/helpers.js.map +0 -1
- package/out-tsc/src/chart/TembaChart.js.map +0 -1
- package/out-tsc/src/chat/Chat.js.map +0 -1
- package/out-tsc/src/checkbox/Checkbox.js.map +0 -1
- package/out-tsc/src/colorpicker/ColorPicker.js.map +0 -1
- package/out-tsc/src/completion/Completion.js.map +0 -1
- package/out-tsc/src/completion/ExcellentParser.js.map +0 -1
- package/out-tsc/src/completion/helpers.js.map +0 -1
- package/out-tsc/src/compose/Compose.js.map +0 -1
- package/out-tsc/src/contacts/ContactBadges.js.map +0 -1
- package/out-tsc/src/contacts/ContactChat.js.map +0 -1
- package/out-tsc/src/contacts/ContactDetails.js.map +0 -1
- package/out-tsc/src/contacts/ContactFieldEditor.js.map +0 -1
- package/out-tsc/src/contacts/ContactFields.js.map +0 -1
- package/out-tsc/src/contacts/ContactName.js.map +0 -1
- package/out-tsc/src/contacts/ContactNameFetch.js.map +0 -1
- package/out-tsc/src/contacts/ContactPending.js.map +0 -1
- package/out-tsc/src/contacts/ContactStoreElement.js.map +0 -1
- package/out-tsc/src/contacts/ContactUrn.js.map +0 -1
- package/out-tsc/src/contacts/events.js +0 -65
- package/out-tsc/src/contacts/events.js.map +0 -1
- package/out-tsc/src/contacts/helpers.js +0 -77
- package/out-tsc/src/contacts/helpers.js.map +0 -1
- package/out-tsc/src/contactsearch/ContactSearch.js.map +0 -1
- package/out-tsc/src/date/TembaDate.js.map +0 -1
- package/out-tsc/src/datepicker/DatePicker.js.map +0 -1
- package/out-tsc/src/datepicker/RangePicker.js.map +0 -1
- package/out-tsc/src/dialog/Dialog.js.map +0 -1
- package/out-tsc/src/dropdown/Dropdown.js.map +0 -1
- package/out-tsc/src/fields/FieldManager.js.map +0 -1
- package/out-tsc/src/flow/EditorNode.js +0 -291
- package/out-tsc/src/flow/EditorNode.js.map +0 -1
- package/out-tsc/src/flow/render.js +0 -41
- package/out-tsc/src/flow/render.js.map +0 -1
- package/out-tsc/src/formfield/FormField.js +0 -144
- package/out-tsc/src/formfield/FormField.js.map +0 -1
- package/out-tsc/src/imagepicker/CroppieCSS.js.map +0 -1
- package/out-tsc/src/imagepicker/ImagePicker.js.map +0 -1
- package/out-tsc/src/label/Label.js.map +0 -1
- package/out-tsc/src/leafletmap/LeafletMap.js.map +0 -1
- package/out-tsc/src/leafletmap/helpers.js +0 -17
- package/out-tsc/src/leafletmap/helpers.js.map +0 -1
- package/out-tsc/src/lightbox/Lightbox.js.map +0 -1
- package/out-tsc/src/mask/Mask.js.map +0 -1
- package/out-tsc/src/mediapicker/MediaPicker.js.map +0 -1
- package/out-tsc/src/omnibox/Omnibox.js.map +0 -1
- package/out-tsc/src/options/helpers.js +0 -28
- package/out-tsc/src/options/helpers.js.map +0 -1
- package/out-tsc/src/progress/ProgressBar.js.map +0 -1
- package/out-tsc/src/progress/StartProgress.js.map +0 -1
- package/out-tsc/src/resizer/Resizer.js.map +0 -1
- package/out-tsc/src/select/PopupSelect.js.map +0 -1
- package/out-tsc/src/select/Select.js.map +0 -1
- package/out-tsc/src/select/UserSelect.js.map +0 -1
- package/out-tsc/src/select/WorkspaceSelect.js.map +0 -1
- package/out-tsc/src/select/helpers.js +0 -1
- package/out-tsc/src/select/helpers.js.map +0 -1
- package/out-tsc/src/shadowless/Shadowless.js +0 -33
- package/out-tsc/src/shadowless/Shadowless.js.map +0 -1
- package/out-tsc/src/slider/TembaSlider.js.map +0 -1
- package/out-tsc/src/sms/gsmsplitter.js.map +0 -1
- package/out-tsc/src/sms/gsmvalidator.js.map +0 -1
- package/out-tsc/src/sms/index.js.map +0 -1
- package/out-tsc/src/sms/unicodesplitter.js.map +0 -1
- package/out-tsc/src/tabpane/Tab.js.map +0 -1
- package/out-tsc/src/tabpane/TabPane.js.map +0 -1
- package/out-tsc/src/templates/TemplateEditor.js.map +0 -1
- package/out-tsc/src/textinput/TextInput.js.map +0 -1
- package/out-tsc/src/textinput/helpers.js +0 -12
- package/out-tsc/src/textinput/helpers.js.map +0 -1
- package/out-tsc/src/thumbnail/Thumbnail.js.map +0 -1
- package/out-tsc/src/tip/Tip.js.map +0 -1
- package/out-tsc/src/tip/helpers.js +0 -7
- package/out-tsc/src/tip/helpers.js.map +0 -1
- package/out-tsc/src/toast/Toast.js.map +0 -1
- package/out-tsc/src/user/TembaUser.js.map +0 -1
- package/out-tsc/src/utils/index.js.map +0 -1
- package/out-tsc/src/vectoricon/VectorIcon.js.map +0 -1
- package/out-tsc/src/vectoricon/index.js.map +0 -1
- package/out-tsc/test/temba-flow-render.test.js +0 -171
- package/out-tsc/test/temba-flow-render.test.js.map +0 -1
- package/src/charcount/helpers.ts +0 -162
- package/src/contacts/events.ts +0 -210
- package/src/contacts/helpers.ts +0 -103
- package/src/flow/EditorNode.ts +0 -318
- package/src/flow/render.ts +0 -56
- package/src/formfield/FormField.ts +0 -134
- package/src/leafletmap/helpers.ts +0 -18
- package/src/options/helpers.ts +0 -37
- package/src/select/helpers.ts +0 -0
- package/src/shadowless/Shadowless.ts +0 -32
- package/src/textinput/helpers.ts +0 -11
- package/src/tip/helpers.ts +0 -7
- package/test/temba-flow-render.test.ts +0 -220
- /package/out-tsc/src/{alert → display}/Alert.js +0 -0
- /package/out-tsc/src/{anchor → display}/Anchor.js +0 -0
- /package/out-tsc/src/{button → display}/Button.js +0 -0
- /package/out-tsc/src/{chat → display}/Chat.js +0 -0
- /package/out-tsc/src/{contacts → display}/ContactName.js +0 -0
- /package/out-tsc/src/{contacts → display}/ContactUrn.js +0 -0
- /package/out-tsc/src/{dropdown → display}/Dropdown.js +0 -0
- /package/out-tsc/src/{label → display}/Label.js +0 -0
- /package/out-tsc/src/{lightbox → display}/Lightbox.js +0 -0
- /package/out-tsc/src/{loading → display}/Loading.js +0 -0
- /package/out-tsc/src/{options → display}/Options.js +0 -0
- /package/out-tsc/src/{progress → display}/ProgressBar.js +0 -0
- /package/out-tsc/src/{date → display}/TembaDate.js +0 -0
- /package/out-tsc/src/{user → display}/TembaUser.js +0 -0
- /package/out-tsc/src/{thumbnail → display}/Thumbnail.js +0 -0
- /package/out-tsc/src/{toast → display}/Toast.js +0 -0
- /package/out-tsc/src/{sms → display/sms}/gsmsplitter.js +0 -0
- /package/out-tsc/src/{sms → display/sms}/gsmvalidator.js +0 -0
- /package/out-tsc/src/{sms → display/sms}/index.js +0 -0
- /package/out-tsc/src/{sms → display/sms}/unicodesplitter.js +0 -0
- /package/out-tsc/src/{completion → excellent}/ExcellentParser.js +0 -0
- /package/out-tsc/src/{completion → excellent}/helpers.js +0 -0
- /package/out-tsc/src/{imagepicker → form}/CroppieCSS.js +0 -0
- /package/out-tsc/src/{datepicker → form}/RangePicker.js +0 -0
- /package/out-tsc/src/{dialog → layout}/Dialog.js +0 -0
- /package/out-tsc/src/{mask → layout}/Mask.js +0 -0
- /package/out-tsc/src/{dialog → layout}/Modax.js +0 -0
- /package/out-tsc/src/{resizer → layout}/Resizer.js +0 -0
- /package/out-tsc/src/{tabpane → layout}/Tab.js +0 -0
- /package/out-tsc/src/{tabpane → layout}/TabPane.js +0 -0
- /package/out-tsc/src/{contacts → live}/ContactFields.js +0 -0
- /package/out-tsc/src/{contacts → live}/ContactNameFetch.js +0 -0
- /package/out-tsc/src/{contacts → live}/ContactStoreElement.js +0 -0
- /package/out-tsc/src/{fields → live}/FieldManager.js +0 -0
- /package/out-tsc/src/{progress → live}/StartProgress.js +0 -0
- /package/out-tsc/src/{chart → live}/TembaChart.js +0 -0
- /package/src/{vectoricon/index.ts → Icons.ts} +0 -0
- /package/src/{alert → display}/Alert.ts +0 -0
- /package/src/{anchor → display}/Anchor.ts +0 -0
- /package/src/{button → display}/Button.ts +0 -0
- /package/src/{chat → display}/Chat.ts +0 -0
- /package/src/{contacts → display}/ContactName.ts +0 -0
- /package/src/{contacts → display}/ContactUrn.ts +0 -0
- /package/src/{dropdown → display}/Dropdown.ts +0 -0
- /package/src/{label → display}/Label.ts +0 -0
- /package/src/{lightbox → display}/Lightbox.ts +0 -0
- /package/src/{loading → display}/Loading.ts +0 -0
- /package/src/{options → display}/Options.ts +0 -0
- /package/src/{progress → display}/ProgressBar.ts +0 -0
- /package/src/{date → display}/TembaDate.ts +0 -0
- /package/src/{user → display}/TembaUser.ts +0 -0
- /package/src/{toast → display}/Toast.ts +0 -0
- /package/src/{sms → display/sms}/gsmsplitter.ts +0 -0
- /package/src/{sms → display/sms}/gsmvalidator.ts +0 -0
- /package/src/{sms → display/sms}/index.ts +0 -0
- /package/src/{sms → display/sms}/unicodesplitter.ts +0 -0
- /package/src/{completion → excellent}/ExcellentParser.ts +0 -0
- /package/src/{completion → excellent}/helpers.ts +0 -0
- /package/src/{imagepicker → form}/CroppieCSS.ts +0 -0
- /package/src/{datepicker → form}/RangePicker.ts +0 -0
- /package/src/{mask → layout}/Mask.ts +0 -0
- /package/src/{dialog → layout}/Modax.ts +0 -0
- /package/src/{resizer → layout}/Resizer.ts +0 -0
- /package/src/{tabpane → layout}/Tab.ts +0 -0
- /package/src/{tabpane → layout}/TabPane.ts +0 -0
- /package/src/{contacts → live}/ContactNameFetch.ts +0 -0
- /package/src/{contacts → live}/ContactStoreElement.ts +0 -0
- /package/src/{fields → live}/FieldManager.ts +0 -0
- /package/src/{progress → live}/StartProgress.ts +0 -0
|
@@ -3,7 +3,6 @@ import { WebChat } from '../src/webchat/WebChat';
|
|
|
3
3
|
import { assertScreenshot, getClip, getComponent, mockNow, mouseClickElement } from '../test/utils.test';
|
|
4
4
|
import { expect, assert } from '@open-wc/testing';
|
|
5
5
|
let clock;
|
|
6
|
-
mockNow('2021-03-31T00:31:00.000-00:00');
|
|
7
6
|
const TAG = 'temba-webchat';
|
|
8
7
|
const getWebChat = async (attrs = {}) => {
|
|
9
8
|
const webChat = (await getComponent(TAG, attrs, '', 400, 600));
|
|
@@ -22,12 +21,11 @@ class MockWebSocket {
|
|
|
22
21
|
this.url = url;
|
|
23
22
|
// Only auto-open if enabled
|
|
24
23
|
if (this.autoOpen) {
|
|
25
|
-
setTimeout
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}, 0);
|
|
24
|
+
// Use synchronous execution instead of setTimeout to avoid clock advancing issues
|
|
25
|
+
this.readyState = 1; // OPEN
|
|
26
|
+
if (this.onopen) {
|
|
27
|
+
this.onopen(new Event('open'));
|
|
28
|
+
}
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
send(data) {
|
|
@@ -64,7 +62,9 @@ describe('temba-webchat', () => {
|
|
|
64
62
|
let mockWebSocket;
|
|
65
63
|
let webSocketStub;
|
|
66
64
|
let cookieStub;
|
|
65
|
+
let mockedNow;
|
|
67
66
|
beforeEach(() => {
|
|
67
|
+
mockedNow = mockNow('2021-03-31T00:31:00.000-00:00');
|
|
68
68
|
// Mock WebSocket
|
|
69
69
|
originalWebSocket = window.WebSocket;
|
|
70
70
|
webSocketStub = stub(window, 'WebSocket').callsFake((url) => {
|
|
@@ -74,12 +74,17 @@ describe('temba-webchat', () => {
|
|
|
74
74
|
});
|
|
75
75
|
// Mock document.cookie
|
|
76
76
|
cookieStub = stub(document, 'cookie').value('');
|
|
77
|
-
|
|
77
|
+
// Use fake timers but with a shorter timeout to avoid test hanging
|
|
78
|
+
clock = useFakeTimers({
|
|
79
|
+
shouldAdvanceTime: true,
|
|
80
|
+
advanceTimeDelta: 10
|
|
81
|
+
});
|
|
78
82
|
});
|
|
79
83
|
afterEach(() => {
|
|
80
84
|
clock.restore();
|
|
81
85
|
webSocketStub.restore();
|
|
82
86
|
cookieStub.restore();
|
|
87
|
+
mockedNow.restore();
|
|
83
88
|
window.WebSocket = originalWebSocket;
|
|
84
89
|
});
|
|
85
90
|
describe('Component Initialization', () => {
|
|
@@ -142,6 +147,7 @@ describe('temba-webchat', () => {
|
|
|
142
147
|
expect(toggleElement).to.exist;
|
|
143
148
|
await mouseClickElement(toggleElement);
|
|
144
149
|
await webChat.updateComplete;
|
|
150
|
+
clock.tick(50);
|
|
145
151
|
// Now it should be open and connecting
|
|
146
152
|
expect(webChat.open).to.equal(true);
|
|
147
153
|
expect(webChat.status).to.equal('connecting');
|
|
@@ -179,10 +185,12 @@ describe('temba-webchat', () => {
|
|
|
179
185
|
expect(toggleElement).to.exist;
|
|
180
186
|
await mouseClickElement(toggleElement);
|
|
181
187
|
await webChat.updateComplete;
|
|
188
|
+
clock.tick(50);
|
|
182
189
|
expect(webChat.open).to.equal(true);
|
|
183
190
|
// Click toggle again
|
|
184
191
|
await mouseClickElement(toggleElement);
|
|
185
192
|
await webChat.updateComplete;
|
|
193
|
+
clock.tick(50);
|
|
186
194
|
expect(webChat.open).to.equal(false);
|
|
187
195
|
});
|
|
188
196
|
it('toggles chat via close button', async () => {
|
|
@@ -217,12 +225,14 @@ describe('temba-webchat', () => {
|
|
|
217
225
|
// Open chat - this should trigger socket connection
|
|
218
226
|
webChat.open = true;
|
|
219
227
|
await webChat.updateComplete;
|
|
228
|
+
clock.tick(50);
|
|
220
229
|
expect(webChat.status).to.equal('connecting');
|
|
221
230
|
expect(webSocketStub.called).to.be.true;
|
|
222
231
|
expect(mockWebSocket.url).to.include('test-channel');
|
|
223
232
|
// Now simulate the socket opening
|
|
224
233
|
mockWebSocket.manualOpen();
|
|
225
234
|
await webChat.updateComplete;
|
|
235
|
+
clock.tick(50);
|
|
226
236
|
expect(webChat.status).to.equal('connected');
|
|
227
237
|
});
|
|
228
238
|
it('does not open socket if already connecting or connected', async () => {
|
|
@@ -248,7 +258,7 @@ describe('temba-webchat', () => {
|
|
|
248
258
|
});
|
|
249
259
|
webChat.open = true;
|
|
250
260
|
await webChat.updateComplete;
|
|
251
|
-
|
|
261
|
+
clock.tick(50);
|
|
252
262
|
expect(mockWebSocket.url).to.equal('wss://localhost.textit.com/wc/connect/my-channel/');
|
|
253
263
|
});
|
|
254
264
|
it('includes urn in WebSocket URL when present', async () => {
|
|
@@ -258,7 +268,7 @@ describe('temba-webchat', () => {
|
|
|
258
268
|
});
|
|
259
269
|
webChat.open = true;
|
|
260
270
|
await webChat.updateComplete;
|
|
261
|
-
|
|
271
|
+
clock.tick(50);
|
|
262
272
|
expect(mockWebSocket.url).to.equal('wss://localhost.textit.com/wc/connect/my-channel/?chat_id=chat-123');
|
|
263
273
|
});
|
|
264
274
|
it('sends start_chat command on socket open', async () => {
|
|
@@ -267,8 +277,11 @@ describe('temba-webchat', () => {
|
|
|
267
277
|
});
|
|
268
278
|
webChat.open = true;
|
|
269
279
|
await webChat.updateComplete;
|
|
270
|
-
|
|
271
|
-
|
|
280
|
+
// Manually open the socket to trigger the start_chat command
|
|
281
|
+
mockWebSocket.manualOpen();
|
|
282
|
+
await webChat.updateComplete;
|
|
283
|
+
clock.tick(100);
|
|
284
|
+
expect(mockWebSocket.sentMessages.length).to.be.at.least(1);
|
|
272
285
|
const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);
|
|
273
286
|
expect(sentMessage.type).to.equal('start_chat');
|
|
274
287
|
});
|
|
@@ -283,6 +296,7 @@ describe('temba-webchat', () => {
|
|
|
283
296
|
await webChat.updateComplete;
|
|
284
297
|
mockWebSocket.manualOpen();
|
|
285
298
|
await webChat.updateComplete;
|
|
299
|
+
clock.tick(50);
|
|
286
300
|
const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);
|
|
287
301
|
expect(sentMessage.type).to.equal('start_chat');
|
|
288
302
|
// The chat_id should be 'existing-chat-123' either from the urn property or cookie
|
|
@@ -294,9 +308,11 @@ describe('temba-webchat', () => {
|
|
|
294
308
|
});
|
|
295
309
|
webChat.open = true;
|
|
296
310
|
await webChat.updateComplete;
|
|
311
|
+
clock.tick(50);
|
|
297
312
|
expect(webChat.status).to.equal('connecting');
|
|
298
313
|
mockWebSocket.close();
|
|
299
314
|
await webChat.updateComplete;
|
|
315
|
+
clock.tick(50);
|
|
300
316
|
expect(webChat.status).to.equal('disconnected');
|
|
301
317
|
});
|
|
302
318
|
it('handles socket error event', async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temba-webchat.test.js","sourceRoot":"","sources":["../../test/temba-webchat.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,IAAI,EAAa,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,OAAO,EACP,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAElD,IAAI,KAAU,CAAC;AACf,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAEzC,MAAM,GAAG,GAAG,eAAe,CAAC;AAE5B,MAAM,UAAU,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE,EAAE;IAC3C,MAAM,OAAO,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAY,CAAC;IAE1E,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,iBAAiB;AACjB,MAAM,aAAa;IAUjB,YAAY,GAAW;QAThB,WAAM,GAAoC,IAAI,CAAC;QAC/C,YAAO,GAAyC,IAAI,CAAC;QACrD,cAAS,GAA2C,IAAI,CAAC;QACzD,YAAO,GAAoC,IAAI,CAAC;QAChD,eAAU,GAAW,CAAC,CAAC;QAEvB,iBAAY,GAAa,EAAE,CAAC;QAC5B,aAAQ,GAAY,IAAI,CAAC;QAG9B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,4BAA4B;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,OAAO;gBAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,SAAS;QAC9B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,UAAU;QACR,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,OAAO;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,eAAe,CAAC,IAAS;QACvB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,CACZ,IAAI,YAAY,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAC5D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,aAAa;QACX,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF;AAED,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,iBAAsB,CAAC;IAC3B,IAAI,aAA4B,CAAC;IACjC,IAAI,aAAwB,CAAC;IAC7B,IAAI,UAAqB,CAAC;IAE1B,UAAU,CAAC,GAAG,EAAE;QACd,iBAAiB;QACjB,iBAAiB,GAAG,MAAM,CAAC,SAAS,CAAC;QACrC,aAAa,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,GAAW,EAAE,EAAE;YAClE,aAAa,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;YACvC,aAAa,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,+BAA+B;YAC/D,OAAO,aAAoB,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,uBAAuB;QACvB,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhD,KAAK,GAAG,aAAa,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,aAAa,CAAC,OAAO,EAAE,CAAC;QACxB,UAAU,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,CAAC,SAAS,GAAG,iBAAiB,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;YAEnC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACpC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAChD,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChD,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,GAAG,EAAE,cAAc;aACpB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACjD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,IAAI,EAAE,aAAa;gBACnB,gBAAgB,EAAE,gCAAgC;aACnD,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,KAAK,CACvC,gCAAgC,CACjC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,gDAAgD;YAChD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,gBAAgB,CAAC,uBAAuB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,MAAM,gBAAgB,CAAC,uBAAuB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAEhD,kEAAkE;YAClE,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAClE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE/B,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;YACvC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,uCAAuC;YACvC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE9C,MAAM,gBAAgB,CAAC,0BAA0B,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YAEH,MAAM,gBAAgB,CAAC,4BAA4B,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YAEH,+FAA+F;YAC/F,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAC5B,UAAU,CAAC,KAAK,CAAC,UAAU,GAAG,aAAa,CAAC;YAE5C,MAAM,gBAAgB,CAAC,yBAAyB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAErC,2BAA2B;YAC3B,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAClE,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE/B,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;YACvC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEpC,qBAAqB;YACrB,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;YACvC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEpC,+BAA+B;YAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;YACtE,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE7B,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACrC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;YAC3C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAErC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAEhD,oDAAoD;YACpD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC9C,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YACxC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAErD,kCAAkC;YAClC,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,mBAAmB;YACnB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEpB,MAAM,cAAc,GAAG,aAAa,CAAC,SAAS,CAAC;YAE/C,wCAAwC;YACxC,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;YACrB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEpB,mCAAmC;YACnC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,YAAY;aACtB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEpB,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAChC,mDAAmD,CACpD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,UAAU;aAChB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEpB,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAChC,oEAAoE,CACrE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEpB,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,6CAA6C;YAC7C,UAAU,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAErD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,GAAG,EAAE,mBAAmB;aACzB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAChD,mFAAmF;YACnF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE9C,aAAa,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE9C,aAAa,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YAEH,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YACvE,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAEjC,MAAM,iBAAiB,CAAC,eAAe,CAAC,CAAC;YACzC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YACxC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAE7C,gCAAgC;YAChC,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAC7C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,gCAAgC;YAChC,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,kBAAkB;aAC5B,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAEjD,uCAAuC;YACvC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,4BAA4B;YAC5B,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE;oBACP,EAAE,EAAE,SAAS;oBACb,IAAI,EAAE,mBAAmB;oBACzB,IAAI,EAAE,0BAA0B;oBAChC,IAAI,EAAE;wBACJ,EAAE,EAAE,QAAQ;wBACZ,IAAI,EAAE,WAAW;wBACjB,KAAK,EAAE,kBAAkB;qBAC1B;iBACF;aACF,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,uBAAuB;YACvB,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAChD,mBAAmB,GAAG,CAAC,CACxB,CAAC;YACF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAC3B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7C,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,4BAA4B;YAC5B,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE;oBACP;wBACE,OAAO,EAAE;4BACP,EAAE,EAAE,OAAO;4BACX,IAAI,EAAE,eAAe;4BACrB,IAAI,EAAE,0BAA0B;4BAChC,IAAI,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE;yBAChE;qBACF;oBACD;wBACE,MAAM,EAAE;4BACN,EAAE,EAAE,OAAO;4BACX,IAAI,EAAE,gBAAgB;4BACtB,IAAI,EAAE,0BAA0B;yBACjC;qBACF;iBACF;aACF,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,gEAAgE;YAChE,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,GAAG,EAAE,cAAc;aACpB,CAAC,CAAC;YAEH,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;YAEnD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,+CAA+C;YAC/C,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAC7C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,gDAAgD;YAChD,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,eAAe;aACzB,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,wBAAwB;YACxB,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;YACnD,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,sDAAsD;YACtD,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,eAAe;aACzB,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC9C,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE5B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAE/C,kBAAkB;YAClB,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC;YAC3B,UAAU,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;YACrE,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAE9C,cAAc;YACd,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;YACtB,UAAU,CAAC,aAAa,CACtB,IAAI,aAAa,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CACnD,CAAC;YACF,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,oCAAoC;YACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAE7C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,UAAU,CAAC,KAAK,GAAG,cAAc,CAAC;YAClC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YAE9B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,iDAAiD;YACjD,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1D,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,2BAA2B;YAC3B,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAChD,mBAAmB,GAAG,CAAC,CACxB,CAAC;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAElD,6DAA6D;YAC7D,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACtC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YAEtB,UAAU,CAAC,KAAK,GAAG,sBAAsB,CAAC;YAC1C,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YAC9B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,uFAAuF;YACtF,OAAe,CAAC,kBAAkB,EAAE,CAAC;YACtC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,2BAA2B;YAC3B,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAChD,mBAAmB,GAAG,CAAC,CACxB,CAAC;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACpE,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE5B,oBAAoB;YACpB,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,UAAU,CAAC,KAAK,GAAG,GAAG,EAAE;gBACtB,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC,CAAC;YAEF,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAEpC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,6DAA6D;YAC7D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAEhD,8DAA8D;YAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,KAAK,GAAG,iBAAiB,CAAC;gBACrC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;gBAE9B,6CAA6C;gBAC7C,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;gBAC1D,MAAM,OAAO,CAAC,cAAc,CAAC;YAC/B,CAAC;YAED,oDAAoD;YACpD,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,sCAAsC;YACtC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YAChC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAChD,mBAAmB,GAAG,CAAC,CACxB,CAAC;YAEF,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAC/B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACpD,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAEpC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,mCAAmC;YACnC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YAChC,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAEpC,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,UAAU,CAAC,KAAK,GAAG,WAAW,CAAC;YAE/B,0BAA0B;YAC1B,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACtD,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAE9C,wBAAwB;YACxB,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;YACtB,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC9D,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CACjD,QAAQ,CACW,CAAC;YACtB,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;YACtB,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC;YAE/B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,6CAA6C;YAC7C,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1D,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,wCAAwC;YACxC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAEhD,mCAAmC;YACnC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC9C,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,kCAAkC;YAClC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE9C,iDAAiD;YACjD,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,MAAM,aAAa,GAAG,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC;YACvD,gBAAgB,CAAC,SAAS,CAAC,KAAK,GAAG;gBACjC,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC,CAAC;YAEF,6DAA6D;YAC7D,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,yBAAyB;YACzB,gBAAgB,CAAC,SAAS,CAAC,KAAK,GAAG,aAAa,CAAC;YAEjD,iEAAiE;YACjE,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACrE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;YAEH,6CAA6C;YAC5C,OAAe,CAAC,UAAU,EAAE,CAAC;YAE9B,4BAA4B;YAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,kCAAkC;YAClC,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,EAAE;aACZ,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,8CAA8C;YAC9C,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE;oBACP;wBACE,MAAM,EAAE;4BACN,EAAE,EAAE,OAAO;4BACX,IAAI,EAAE,kBAAkB;4BACxB,IAAI,EAAE,0BAA0B;yBACjC;qBACF;iBACF;aACF,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACpE,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE5B,IAAI,oBAAoB,GAAG,KAAK,CAAC;YACjC,IAAI,qBAAqB,GAAG,KAAK,CAAC;YAElC,MAAM,SAAS,GAAG;gBAChB,cAAc,EAAE,GAAG,EAAE;oBACnB,oBAAoB,GAAG,IAAI,CAAC;gBAC9B,CAAC;gBACD,eAAe,EAAE,GAAG,EAAE;oBACpB,qBAAqB,GAAG,IAAI,CAAC;gBAC/B,CAAC;aACF,CAAC;YAED,OAAe,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAElD,MAAM,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YACxC,MAAM,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,gCAAgC;YAChC,aAAa,CAAC,eAAe,CAAC;gBAC5B,IAAI,EAAE,sBAAsB;gBAC5B,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,4BAA4B;YAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC/C,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,MAAM,OAAO,CAAC,cAAc,CAAC;YAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE7B,MAAM,mBAAmB,GAAG,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC;YAE9D,kCAAkC;YAClC,WAAW,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,wBAAwB,CAAC,CAAC,CAAC;YACrE,MAAM,OAAO,CAAC,cAAc,CAAC;YAE7B,sCAAsC;YACtC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAChD,mBAAmB,GAAG,CAAC,CACxB,CAAC;YACF,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAC/B,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAClE,CAAC;YACF,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC;gBAC/B,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAEpC,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;YAE7B,gCAAgC;YAChC,WAAW,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAEnE,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { useFakeTimers, stub, SinonStub } from 'sinon';\nimport { WebChat } from '../src/webchat/WebChat';\nimport {\n assertScreenshot,\n getClip,\n getComponent,\n mockNow,\n mouseClickElement\n} from '../test/utils.test';\nimport { expect, assert } from '@open-wc/testing';\n\nlet clock: any;\nmockNow('2021-03-31T00:31:00.000-00:00');\n\nconst TAG = 'temba-webchat';\n\nconst getWebChat = async (attrs: any = {}) => {\n const webChat = (await getComponent(TAG, attrs, '', 400, 600)) as WebChat;\n\n return webChat;\n};\n\n// Mock WebSocket\nclass MockWebSocket {\n public onopen: ((event: Event) => void) | null = null;\n public onclose: ((event: CloseEvent) => void) | null = null;\n public onmessage: ((event: MessageEvent) => void) | null = null;\n public onerror: ((event: Event) => void) | null = null;\n public readyState: number = 0;\n public url: string;\n public sentMessages: string[] = [];\n public autoOpen: boolean = true;\n\n constructor(url: string) {\n this.url = url;\n // Only auto-open if enabled\n if (this.autoOpen) {\n setTimeout(() => {\n this.readyState = 1; // OPEN\n if (this.onopen) {\n this.onopen(new Event('open'));\n }\n }, 0);\n }\n }\n\n send(data: string) {\n this.sentMessages.push(data);\n }\n\n close() {\n this.readyState = 3; // CLOSED\n if (this.onclose) {\n this.onclose(new CloseEvent('close'));\n }\n }\n\n // Test helper to manually open connection\n manualOpen() {\n this.readyState = 1; // OPEN\n if (this.onopen) {\n this.onopen(new Event('open'));\n }\n }\n\n // Test helper to simulate incoming messages\n simulateMessage(data: any) {\n if (this.onmessage) {\n this.onmessage(\n new MessageEvent('message', { data: JSON.stringify(data) })\n );\n }\n }\n\n // Test helper to simulate errors\n simulateError() {\n if (this.onerror) {\n this.onerror(new Event('error'));\n }\n }\n}\n\ndescribe('temba-webchat', () => {\n let originalWebSocket: any;\n let mockWebSocket: MockWebSocket;\n let webSocketStub: SinonStub;\n let cookieStub: SinonStub;\n\n beforeEach(() => {\n // Mock WebSocket\n originalWebSocket = window.WebSocket;\n webSocketStub = stub(window, 'WebSocket').callsFake((url: string) => {\n mockWebSocket = new MockWebSocket(url);\n mockWebSocket.autoOpen = false; // Disable auto-open by default\n return mockWebSocket as any;\n });\n\n // Mock document.cookie\n cookieStub = stub(document, 'cookie').value('');\n\n clock = useFakeTimers();\n });\n\n afterEach(() => {\n clock.restore();\n webSocketStub.restore();\n cookieStub.restore();\n window.WebSocket = originalWebSocket;\n });\n\n describe('Component Initialization', () => {\n it('creates component with default properties', async () => {\n const webChat = await getWebChat();\n\n assert.instanceOf(webChat, WebChat);\n expect(webChat.open).to.equal(false);\n expect(webChat.status).to.equal('disconnected');\n expect(webChat.hasPendingText).to.equal(false);\n expect(webChat.messageGroups).to.deep.equal([]);\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('accepts channel and urn properties', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'test-urn-123'\n });\n\n expect(webChat.channel).to.equal('test-channel');\n expect(webChat.urn).to.equal('test-urn-123');\n });\n\n it('accepts host and activeUserAvatar properties', async () => {\n const webChat = await getWebChat({\n host: 'example.com',\n activeUserAvatar: 'https://example.com/avatar.jpg'\n });\n\n expect(webChat.host).to.equal('example.com');\n expect(webChat.activeUserAvatar).to.equal(\n 'https://example.com/avatar.jpg'\n );\n });\n\n it('initializes chat component on first update', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // Check that the chat component was initialized\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n });\n });\n\n describe('UI Rendering', () => {\n it('renders closed chat widget by default', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n await assertScreenshot('webchat/closed-widget', getClip(webChat));\n });\n\n it('renders opened chat widget', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n await assertScreenshot('webchat/opened-widget', getClip(webChat));\n });\n\n it('renders connecting state', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n expect(webChat.status).to.equal('disconnected');\n\n // Click to open the widget, which should trigger connecting state\n const toggleElement = webChat.shadowRoot.querySelector('.toggle');\n expect(toggleElement).to.exist;\n\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n\n // Now it should be open and connecting\n expect(webChat.open).to.equal(true);\n expect(webChat.status).to.equal('connecting');\n\n await assertScreenshot('webchat/connecting-state', getClip(webChat));\n });\n\n it('renders disconnected state with reconnect option', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n await assertScreenshot('webchat/disconnected-state', getClip(webChat));\n });\n\n it('renders connected state with input field', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n // the cursor is blinking, we need to account for it in our screenshot by making it transparent\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n expect(inputField).to.exist;\n inputField.style.caretColor = 'transparent';\n\n await assertScreenshot('webchat/connected-state', getClip(webChat));\n });\n });\n\n describe('Chat Toggle Functionality', () => {\n it('toggles chat open/closed', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n\n // Click the toggle element\n const toggleElement = webChat.shadowRoot.querySelector('.toggle');\n expect(toggleElement).to.exist;\n\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(true);\n\n // Click toggle again\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(false);\n });\n\n it('toggles chat via close button', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n expect(webChat.open).to.equal(true);\n\n // Click close button in header\n const closeButton = webChat.shadowRoot.querySelector('.close-button');\n expect(closeButton).to.exist;\n\n await mouseClickElement(closeButton);\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(false);\n });\n\n it('opens chat programmatically', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n\n webChat.openChat();\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(true);\n });\n });\n\n describe('Socket Connection Management', () => {\n it('opens socket when chat is opened', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.status).to.equal('disconnected');\n\n // Open chat - this should trigger socket connection\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n expect(webSocketStub.called).to.be.true;\n expect(mockWebSocket.url).to.include('test-channel');\n\n // Now simulate the socket opening\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connected');\n });\n\n it('does not open socket if already connecting or connected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // First connection\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n const firstCallCount = webSocketStub.callCount;\n\n // Try to connect again while connecting\n webChat.open = false;\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n // Should not create another socket\n expect(webSocketStub.callCount).to.equal(firstCallCount);\n });\n\n it('constructs correct WebSocket URL with channel', async () => {\n const webChat = await getWebChat({\n channel: 'my-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n expect(mockWebSocket.url).to.equal(\n 'wss://localhost.textit.com/wc/connect/my-channel/'\n );\n });\n\n it('includes urn in WebSocket URL when present', async () => {\n const webChat = await getWebChat({\n channel: 'my-channel',\n urn: 'chat-123'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n expect(mockWebSocket.url).to.equal(\n 'wss://localhost.textit.com/wc/connect/my-channel/?chat_id=chat-123'\n );\n });\n\n it('sends start_chat command on socket open', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n expect(mockWebSocket.sentMessages).to.have.length(1);\n const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);\n expect(sentMessage.type).to.equal('start_chat');\n });\n\n it('includes chat_id in start_chat command when urn is present', async () => {\n // Set the cookie directly in document.cookie\n cookieStub.value('temba-chat-urn=existing-chat-123');\n\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'existing-chat-123'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);\n expect(sentMessage.type).to.equal('start_chat');\n // The chat_id should be 'existing-chat-123' either from the urn property or cookie\n expect(sentMessage.chat_id).to.equal('existing-chat-123');\n });\n\n it('handles socket close event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n\n mockWebSocket.close();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('disconnected');\n });\n\n it('handles socket error event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n\n mockWebSocket.simulateError();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('disconnected');\n });\n\n it('reconnects when reconnect button is clicked', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n const reconnectButton = webChat.shadowRoot.querySelector('.reconnect');\n expect(reconnectButton).to.exist;\n\n await mouseClickElement(reconnectButton);\n await webChat.updateComplete;\n\n expect(webSocketStub.called).to.be.true;\n expect(webChat.status).to.equal('connecting');\n });\n });\n\n describe('Message Handling', () => {\n it('handles chat_started message', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connected');\n\n // Simulate chat_started message\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'new-chat-456'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('new-chat-456');\n expect(webChat.messageGroups).to.deep.equal([]);\n });\n\n it('handles chat_resumed message and fetches history', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate chat_resumed message\n mockWebSocket.simulateMessage({\n type: 'chat_resumed',\n chat_id: 'resumed-chat-789'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('resumed-chat-789');\n\n // Should have sent get_history command\n expect(mockWebSocket.sentMessages.length).to.be.greaterThan(1);\n const lastMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(lastMessage.type).to.equal('get_history');\n });\n\n it('handles chat_out message and sends ack', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Simulate incoming message\n mockWebSocket.simulateMessage({\n type: 'chat_out',\n msg_out: {\n id: 'msg-123',\n text: 'Hello from server',\n time: '2021-03-31T00:31:00.000Z',\n user: {\n id: 'user-1',\n name: 'Test User',\n email: 'test@example.com'\n }\n }\n });\n await webChat.updateComplete;\n\n // Should have sent ack\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const ackMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(ackMessage.type).to.equal('ack_chat');\n expect(ackMessage.msg_id).to.equal('msg-123');\n });\n\n it('handles history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate history response\n mockWebSocket.simulateMessage({\n type: 'history',\n history: [\n {\n msg_out: {\n id: 'msg-1',\n text: 'First message',\n time: '2021-03-31T00:30:00.000Z',\n user: { id: 'user-1', name: 'User', email: 'user@example.com' }\n }\n },\n {\n msg_in: {\n id: 'msg-2',\n text: 'Second message',\n time: '2021-03-31T00:30:30.000Z'\n }\n }\n ]\n });\n await webChat.updateComplete;\n\n // Should have updated beforeTime and unblocked history fetching\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('clears messages when chat_id changes', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'old-chat-123'\n });\n\n webChat.messageGroups = [['existing', 'messages']];\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate chat_started with different chat_id\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'new-chat-456'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('new-chat-456');\n expect(webChat.messageGroups).to.deep.equal([]);\n });\n\n it('keeps messages when chat_id is the same', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // First, simulate a chat_started to set the URN\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'same-chat-123'\n });\n await webChat.updateComplete;\n\n // Now set some messages\n webChat.messageGroups = [['existing', 'messages']];\n await webChat.updateComplete;\n\n // Simulate another chat_started with the same chat_id\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'same-chat-123'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('same-chat-123');\n expect(webChat.messageGroups).to.deep.equal([['existing', 'messages']]);\n });\n });\n\n describe('User Input and Message Sending', () => {\n it('updates hasPendingText on keyup', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n expect(inputField).to.exist;\n\n expect(webChat.hasPendingText).to.equal(false);\n\n // Simulate typing\n inputField.value = 'Hello';\n inputField.dispatchEvent(new KeyboardEvent('keydown', { key: 'h' }));\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(true);\n\n // Clear input\n inputField.value = '';\n inputField.dispatchEvent(\n new KeyboardEvent('keydown', { key: 'Backspace' })\n );\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('sends message on Enter key', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Ensure the socket is properly set\n expect(webChat.status).to.equal('connected');\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = 'Test message';\n webChat.hasPendingText = true;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Call handleKeyUp directly with Enter key event\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n\n // Should have sent message\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const sentMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(sentMessage.type).to.equal('send_msg');\n expect(sentMessage.text).to.equal('Test message');\n\n // input should be cleared and hasPendingText should be false\n expect(inputField.value).to.equal('');\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('sends message via send button click', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n\n inputField.value = 'Button click message';\n webChat.hasPendingText = true;\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // call sendPendingMessage directly since it's a private method called by click handler\n (webChat as any).sendPendingMessage();\n await webChat.updateComplete;\n\n // should have sent message\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const sentMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(sentMessage.type).to.equal('send_msg');\n expect(sentMessage.text).to.equal('Button click message');\n });\n\n it('focuses input when input panel is clicked', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputPanel = webChat.shadowRoot.querySelector('.input-panel');\n expect(inputPanel).to.exist;\n\n // Mock focus method\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n let focusCalled = false;\n inputField.focus = () => {\n focusCalled = true;\n };\n\n await mouseClickElement(inputPanel);\n\n expect(focusCalled).to.be.true;\n });\n\n it('does not send message when disconnected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n // Keep the status as disconnected - don't connect the socket\n expect(webChat.status).to.equal('disconnected');\n\n // Find input field - it might not exist in disconnected state\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n if (inputField) {\n inputField.value = 'Should not send';\n webChat.hasPendingText = true;\n\n // Try to send message by calling handleKeyUp\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n }\n\n // Should not have created any WebSocket connections\n expect(webSocketStub.called).to.be.false;\n });\n });\n\n describe('History Fetching', () => {\n it('fetches previous messages when requested', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Manually call fetchPreviousMessages\n webChat.fetchPreviousMessages();\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(true);\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n\n const historyRequest = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(historyRequest.type).to.equal('get_history');\n expect(historyRequest.before).to.exist;\n });\n\n it('does not fetch when already fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Try to fetch - should be blocked\n webChat.fetchPreviousMessages();\n await webChat.updateComplete;\n\n expect(mockWebSocket.sentMessages.length).to.equal(initialMessageCount);\n });\n\n it('completes fetch and unblocks history fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n webChat.fetchComplete();\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n });\n\n describe('Edge Cases and Additional Coverage', () => {\n it('handles keyup events that are not Enter', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = 'Some text';\n\n // Test with non-Enter key\n webChat.handleKeyUp({ key: 'a', target: inputField });\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(true);\n\n // Test with empty value\n inputField.value = '';\n webChat.handleKeyUp({ key: 'Backspace', target: inputField });\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('does not send message on Enter if no pending text', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = '';\n webChat.hasPendingText = false;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Try to send with Enter but no pending text\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n\n // Should not have sent any new messages\n expect(mockWebSocket.sentMessages.length).to.equal(initialMessageCount);\n });\n\n it('updates status when open changes from false to true', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.status).to.equal('disconnected');\n\n // Open the chat for the first time\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n expect(webSocketStub.called).to.be.true;\n });\n\n it('focuses input when status changes to connected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // Open chat to trigger connection\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n\n // Mock focus method before the input is rendered\n let focusCalled = false;\n const originalFocus = HTMLInputElement.prototype.focus;\n HTMLInputElement.prototype.focus = function () {\n focusCalled = true;\n };\n\n // Manually open socket to trigger status change to connected\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Restore original focus\n HTMLInputElement.prototype.focus = originalFocus;\n\n // Focus should have been called when status changed to connected\n expect(focusCalled).to.be.true;\n });\n\n it('handles focus input when input element does not exist', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n // Try to focus input when it might not exist\n (webChat as any).focusInput();\n\n // Should not throw an error\n expect(true).to.be.true;\n });\n\n it('handles empty history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate empty history response\n mockWebSocket.simulateMessage({\n type: 'history',\n history: []\n });\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('handles message with msg_in in history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate history response with msg_in first\n mockWebSocket.simulateMessage({\n type: 'history',\n history: [\n {\n msg_in: {\n id: 'msg-1',\n text: 'Incoming message',\n time: '2021-03-31T00:30:00.000Z'\n }\n }\n ]\n });\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('prevents event propagation on input panel click', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputPanel = webChat.shadowRoot.querySelector('.input-panel');\n expect(inputPanel).to.exist;\n\n let preventDefaultCalled = false;\n let stopPropagationCalled = false;\n\n const mockEvent = {\n preventDefault: () => {\n preventDefaultCalled = true;\n },\n stopPropagation: () => {\n stopPropagationCalled = true;\n }\n };\n\n (webChat as any).handleClickInputPanel(mockEvent);\n\n expect(preventDefaultCalled).to.be.true;\n expect(stopPropagationCalled).to.be.true;\n });\n\n it('handles unknown message types gracefully', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate unknown message type\n mockWebSocket.simulateMessage({\n type: 'unknown_message_type',\n data: 'some data'\n });\n await webChat.updateComplete;\n\n // Should not throw an error\n expect(true).to.be.true;\n });\n });\n\n describe('Integration with Chat Component', () => {\n it('listens to scroll threshold event for history fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Simulate scroll threshold event\n chatElement.dispatchEvent(new CustomEvent('temba-scroll-threshold'));\n await webChat.updateComplete;\n\n // Should have triggered history fetch\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const historyRequest = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(historyRequest.type).to.equal('get_history');\n });\n\n it('listens to fetch complete event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n\n // Simulate fetch complete event\n chatElement.dispatchEvent(new CustomEvent('temba-fetch-complete'));\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"temba-webchat.test.js","sourceRoot":"","sources":["../../test/temba-webchat.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { useFakeTimers, stub, SinonStub } from 'sinon';\nimport { WebChat } from '../src/webchat/WebChat';\nimport {\n assertScreenshot,\n getClip,\n getComponent,\n mockNow,\n mouseClickElement\n} from '../test/utils.test';\nimport { expect, assert } from '@open-wc/testing';\n\nlet clock: any;\n\nconst TAG = 'temba-webchat';\n\nconst getWebChat = async (attrs: any = {}) => {\n const webChat = (await getComponent(TAG, attrs, '', 400, 600)) as WebChat;\n\n return webChat;\n};\n\n// Mock WebSocket\nclass MockWebSocket {\n public onopen: ((event: Event) => void) | null = null;\n public onclose: ((event: CloseEvent) => void) | null = null;\n public onmessage: ((event: MessageEvent) => void) | null = null;\n public onerror: ((event: Event) => void) | null = null;\n public readyState: number = 0;\n public url: string;\n public sentMessages: string[] = [];\n public autoOpen: boolean = true;\n\n constructor(url: string) {\n this.url = url;\n // Only auto-open if enabled\n if (this.autoOpen) {\n // Use synchronous execution instead of setTimeout to avoid clock advancing issues\n this.readyState = 1; // OPEN\n if (this.onopen) {\n this.onopen(new Event('open'));\n }\n }\n }\n\n send(data: string) {\n this.sentMessages.push(data);\n }\n\n close() {\n this.readyState = 3; // CLOSED\n if (this.onclose) {\n this.onclose(new CloseEvent('close'));\n }\n }\n\n // Test helper to manually open connection\n manualOpen() {\n this.readyState = 1; // OPEN\n if (this.onopen) {\n this.onopen(new Event('open'));\n }\n }\n\n // Test helper to simulate incoming messages\n simulateMessage(data: any) {\n if (this.onmessage) {\n this.onmessage(\n new MessageEvent('message', { data: JSON.stringify(data) })\n );\n }\n }\n\n // Test helper to simulate errors\n simulateError() {\n if (this.onerror) {\n this.onerror(new Event('error'));\n }\n }\n}\n\ndescribe('temba-webchat', () => {\n let originalWebSocket: any;\n let mockWebSocket: MockWebSocket;\n let webSocketStub: SinonStub;\n let cookieStub: SinonStub;\n let mockedNow: SinonStub;\n\n beforeEach(() => {\n mockedNow = mockNow('2021-03-31T00:31:00.000-00:00');\n\n // Mock WebSocket\n originalWebSocket = window.WebSocket;\n webSocketStub = stub(window, 'WebSocket').callsFake((url: string) => {\n mockWebSocket = new MockWebSocket(url);\n mockWebSocket.autoOpen = false; // Disable auto-open by default\n return mockWebSocket as any;\n });\n\n // Mock document.cookie\n cookieStub = stub(document, 'cookie').value('');\n\n // Use fake timers but with a shorter timeout to avoid test hanging\n clock = useFakeTimers({\n shouldAdvanceTime: true,\n advanceTimeDelta: 10\n });\n });\n\n afterEach(() => {\n clock.restore();\n webSocketStub.restore();\n cookieStub.restore();\n mockedNow.restore();\n window.WebSocket = originalWebSocket;\n });\n\n describe('Component Initialization', () => {\n it('creates component with default properties', async () => {\n const webChat = await getWebChat();\n\n assert.instanceOf(webChat, WebChat);\n expect(webChat.open).to.equal(false);\n expect(webChat.status).to.equal('disconnected');\n expect(webChat.hasPendingText).to.equal(false);\n expect(webChat.messageGroups).to.deep.equal([]);\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('accepts channel and urn properties', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'test-urn-123'\n });\n\n expect(webChat.channel).to.equal('test-channel');\n expect(webChat.urn).to.equal('test-urn-123');\n });\n\n it('accepts host and activeUserAvatar properties', async () => {\n const webChat = await getWebChat({\n host: 'example.com',\n activeUserAvatar: 'https://example.com/avatar.jpg'\n });\n\n expect(webChat.host).to.equal('example.com');\n expect(webChat.activeUserAvatar).to.equal(\n 'https://example.com/avatar.jpg'\n );\n });\n\n it('initializes chat component on first update', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // Check that the chat component was initialized\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n });\n });\n\n describe('UI Rendering', () => {\n it('renders closed chat widget by default', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n await assertScreenshot('webchat/closed-widget', getClip(webChat));\n });\n\n it('renders opened chat widget', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n await assertScreenshot('webchat/opened-widget', getClip(webChat));\n });\n\n it('renders connecting state', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n expect(webChat.status).to.equal('disconnected');\n\n // Click to open the widget, which should trigger connecting state\n const toggleElement = webChat.shadowRoot.querySelector('.toggle');\n expect(toggleElement).to.exist;\n\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n clock.tick(50);\n\n // Now it should be open and connecting\n expect(webChat.open).to.equal(true);\n expect(webChat.status).to.equal('connecting');\n\n await assertScreenshot('webchat/connecting-state', getClip(webChat));\n });\n\n it('renders disconnected state with reconnect option', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n await assertScreenshot('webchat/disconnected-state', getClip(webChat));\n });\n\n it('renders connected state with input field', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n // the cursor is blinking, we need to account for it in our screenshot by making it transparent\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n expect(inputField).to.exist;\n inputField.style.caretColor = 'transparent';\n\n await assertScreenshot('webchat/connected-state', getClip(webChat));\n });\n });\n\n describe('Chat Toggle Functionality', () => {\n it('toggles chat open/closed', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n\n // Click the toggle element\n const toggleElement = webChat.shadowRoot.querySelector('.toggle');\n expect(toggleElement).to.exist;\n\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.open).to.equal(true);\n\n // Click toggle again\n await mouseClickElement(toggleElement);\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.open).to.equal(false);\n });\n\n it('toggles chat via close button', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n expect(webChat.open).to.equal(true);\n\n // Click close button in header\n const closeButton = webChat.shadowRoot.querySelector('.close-button');\n expect(closeButton).to.exist;\n\n await mouseClickElement(closeButton);\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(false);\n });\n\n it('opens chat programmatically', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.open).to.equal(false);\n\n webChat.openChat();\n await webChat.updateComplete;\n\n expect(webChat.open).to.equal(true);\n });\n });\n\n describe('Socket Connection Management', () => {\n it('opens socket when chat is opened', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.status).to.equal('disconnected');\n\n // Open chat - this should trigger socket connection\n webChat.open = true;\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.status).to.equal('connecting');\n expect(webSocketStub.called).to.be.true;\n expect(mockWebSocket.url).to.include('test-channel');\n\n // Now simulate the socket opening\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.status).to.equal('connected');\n });\n\n it('does not open socket if already connecting or connected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // First connection\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n const firstCallCount = webSocketStub.callCount;\n\n // Try to connect again while connecting\n webChat.open = false;\n webChat.open = true;\n await webChat.updateComplete;\n await clock.tick(0);\n\n // Should not create another socket\n expect(webSocketStub.callCount).to.equal(firstCallCount);\n });\n\n it('constructs correct WebSocket URL with channel', async () => {\n const webChat = await getWebChat({\n channel: 'my-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(mockWebSocket.url).to.equal(\n 'wss://localhost.textit.com/wc/connect/my-channel/'\n );\n });\n\n it('includes urn in WebSocket URL when present', async () => {\n const webChat = await getWebChat({\n channel: 'my-channel',\n urn: 'chat-123'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(mockWebSocket.url).to.equal(\n 'wss://localhost.textit.com/wc/connect/my-channel/?chat_id=chat-123'\n );\n });\n\n it('sends start_chat command on socket open', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n // Manually open the socket to trigger the start_chat command\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n clock.tick(100);\n\n expect(mockWebSocket.sentMessages.length).to.be.at.least(1);\n const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);\n expect(sentMessage.type).to.equal('start_chat');\n });\n\n it('includes chat_id in start_chat command when urn is present', async () => {\n // Set the cookie directly in document.cookie\n cookieStub.value('temba-chat-urn=existing-chat-123');\n\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'existing-chat-123'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n clock.tick(50);\n\n const sentMessage = JSON.parse(mockWebSocket.sentMessages[0]);\n expect(sentMessage.type).to.equal('start_chat');\n // The chat_id should be 'existing-chat-123' either from the urn property or cookie\n expect(sentMessage.chat_id).to.equal('existing-chat-123');\n });\n\n it('handles socket close event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.status).to.equal('connecting');\n\n mockWebSocket.close();\n await webChat.updateComplete;\n clock.tick(50);\n\n expect(webChat.status).to.equal('disconnected');\n });\n\n it('handles socket error event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n\n mockWebSocket.simulateError();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('disconnected');\n });\n\n it('reconnects when reconnect button is clicked', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n const reconnectButton = webChat.shadowRoot.querySelector('.reconnect');\n expect(reconnectButton).to.exist;\n\n await mouseClickElement(reconnectButton);\n await webChat.updateComplete;\n\n expect(webSocketStub.called).to.be.true;\n expect(webChat.status).to.equal('connecting');\n });\n });\n\n describe('Message Handling', () => {\n it('handles chat_started message', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connected');\n\n // Simulate chat_started message\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'new-chat-456'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('new-chat-456');\n expect(webChat.messageGroups).to.deep.equal([]);\n });\n\n it('handles chat_resumed message and fetches history', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate chat_resumed message\n mockWebSocket.simulateMessage({\n type: 'chat_resumed',\n chat_id: 'resumed-chat-789'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('resumed-chat-789');\n\n // Should have sent get_history command\n expect(mockWebSocket.sentMessages.length).to.be.greaterThan(1);\n const lastMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(lastMessage.type).to.equal('get_history');\n });\n\n it('handles chat_out message and sends ack', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Simulate incoming message\n mockWebSocket.simulateMessage({\n type: 'chat_out',\n msg_out: {\n id: 'msg-123',\n text: 'Hello from server',\n time: '2021-03-31T00:31:00.000Z',\n user: {\n id: 'user-1',\n name: 'Test User',\n email: 'test@example.com'\n }\n }\n });\n await webChat.updateComplete;\n\n // Should have sent ack\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const ackMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(ackMessage.type).to.equal('ack_chat');\n expect(ackMessage.msg_id).to.equal('msg-123');\n });\n\n it('handles history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate history response\n mockWebSocket.simulateMessage({\n type: 'history',\n history: [\n {\n msg_out: {\n id: 'msg-1',\n text: 'First message',\n time: '2021-03-31T00:30:00.000Z',\n user: { id: 'user-1', name: 'User', email: 'user@example.com' }\n }\n },\n {\n msg_in: {\n id: 'msg-2',\n text: 'Second message',\n time: '2021-03-31T00:30:30.000Z'\n }\n }\n ]\n });\n await webChat.updateComplete;\n\n // Should have updated beforeTime and unblocked history fetching\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('clears messages when chat_id changes', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n urn: 'old-chat-123'\n });\n\n webChat.messageGroups = [['existing', 'messages']];\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate chat_started with different chat_id\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'new-chat-456'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('new-chat-456');\n expect(webChat.messageGroups).to.deep.equal([]);\n });\n\n it('keeps messages when chat_id is the same', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // First, simulate a chat_started to set the URN\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'same-chat-123'\n });\n await webChat.updateComplete;\n\n // Now set some messages\n webChat.messageGroups = [['existing', 'messages']];\n await webChat.updateComplete;\n\n // Simulate another chat_started with the same chat_id\n mockWebSocket.simulateMessage({\n type: 'chat_started',\n chat_id: 'same-chat-123'\n });\n await webChat.updateComplete;\n\n expect(webChat.urn).to.equal('same-chat-123');\n expect(webChat.messageGroups).to.deep.equal([['existing', 'messages']]);\n });\n });\n\n describe('User Input and Message Sending', () => {\n it('updates hasPendingText on keyup', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n expect(inputField).to.exist;\n\n expect(webChat.hasPendingText).to.equal(false);\n\n // Simulate typing\n inputField.value = 'Hello';\n inputField.dispatchEvent(new KeyboardEvent('keydown', { key: 'h' }));\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(true);\n\n // Clear input\n inputField.value = '';\n inputField.dispatchEvent(\n new KeyboardEvent('keydown', { key: 'Backspace' })\n );\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('sends message on Enter key', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Ensure the socket is properly set\n expect(webChat.status).to.equal('connected');\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = 'Test message';\n webChat.hasPendingText = true;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Call handleKeyUp directly with Enter key event\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n\n // Should have sent message\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const sentMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(sentMessage.type).to.equal('send_msg');\n expect(sentMessage.text).to.equal('Test message');\n\n // input should be cleared and hasPendingText should be false\n expect(inputField.value).to.equal('');\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('sends message via send button click', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n\n inputField.value = 'Button click message';\n webChat.hasPendingText = true;\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // call sendPendingMessage directly since it's a private method called by click handler\n (webChat as any).sendPendingMessage();\n await webChat.updateComplete;\n\n // should have sent message\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const sentMessage = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(sentMessage.type).to.equal('send_msg');\n expect(sentMessage.text).to.equal('Button click message');\n });\n\n it('focuses input when input panel is clicked', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputPanel = webChat.shadowRoot.querySelector('.input-panel');\n expect(inputPanel).to.exist;\n\n // Mock focus method\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n let focusCalled = false;\n inputField.focus = () => {\n focusCalled = true;\n };\n\n await mouseClickElement(inputPanel);\n\n expect(focusCalled).to.be.true;\n });\n\n it('does not send message when disconnected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true\n });\n\n // Keep the status as disconnected - don't connect the socket\n expect(webChat.status).to.equal('disconnected');\n\n // Find input field - it might not exist in disconnected state\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n if (inputField) {\n inputField.value = 'Should not send';\n webChat.hasPendingText = true;\n\n // Try to send message by calling handleKeyUp\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n }\n\n // Should not have created any WebSocket connections\n expect(webSocketStub.called).to.be.false;\n });\n });\n\n describe('History Fetching', () => {\n it('fetches previous messages when requested', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Manually call fetchPreviousMessages\n webChat.fetchPreviousMessages();\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(true);\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n\n const historyRequest = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(historyRequest.type).to.equal('get_history');\n expect(historyRequest.before).to.exist;\n });\n\n it('does not fetch when already fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Try to fetch - should be blocked\n webChat.fetchPreviousMessages();\n await webChat.updateComplete;\n\n expect(mockWebSocket.sentMessages.length).to.equal(initialMessageCount);\n });\n\n it('completes fetch and unblocks history fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n webChat.fetchComplete();\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n });\n\n describe('Edge Cases and Additional Coverage', () => {\n it('handles keyup events that are not Enter', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = 'Some text';\n\n // Test with non-Enter key\n webChat.handleKeyUp({ key: 'a', target: inputField });\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(true);\n\n // Test with empty value\n inputField.value = '';\n webChat.handleKeyUp({ key: 'Backspace', target: inputField });\n await webChat.updateComplete;\n\n expect(webChat.hasPendingText).to.equal(false);\n });\n\n it('does not send message on Enter if no pending text', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const inputField = webChat.shadowRoot.querySelector(\n '.input'\n ) as HTMLInputElement;\n inputField.value = '';\n webChat.hasPendingText = false;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Try to send with Enter but no pending text\n webChat.handleKeyUp({ key: 'Enter', target: inputField });\n await webChat.updateComplete;\n\n // Should not have sent any new messages\n expect(mockWebSocket.sentMessages.length).to.equal(initialMessageCount);\n });\n\n it('updates status when open changes from false to true', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n expect(webChat.status).to.equal('disconnected');\n\n // Open the chat for the first time\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n expect(webSocketStub.called).to.be.true;\n });\n\n it('focuses input when status changes to connected', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n // Open chat to trigger connection\n webChat.open = true;\n await webChat.updateComplete;\n\n expect(webChat.status).to.equal('connecting');\n\n // Mock focus method before the input is rendered\n let focusCalled = false;\n const originalFocus = HTMLInputElement.prototype.focus;\n HTMLInputElement.prototype.focus = function () {\n focusCalled = true;\n };\n\n // Manually open socket to trigger status change to connected\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Restore original focus\n HTMLInputElement.prototype.focus = originalFocus;\n\n // Focus should have been called when status changed to connected\n expect(focusCalled).to.be.true;\n });\n\n it('handles focus input when input element does not exist', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'disconnected'\n });\n\n // Try to focus input when it might not exist\n (webChat as any).focusInput();\n\n // Should not throw an error\n expect(true).to.be.true;\n });\n\n it('handles empty history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate empty history response\n mockWebSocket.simulateMessage({\n type: 'history',\n history: []\n });\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('handles message with msg_in in history response', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate history response with msg_in first\n mockWebSocket.simulateMessage({\n type: 'history',\n history: [\n {\n msg_in: {\n id: 'msg-1',\n text: 'Incoming message',\n time: '2021-03-31T00:30:00.000Z'\n }\n }\n ]\n });\n await webChat.updateComplete;\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n\n it('prevents event propagation on input panel click', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel',\n open: true,\n status: 'connected'\n });\n\n const inputPanel = webChat.shadowRoot.querySelector('.input-panel');\n expect(inputPanel).to.exist;\n\n let preventDefaultCalled = false;\n let stopPropagationCalled = false;\n\n const mockEvent = {\n preventDefault: () => {\n preventDefaultCalled = true;\n },\n stopPropagation: () => {\n stopPropagationCalled = true;\n }\n };\n\n (webChat as any).handleClickInputPanel(mockEvent);\n\n expect(preventDefaultCalled).to.be.true;\n expect(stopPropagationCalled).to.be.true;\n });\n\n it('handles unknown message types gracefully', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n // Simulate unknown message type\n mockWebSocket.simulateMessage({\n type: 'unknown_message_type',\n data: 'some data'\n });\n await webChat.updateComplete;\n\n // Should not throw an error\n expect(true).to.be.true;\n });\n });\n\n describe('Integration with Chat Component', () => {\n it('listens to scroll threshold event for history fetching', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.open = true;\n await webChat.updateComplete;\n mockWebSocket.manualOpen();\n await webChat.updateComplete;\n\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n\n const initialMessageCount = mockWebSocket.sentMessages.length;\n\n // Simulate scroll threshold event\n chatElement.dispatchEvent(new CustomEvent('temba-scroll-threshold'));\n await webChat.updateComplete;\n\n // Should have triggered history fetch\n expect(mockWebSocket.sentMessages.length).to.equal(\n initialMessageCount + 1\n );\n const historyRequest = JSON.parse(\n mockWebSocket.sentMessages[mockWebSocket.sentMessages.length - 1]\n );\n expect(historyRequest.type).to.equal('get_history');\n });\n\n it('listens to fetch complete event', async () => {\n const webChat = await getWebChat({\n channel: 'test-channel'\n });\n\n webChat.blockHistoryFetching = true;\n\n const chatElement = webChat.shadowRoot.querySelector('temba-chat');\n expect(chatElement).to.exist;\n\n // Simulate fetch complete event\n chatElement.dispatchEvent(new CustomEvent('temba-fetch-complete'));\n\n expect(webChat.blockHistoryFetching).to.equal(false);\n });\n });\n});\n"]}
|
|
@@ -2,7 +2,7 @@ import '../temba-modules';
|
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
3
|
import { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';
|
|
4
4
|
import MouseHelper from './MouseHelper';
|
|
5
|
-
import {
|
|
5
|
+
import { stub } from 'sinon';
|
|
6
6
|
const gets = [];
|
|
7
7
|
let posts = [];
|
|
8
8
|
let normalFetch;
|
|
@@ -205,11 +205,7 @@ export const loadStore = async () => {
|
|
|
205
205
|
return store;
|
|
206
206
|
};
|
|
207
207
|
export const mockNow = (isodate) => {
|
|
208
|
-
|
|
209
|
-
// mock the current time
|
|
210
|
-
replace(DateTime, 'now', () => {
|
|
211
|
-
return now;
|
|
212
|
-
});
|
|
208
|
+
return stub(DateTime, 'now').returns(DateTime.fromISO(isodate));
|
|
213
209
|
};
|
|
214
210
|
export const getOptions = (select) => {
|
|
215
211
|
return select.shadowRoot.querySelector('temba-options[visible]');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { replace, stub } from 'sinon';\nimport { Select, SelectOption } from '../src/select/Select';\nimport { Options } from '../src/options/Options';\nimport { Attachment } from '../src/interfaces';\nimport { Compose } from '../src/compose/Compose';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n status: string;\n}\n\nconst gets: CodeMock[] = [];\nlet posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = (mocked) => {\n const mockResponse = new window.Response(mocked.body, {\n status: mocked.status,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = (mocked) => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: mocked.status,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options = { method: 'GET' }) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find((mock) => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nconst mockMapping = {\n '/test-assets/api/users/admin1.json': [\n /\\/api\\/v2\\/users.json\\?email=admin1@nyaruka.com/\n ],\n '/test-assets/api/users/editor1.json': [\n /\\/api\\/v2\\/users.json\\?email=editor1@nyaruka.com/\n ],\n '/test-assets/api/users/agent1.json': [\n /\\/api\\/v2\\/users.json\\?email=agent1@nyaruka.com/\n ],\n '/test-assets/api/users/viewer1.json': [\n /\\/api\\/v2\\/users.json\\?email=viewer1@nyaruka.com/\n ],\n '/test-assets/contacts/contact-tickets.json': [\n /\\/api\\/v2\\/tickets.json\\?contact=24d64810-3315-4ff5-be85-48e3fe055bf9/\n ]\n};\n\nexport const mockAPI = () => {\n for (const key in mockMapping) {\n const urls = mockMapping[key];\n for (const url of urls) {\n mockGET(url, key);\n }\n }\n};\n\nexport const mockGET = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n gets.push({ endpoint, body, headers, status });\n};\n\nexport const mockPOST = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n posts.push({ endpoint, body, headers, status });\n};\n\nexport const clearMockPosts = () => {\n posts = [];\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\n// Enhanced wait utility for more robust testing\nexport const waitForCondition = async (\n predicate: () => boolean,\n maxAttempts: number = 20,\n delayMs: number = 50\n): Promise<void> => {\n let attempts = 0;\n while (!predicate() && attempts < maxAttempts) {\n await delay(delayMs);\n attempts++;\n }\n if (!predicate()) {\n throw new Error(\n `Condition not met after ${maxAttempts} attempts (${\n maxAttempts * delayMs\n }ms)`\n );\n }\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n // detect if we're running in copilot's environment and use adaptive threshold\n const isCopilotEnvironment = (window as any).isCopilotEnvironment;\n const threshold = isCopilotEnvironment ? 1.0 : 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x\n };\n\n return newClip;\n};\n\nexport const mouseClickElement = async (ele: HTMLElement | Element) => {\n const bounds = ele.getBoundingClientRect();\n await mouseClick(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n users='/test-assets/store/users.json'\n workspace='/test-assets/store/workspace.json'\n />`\n );\n await store.initialHttpComplete;\n await store.initialHttpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n replace(DateTime, 'now', () => {\n return now;\n });\n};\n\nexport const getOptions = (select: Select<SelectOption>): Options => {\n return select.shadowRoot.querySelector('temba-options[visible]');\n};\n\nexport const clickOption = async (\n clock: any,\n select: Select<SelectOption>,\n index: number\n) => {\n const options = getOptions(select);\n if (!options) {\n throw new Error('No options element found');\n }\n\n // Wait for the specific option to be available, but only if it's not already there\n const existingOption = options.shadowRoot?.querySelector(\n `[data-option-index=\"${index}\"]`\n );\n if (!existingOption) {\n try {\n await waitForCondition(\n () => {\n const option = options.shadowRoot?.querySelector(\n `[data-option-index=\"${index}\"]`\n );\n return !!option;\n },\n 10,\n 25\n );\n } catch (e) {\n throw new Error(`Option at index ${index} not found after waiting`);\n }\n }\n\n const option = options.shadowRoot.querySelector(\n `[data-option-index=\"${index}\"]`\n ) as HTMLDivElement;\n\n await mouseClickElement(option);\n await options.updateComplete;\n await select.updateComplete;\n await clock.runAll();\n\n checkTimers(clock);\n};\nexport const openSelect = async (clock: any, select: Select<SelectOption>) => {\n const container = select.shadowRoot.querySelector('.select-container');\n container.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n\n clock.runAll();\n\n // add more explicit waiting and clock ticks\n await select.updateComplete;\n clock.runAll();\n\n // reduce wait time for options to become visible\n await waitFor(25);\n clock.runAll();\n\n // For non-endpoint selects, options might be immediately available\n // For endpoint selects, we need to wait for them to load\n const hasEndpoint = select.getAttribute('endpoint');\n if (hasEndpoint) {\n try {\n // Wait for options to be properly rendered and visible (but only for endpoint selects)\n await waitForCondition(\n () => {\n const options = select.shadowRoot.querySelector(\n 'temba-options[visible]'\n );\n return options && options.isConnected;\n },\n 10,\n 25\n );\n } catch (e) {\n // If condition fails, continue - some tests might not need options to be visible immediately\n }\n }\n};\n\nexport const openAndClick = async (\n clock: any,\n select: Select<SelectOption>,\n idx: number\n) => {\n await openSelect(clock, select);\n\n // Add this line to ensure proper timing when running as part of a test suite\n await select.updateComplete;\n clock.tick(25); // Reduced from 50 to give minimum time for options to render\n\n await clickOption(clock, select, idx);\n};\n\n// valid = attachments that are uploaded sent to the server when the user clicks send\nexport const getValidAttachments = (numFiles = 2): Attachment[] => {\n const attachments = [];\n let index = 1;\n while (index <= numFiles) {\n const s = 's' + index;\n const attachment = {\n uuid: s,\n content_type: 'image/png',\n type: 'image/png',\n filename: 'name_' + s,\n url: 'url_' + s,\n size: 1024,\n error: null\n } as Attachment;\n attachments.push(attachment);\n index++;\n }\n return attachments;\n};\n\nexport const updateComponent = async (\n compose: Compose,\n text?: string,\n attachments?: Attachment[]\n): Promise<void> => {\n compose.initialText = text ? text : '';\n compose.currentAttachments = attachments ? attachments : [];\n await compose.updateComplete;\n};\nexport const getValidText = () => {\n return 'sà-wàd-dee!';\n};\n\n// Helper for waiting for select pagination to complete\nexport const waitForSelectPagination = async (\n select: Select<SelectOption>,\n clock: any,\n expectedCount: number,\n maxAttempts: number = 30\n): Promise<void> => {\n let attempts = 0;\n while (attempts < maxAttempts) {\n // Ensure we're not still fetching\n if (!select.fetching && select.visibleOptions.length >= expectedCount) {\n return;\n }\n\n await select.updateComplete;\n clock.runAll();\n\n // Give more time between attempts for slow CI environments\n await delay(75);\n\n attempts++;\n }\n\n throw new Error(\n `Pagination did not complete after ${maxAttempts} attempts (${\n maxAttempts * 75\n }ms). ` +\n `Expected ${expectedCount} options, got ${select.visibleOptions.length}. ` +\n `Fetching: ${select.fetching}`\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { stub } from 'sinon';\nimport { Select, SelectOption } from '../src/form/select/Select';\nimport { Options } from '../src/display/Options';\nimport { Attachment } from '../src/interfaces';\nimport { Compose } from '../src/form/Compose';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n status: string;\n}\n\nconst gets: CodeMock[] = [];\nlet posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = (mocked) => {\n const mockResponse = new window.Response(mocked.body, {\n status: mocked.status,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = (mocked) => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: mocked.status,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers\n }\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options = { method: 'GET' }) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find((mock) => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nconst mockMapping = {\n '/test-assets/api/users/admin1.json': [\n /\\/api\\/v2\\/users.json\\?email=admin1@nyaruka.com/\n ],\n '/test-assets/api/users/editor1.json': [\n /\\/api\\/v2\\/users.json\\?email=editor1@nyaruka.com/\n ],\n '/test-assets/api/users/agent1.json': [\n /\\/api\\/v2\\/users.json\\?email=agent1@nyaruka.com/\n ],\n '/test-assets/api/users/viewer1.json': [\n /\\/api\\/v2\\/users.json\\?email=viewer1@nyaruka.com/\n ],\n '/test-assets/contacts/contact-tickets.json': [\n /\\/api\\/v2\\/tickets.json\\?contact=24d64810-3315-4ff5-be85-48e3fe055bf9/\n ]\n};\n\nexport const mockAPI = () => {\n for (const key in mockMapping) {\n const urls = mockMapping[key];\n for (const url of urls) {\n mockGET(url, key);\n }\n }\n};\n\nexport const mockGET = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n gets.push({ endpoint, body, headers, status });\n};\n\nexport const mockPOST = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n posts.push({ endpoint, body, headers, status });\n};\n\nexport const clearMockPosts = () => {\n posts = [];\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\n// Enhanced wait utility for more robust testing\nexport const waitForCondition = async (\n predicate: () => boolean,\n maxAttempts: number = 20,\n delayMs: number = 50\n): Promise<void> => {\n let attempts = 0;\n while (!predicate() && attempts < maxAttempts) {\n await delay(delayMs);\n attempts++;\n }\n if (!predicate()) {\n throw new Error(\n `Condition not met after ${maxAttempts} attempts (${\n maxAttempts * delayMs\n }ms)`\n );\n }\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n // detect if we're running in copilot's environment and use adaptive threshold\n const isCopilotEnvironment = (window as any).isCopilotEnvironment;\n const threshold = isCopilotEnvironment ? 1.0 : 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x\n };\n\n return newClip;\n};\n\nexport const mouseClickElement = async (ele: HTMLElement | Element) => {\n const bounds = ele.getBoundingClientRect();\n await mouseClick(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n users='/test-assets/store/users.json'\n workspace='/test-assets/store/workspace.json'\n />`\n );\n await store.initialHttpComplete;\n await store.initialHttpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n return stub(DateTime, 'now').returns(DateTime.fromISO(isodate));\n};\n\nexport const getOptions = (select: Select<SelectOption>): Options => {\n return select.shadowRoot.querySelector('temba-options[visible]');\n};\n\nexport const clickOption = async (\n clock: any,\n select: Select<SelectOption>,\n index: number\n) => {\n const options = getOptions(select);\n if (!options) {\n throw new Error('No options element found');\n }\n\n // Wait for the specific option to be available, but only if it's not already there\n const existingOption = options.shadowRoot?.querySelector(\n `[data-option-index=\"${index}\"]`\n );\n if (!existingOption) {\n try {\n await waitForCondition(\n () => {\n const option = options.shadowRoot?.querySelector(\n `[data-option-index=\"${index}\"]`\n );\n return !!option;\n },\n 10,\n 25\n );\n } catch (e) {\n throw new Error(`Option at index ${index} not found after waiting`);\n }\n }\n\n const option = options.shadowRoot.querySelector(\n `[data-option-index=\"${index}\"]`\n ) as HTMLDivElement;\n\n await mouseClickElement(option);\n await options.updateComplete;\n await select.updateComplete;\n await clock.runAll();\n\n checkTimers(clock);\n};\nexport const openSelect = async (clock: any, select: Select<SelectOption>) => {\n const container = select.shadowRoot.querySelector('.select-container');\n container.dispatchEvent(new MouseEvent('click', { bubbles: true }));\n\n clock.runAll();\n\n // add more explicit waiting and clock ticks\n await select.updateComplete;\n clock.runAll();\n\n // reduce wait time for options to become visible\n await waitFor(25);\n clock.runAll();\n\n // For non-endpoint selects, options might be immediately available\n // For endpoint selects, we need to wait for them to load\n const hasEndpoint = select.getAttribute('endpoint');\n if (hasEndpoint) {\n try {\n // Wait for options to be properly rendered and visible (but only for endpoint selects)\n await waitForCondition(\n () => {\n const options = select.shadowRoot.querySelector(\n 'temba-options[visible]'\n );\n return options && options.isConnected;\n },\n 10,\n 25\n );\n } catch (e) {\n // If condition fails, continue - some tests might not need options to be visible immediately\n }\n }\n};\n\nexport const openAndClick = async (\n clock: any,\n select: Select<SelectOption>,\n idx: number\n) => {\n await openSelect(clock, select);\n\n // Add this line to ensure proper timing when running as part of a test suite\n await select.updateComplete;\n clock.tick(25); // Reduced from 50 to give minimum time for options to render\n\n await clickOption(clock, select, idx);\n};\n\n// valid = attachments that are uploaded sent to the server when the user clicks send\nexport const getValidAttachments = (numFiles = 2): Attachment[] => {\n const attachments = [];\n let index = 1;\n while (index <= numFiles) {\n const s = 's' + index;\n const attachment = {\n uuid: s,\n content_type: 'image/png',\n type: 'image/png',\n filename: 'name_' + s,\n url: 'url_' + s,\n size: 1024,\n error: null\n } as Attachment;\n attachments.push(attachment);\n index++;\n }\n return attachments;\n};\n\nexport const updateComponent = async (\n compose: Compose,\n text?: string,\n attachments?: Attachment[]\n): Promise<void> => {\n compose.initialText = text ? text : '';\n compose.currentAttachments = attachments ? attachments : [];\n await compose.updateComplete;\n};\nexport const getValidText = () => {\n return 'sà-wàd-dee!';\n};\n\n// Helper for waiting for select pagination to complete\nexport const waitForSelectPagination = async (\n select: Select<SelectOption>,\n clock: any,\n expectedCount: number,\n maxAttempts: number = 30\n): Promise<void> => {\n let attempts = 0;\n while (attempts < maxAttempts) {\n // Ensure we're not still fetching\n if (!select.fetching && select.visibleOptions.length >= expectedCount) {\n return;\n }\n\n await select.updateComplete;\n clock.runAll();\n\n // Give more time between attempts for slow CI environments\n await delay(75);\n\n attempts++;\n }\n\n throw new Error(\n `Pagination did not complete after ${maxAttempts} attempts (${\n maxAttempts * 75\n }ms). ` +\n `Expected ${expectedCount} options, got ${select.visibleOptions.length}. ` +\n `Fetching: ${select.fetching}`\n );\n};\n"]}
|