@nyaruka/temba-components 0.135.9 → 0.136.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/demo/components/webchat/example.html +4 -2
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1351 -322
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +2 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +2 -6
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +29 -1
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +229 -5
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +320 -1
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +30 -8
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -1
- package/out-tsc/src/simulator/Simulator.js +1861 -0
- package/out-tsc/src/simulator/Simulator.js.map +1 -0
- package/out-tsc/src/store/AppState.js +66 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils.js +48 -0
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +2 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-appstate-node-sorting.test.js +430 -0
- package/out-tsc/test/temba-appstate-node-sorting.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +0 -9
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +262 -1
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +3 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +3 -1
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-simulator.test.js +642 -0
- package/out-tsc/test/temba-simulator.test.js.map +1 -0
- package/out-tsc/test/utils.test.js +1 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- 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/add_contact_urn/render/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/whatsapp.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_broadcast/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/multiline-text.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/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/actions/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/screenshots/truth/simulator/after-message-sent.png +0 -0
- package/screenshots/truth/simulator/after-reset.png +0 -0
- package/screenshots/truth/simulator/attachment-menu.png +0 -0
- package/screenshots/truth/simulator/context-expanded.png +0 -0
- package/screenshots/truth/simulator/context-explorer-open.png +0 -0
- package/screenshots/truth/simulator/event-info.png +0 -0
- package/screenshots/truth/simulator/image-attachment.png +0 -0
- package/screenshots/truth/simulator/open-initial.png +0 -0
- package/screenshots/truth/simulator/quick-replies.png +0 -0
- package/src/Icons.ts +2 -1
- package/src/display/FloatingTab.ts +2 -7
- package/src/flow/CanvasNode.ts +30 -1
- package/src/flow/Editor.ts +246 -4
- package/src/flow/Plumber.ts +371 -2
- package/src/interfaces.ts +2 -1
- package/src/layout/FloatingWindow.ts +37 -12
- package/src/simulator/Simulator.ts +2061 -0
- package/src/store/AppState.ts +109 -0
- package/src/utils.ts +53 -0
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/route.svg +1 -0
- package/static/svg/work/used/route.svg +3 -0
- package/temba-modules.ts +2 -0
- package/test/temba-appstate-node-sorting.test.ts +506 -0
- package/test/temba-floating-tab.test.ts +0 -11
- package/test/temba-flow-editor.test.ts +298 -1
- package/test/temba-flow-plumber-connections.test.ts +4 -1
- package/test/temba-flow-plumber.test.ts +4 -1
- package/test/temba-simulator.test.ts +866 -0
- package/test/utils.test.ts +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temba-simulator.test.js","sourceRoot":"","sources":["../../test/temba-simulator.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { fixture, expect, assert } from '@open-wc/testing';\nimport { Simulator } from '../src/simulator/Simulator';\nimport {\n assertScreenshot,\n getClip,\n mockPOST,\n clearMockPosts,\n delay,\n waitForCondition,\n loadStore\n} from './utils.test';\n\nconst FLOW_UUID = 'test-flow-123';\n\nconst createSimulator = async (attrs: any = {}) => {\n // load store first since simulator depends on it\n await loadStore();\n\n const defaults = {\n flow: FLOW_UUID,\n animationTime: '0' // disable animations for deterministic tests\n };\n const mergedAttrs = { ...defaults, ...attrs };\n\n const attrString = Object.entries(mergedAttrs)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(' ');\n\n const simulator: Simulator = await fixture(\n `<temba-simulator ${attrString}></temba-simulator>`\n );\n\n // reset cookie-based properties for deterministic tests\n simulator.size = 'medium';\n (simulator as any).following = true;\n (simulator as any).contextExplorerOpen = false;\n await simulator.updateComplete;\n\n return simulator;\n};\n\n// helper to open the simulator\nconst openSimulator = async (simulator: Simulator) => {\n const tab = simulator.shadowRoot.querySelector('temba-floating-tab') as any;\n expect(tab).to.exist;\n\n // trigger the button clicked event on the tab\n tab.dispatchEvent(new CustomEvent('temba-button-clicked', { bubbles: true }));\n\n await simulator.updateComplete;\n // brief delay for async API mock processing\n await delay(50);\n};\n\n// helper to get clip for the simulator window (fixed positioning)\nconst getSimulatorClip = (\n simulator: Simulator,\n includeContext: boolean = false\n) => {\n const phoneWindow = simulator.shadowRoot.querySelector(\n 'temba-floating-window'\n ) as any;\n\n if (!phoneWindow) {\n // if window not open, use default clip\n return getClip(simulator);\n }\n\n const windowElement = phoneWindow.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n if (!windowElement) {\n return getClip(simulator);\n }\n\n const windowBounds = windowElement.getBoundingClientRect();\n\n if (includeContext) {\n // get the context explorer and phone to clip just those areas\n const phoneSimulator = phoneWindow.querySelector(\n '.phone-simulator'\n ) as HTMLElement;\n if (!phoneSimulator) {\n return getClip(simulator);\n }\n\n const contextExplorer = phoneSimulator.querySelector(\n '.context-explorer'\n ) as HTMLElement;\n const phoneFrame = phoneSimulator.querySelector(\n '.phone-frame'\n ) as HTMLElement;\n\n if (!contextExplorer || !phoneFrame) {\n return {\n x: windowBounds.x,\n y: windowBounds.y,\n width: windowBounds.width,\n height: windowBounds.height\n };\n }\n\n const contextBounds = contextExplorer.getBoundingClientRect();\n const phoneBounds = phoneFrame.getBoundingClientRect();\n\n // clip from the left edge of context explorer to the right edge of phone frame only\n // do not include the option-pane which is to the right of the phone\n // keep padding within the phone bounds to avoid capturing the gap to the option pane\n const padding = 10;\n const leftX = contextBounds.x - padding;\n\n // don't extend past the phone frame right edge - the option pane is close by\n const rightX = phoneBounds.right;\n\n const topY = Math.min(contextBounds.y, phoneBounds.y) - padding;\n const bottomY =\n Math.max(contextBounds.bottom, phoneBounds.bottom) + padding;\n\n return {\n x: leftX,\n y: topY,\n width: rightX - leftX,\n height: bottomY - topY\n };\n }\n\n // the phone-simulator is in the light DOM of the phoneWindow (slotted content)\n const phoneSimulator = phoneWindow.querySelector(\n '.phone-simulator'\n ) as HTMLElement;\n if (!phoneSimulator) {\n return getClip(simulator);\n }\n\n // get the phone-frame from within the phone-simulator\n const phoneFrame = phoneSimulator.querySelector(\n '.phone-frame'\n ) as HTMLElement;\n if (!phoneFrame) {\n // fallback to window bounds if phone-frame not found\n return {\n x: windowBounds.x,\n y: windowBounds.y,\n width: windowBounds.width,\n height: windowBounds.height\n };\n }\n\n const frameBounds = phoneFrame.getBoundingClientRect();\n\n // add padding around the phone frame\n const padding = 10;\n return {\n x: frameBounds.x - padding,\n y: frameBounds.y - padding,\n width: frameBounds.width + padding * 2,\n height: frameBounds.height + padding * 2\n };\n};\n\n// mock responses for simulation endpoints\nconst mockSimulatorStart = () => {\n const response = {\n session: {\n status: 'waiting',\n trigger: {\n type: 'manual',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' }\n },\n runs: [\n {\n uuid: 'run-1',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' },\n status: 'waiting',\n path: [\n {\n uuid: 'step-1',\n node_uuid: 'node-1',\n arrived_on: new Date().toISOString(),\n exit_uuid: null\n }\n ]\n }\n ],\n environment: {\n date_format: 'YYYY-MM-DD',\n time_format: 'HH:mm',\n timezone: 'America/New_York',\n allowed_languages: ['eng'],\n default_country: 'US'\n }\n },\n events: [\n {\n type: 'msg_created',\n created_on: new Date().toISOString(),\n msg: {\n uuid: 'msg-1',\n text: 'Hello! How can I help you today?',\n urn: 'tel:+12065551212'\n }\n }\n ],\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n },\n context: {\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n name: 'Test User',\n urns: {\n tel: ['+12065551212'],\n __default__: '+12065551212'\n },\n fields: {\n age: '25',\n city: 'Seattle'\n }\n },\n trigger: {\n type: 'manual',\n __default__: 'manual'\n }\n }\n };\n\n mockPOST(/\\/flow\\/simulate\\/.*\\//, response);\n};\n\nconst mockSimulatorResume = (responseText: string, quickReplies?: string[]) => {\n const msg: any = {\n uuid: 'msg-response',\n text: responseText,\n urn: 'tel:+12065551212'\n };\n\n if (quickReplies) {\n msg.quick_replies = quickReplies.map((text) => ({ text }));\n }\n\n const response = {\n session: {\n status: 'waiting',\n trigger: {\n type: 'manual',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' }\n },\n runs: [\n {\n uuid: 'run-1',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' },\n status: 'waiting',\n path: [\n {\n uuid: 'step-1',\n node_uuid: 'node-1',\n arrived_on: new Date().toISOString(),\n exit_uuid: 'exit-1'\n },\n {\n uuid: 'step-2',\n node_uuid: 'node-2',\n arrived_on: new Date().toISOString(),\n exit_uuid: null\n }\n ]\n }\n ],\n environment: {\n date_format: 'YYYY-MM-DD',\n time_format: 'HH:mm',\n timezone: 'America/New_York',\n allowed_languages: ['eng'],\n default_country: 'US'\n }\n },\n events: [\n {\n type: 'msg_created',\n created_on: new Date().toISOString(),\n msg\n }\n ],\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {\n age: '25',\n city: 'Seattle'\n },\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n },\n context: {\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n name: 'Test User',\n urns: {\n tel: ['+12065551212'],\n __default__: '+12065551212'\n },\n fields: {\n age: '25',\n city: 'Seattle'\n }\n },\n results: {\n user_response: {\n value: responseText,\n __default__: responseText\n }\n }\n }\n };\n\n mockPOST(/\\/flow\\/simulate\\/.*\\//, response);\n};\n\ndescribe('temba-simulator', () => {\n beforeEach(() => {\n clearMockPosts();\n });\n\n it('can be created', async () => {\n const simulator: Simulator = await createSimulator();\n assert.instanceOf(simulator, Simulator);\n expect(simulator.flow).to.equal(FLOW_UUID);\n expect(simulator.endpoint).to.equal(`/flow/simulate/${FLOW_UUID}/`);\n });\n\n it('opens simulator window and starts flow', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n // ensure consistent size for screenshot\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n const phoneWindow = simulator.shadowRoot.querySelector(\n 'temba-floating-window'\n ) as any;\n expect(phoneWindow).to.exist;\n\n // verify phone screen is visible\n const phoneScreen = simulator.shadowRoot.querySelector('.phone-screen');\n expect(phoneScreen).to.exist;\n\n // verify initial message is displayed\n const messages = simulator.shadowRoot.querySelectorAll('.message');\n expect(messages.length).to.be.greaterThan(0);\n\n await assertScreenshot(\n 'simulator/open-initial',\n getSimulatorClip(simulator)\n );\n });\n\n it('sends a text message', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n // count initial messages\n let messages = simulator.shadowRoot.querySelectorAll('.message');\n const initialCount = messages.length;\n\n // mock the resume response\n mockSimulatorResume('Thanks for your message!');\n\n // type a message\n const input = simulator.shadowRoot.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n expect(input).to.exist;\n\n input.value = 'Hello from test';\n input.dispatchEvent(new Event('input'));\n await simulator.updateComplete;\n\n // press enter to send\n const enterEvent = new KeyboardEvent('keyup', {\n key: 'Enter',\n bubbles: true\n });\n input.dispatchEvent(enterEvent);\n\n await simulator.updateComplete;\n // brief delay for async API mock processing\n await delay(100);\n\n // verify we have more messages than before\n messages = simulator.shadowRoot.querySelectorAll('.message');\n expect(messages.length).to.be.greaterThan(initialCount);\n\n // ensure DOM is settled\n await simulator.updateComplete;\n\n await assertScreenshot(\n 'simulator/after-message-sent',\n getSimulatorClip(simulator)\n );\n });\n\n it('tests message flow and takes screenshot', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n // clear previous mocks and set up new mock for a response\n clearMockPosts();\n mockSimulatorResume('Thank you for your message!', ['Yes', 'No', 'Maybe']);\n\n // send a message\n const input = simulator.shadowRoot.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n input.value = 'Test message';\n input.dispatchEvent(new Event('input'));\n\n const enterEvent = new KeyboardEvent('keyup', {\n key: 'Enter',\n bubbles: true\n });\n input.dispatchEvent(enterEvent);\n\n // wait for quick replies to appear\n await waitForCondition(\n () =>\n simulator.shadowRoot.querySelectorAll('.quick-reply-btn').length > 0,\n 2000\n );\n await simulator.updateComplete;\n\n // take screenshot with quick replies\n await assertScreenshot(\n 'simulator/quick-replies',\n getSimulatorClip(simulator)\n );\n });\n\n it('opens attachment menu', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n // click the attachment button\n const attachmentButton = simulator.shadowRoot.querySelector(\n '.attachment-button'\n ) as HTMLElement;\n expect(attachmentButton).to.exist;\n attachmentButton.click();\n\n await simulator.updateComplete;\n\n // verify attachment menu is displayed\n const attachmentMenu =\n simulator.shadowRoot.querySelector('.attachment-menu');\n expect(attachmentMenu).to.exist;\n expect(attachmentMenu.classList.contains('open')).to.be.true;\n\n await assertScreenshot(\n 'simulator/attachment-menu',\n getSimulatorClip(simulator)\n );\n });\n\n it('sends an image attachment', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n // reset attachment indices for deterministic testing\n simulator.resetAttachmentIndices();\n await openSimulator(simulator);\n\n // mock the response for image attachment\n mockSimulatorResume('Nice picture!');\n\n // open attachment menu and click image option\n const attachmentButton = simulator.shadowRoot.querySelector(\n '.attachment-button'\n ) as HTMLElement;\n attachmentButton.click();\n await simulator.updateComplete;\n await delay(200);\n\n const imageMenuItem = Array.from(\n simulator.shadowRoot.querySelectorAll('.attachment-menu-item')\n ).find((el) => el.textContent?.includes('Image')) as HTMLElement;\n expect(imageMenuItem).to.exist;\n imageMenuItem.click();\n\n await delay(100);\n await simulator.updateComplete;\n\n // verify attachment wrapper is displayed (image attachments show in attachments not messages)\n const attachmentWrappers = simulator.shadowRoot.querySelectorAll(\n '.attachment-wrapper'\n );\n expect(attachmentWrappers.length).to.be.greaterThan(0);\n\n await assertScreenshot(\n 'simulator/image-attachment',\n getSimulatorClip(simulator)\n );\n });\n\n it('opens context explorer', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n await openSimulator(simulator);\n\n // find and click the context explorer button (has expressions icon)\n const optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n const contextButton = optionButtons.find((btn) =>\n btn.querySelector('temba-icon[name=\"expressions\"]')\n ) as HTMLElement;\n expect(contextButton).to.exist;\n contextButton.click();\n\n await simulator.updateComplete;\n await delay(100);\n\n // verify context explorer is displayed\n const contextExplorer =\n simulator.shadowRoot.querySelector('.context-explorer');\n expect(contextExplorer).to.exist;\n expect(contextExplorer.classList.contains('open')).to.be.true;\n\n // delay for context explorer to fully render\n await delay(300);\n await simulator.updateComplete;\n await document.fonts.ready;\n\n await assertScreenshot(\n 'simulator/context-explorer-open',\n getSimulatorClip(simulator, true)\n );\n });\n\n it('expands context tree items', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n await openSimulator(simulator);\n\n // ensure context explorer starts closed\n if ((simulator as any).contextExplorerOpen) {\n // click to close it first\n const optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n const contextButton = optionButtons.find((btn) =>\n btn.querySelector('temba-icon[name=\"expressions\"]')\n ) as HTMLElement;\n contextButton.click();\n await simulator.updateComplete;\n await delay(100);\n }\n\n // now open context explorer\n const optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n const contextButton = optionButtons.find((btn) =>\n btn.querySelector('temba-icon[name=\"expressions\"]')\n ) as HTMLElement;\n expect(contextButton).to.exist;\n contextButton.click();\n\n await simulator.updateComplete;\n await delay(100);\n\n // verify context explorer is now open\n expect((simulator as any).contextExplorerOpen).to.be.true;\n const contextExplorer =\n simulator.shadowRoot.querySelector('.context-explorer');\n expect(contextExplorer).to.exist;\n expect(contextExplorer.classList.contains('open')).to.be.true;\n\n // find and click on an expandable item (should have context-item-expandable class)\n const expandableItems = simulator.shadowRoot.querySelectorAll(\n '.context-item-expandable'\n );\n expect(expandableItems.length).to.be.greaterThan(0);\n\n const firstExpandable = expandableItems[0] as HTMLElement;\n firstExpandable.click();\n\n // wait for children to be displayed with specific content\n await waitForCondition(() => {\n const children =\n simulator.shadowRoot.querySelectorAll('.context-children');\n if (children.length === 0) return false;\n // also check that the children have rendered content\n const items = simulator.shadowRoot.querySelectorAll('.context-item');\n return items.length > expandableItems.length;\n }, 2000);\n\n // verify children are displayed\n const contextChildren =\n simulator.shadowRoot.querySelectorAll('.context-children');\n expect(contextChildren.length).to.be.greaterThan(0);\n\n await simulator.updateComplete;\n // delay for DOM to fully render expanded content (context rendering is complex)\n await delay(300);\n await simulator.updateComplete;\n\n // ensure fonts are loaded and give extra time for rendering\n await document.fonts.ready;\n\n // wait for any pending animation frames\n await new Promise((resolve) =>\n requestAnimationFrame(() => requestAnimationFrame(resolve))\n );\n await delay(200);\n\n await assertScreenshot(\n 'simulator/context-expanded',\n getSimulatorClip(simulator, true)\n );\n });\n\n it('cycles simulator size', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n await openSimulator(simulator);\n\n // initially should be medium (set in createSimulator)\n expect(simulator.size).to.equal('medium');\n\n // find and click the size button (shows current size as text)\n const optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n const sizeButton = optionButtons.find((btn) => {\n const text = btn.textContent?.trim();\n return text === 'S' || text === 'M' || text === 'L';\n }) as HTMLElement;\n expect(sizeButton).to.exist;\n sizeButton.click();\n\n await simulator.updateComplete;\n\n // should now be large (medium -> large)\n expect(simulator.size).to.equal('large');\n });\n\n it('resets simulation', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n // send a message first\n mockSimulatorResume('Response to test message');\n const input = simulator.shadowRoot.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n input.value = 'Test message';\n input.dispatchEvent(new Event('input'));\n\n const enterEvent = new KeyboardEvent('keyup', {\n key: 'Enter',\n bubbles: true\n });\n input.dispatchEvent(enterEvent);\n\n await delay(1000);\n await simulator.updateComplete;\n\n // verify we have multiple messages\n let messages = simulator.shadowRoot.querySelectorAll('.message');\n const messageCountBefore = messages.length;\n expect(messageCountBefore).to.be.greaterThan(1);\n\n // mock the start response for reset\n mockSimulatorStart();\n\n // click the reset button (has delete icon)\n const optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n const resetButton = optionButtons.find((btn) =>\n btn.querySelector('temba-icon[name=\"delete\"]')\n ) as HTMLElement;\n expect(resetButton).to.exist;\n resetButton.click();\n\n await delay(100);\n await simulator.updateComplete;\n\n // verify messages are reset - should go back to just initial message\n messages = simulator.shadowRoot.querySelectorAll('.message');\n expect(messages.length).to.be.lessThan(messageCountBefore);\n\n await assertScreenshot(\n 'simulator/after-reset',\n getSimulatorClip(simulator)\n );\n });\n\n it('displays event info messages', async () => {\n const responseWithEvents = {\n session: {\n status: 'waiting',\n trigger: {\n type: 'manual',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' }\n },\n runs: [\n {\n uuid: 'run-1',\n flow: { uuid: FLOW_UUID, name: 'Test Flow' },\n status: 'waiting',\n path: [\n {\n uuid: 'step-1',\n node_uuid: 'node-1',\n arrived_on: new Date().toISOString(),\n exit_uuid: null\n }\n ]\n }\n ],\n environment: {\n date_format: 'YYYY-MM-DD',\n time_format: 'HH:mm',\n timezone: 'America/New_York',\n allowed_languages: ['eng'],\n default_country: 'US'\n }\n },\n events: [\n {\n type: 'contact_field_changed',\n created_on: new Date().toISOString(),\n field: { key: 'name', name: 'Name' },\n value: { text: 'John Doe' }\n },\n {\n type: 'msg_created',\n created_on: new Date().toISOString(),\n msg: {\n uuid: 'msg-1',\n text: 'Your name has been updated!',\n urn: 'tel:+12065551212'\n }\n }\n ],\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {\n name: 'John Doe'\n },\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n },\n context: {\n contact: {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n name: 'John Doe',\n fields: {\n name: 'John Doe'\n }\n }\n }\n };\n\n mockPOST(/\\/flow\\/simulate\\/.*\\//, responseWithEvents);\n\n const simulator: Simulator = await createSimulator();\n simulator.size = 'medium';\n await simulator.updateComplete;\n await openSimulator(simulator);\n\n // verify event info is displayed\n const eventInfo = simulator.shadowRoot.querySelectorAll('.event-info');\n expect(eventInfo.length).to.be.greaterThan(0);\n\n await assertScreenshot('simulator/event-info', getSimulatorClip(simulator));\n });\n\n it('displays different simulator sizes', async () => {\n mockSimulatorStart();\n\n const simulator: Simulator = await createSimulator();\n await openSimulator(simulator);\n\n // get size button - find it by checking if textContent is a size indicator\n let optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n let sizeButton = optionButtons.find((btn) => {\n const text = btn.textContent?.trim();\n return text === 'S' || text === 'M' || text === 'L';\n }) as HTMLElement;\n expect(sizeButton).to.exist;\n\n // cycle to next size\n sizeButton.click();\n await simulator.updateComplete;\n await delay(200);\n\n // verify size changed\n expect(simulator.size).to.equal('large');\n\n // re-query the button after it updated\n optionButtons = Array.from(\n simulator.shadowRoot.querySelectorAll('.option-btn')\n );\n sizeButton = optionButtons.find((btn) => {\n const text = btn.textContent?.trim();\n return text === 'S' || text === 'M' || text === 'L';\n }) as HTMLElement;\n\n // cycle to next size\n sizeButton.click();\n await simulator.updateComplete;\n await delay(200);\n\n expect(simulator.size).to.equal('small');\n });\n\n it('verifies simulator endpoint configuration', async () => {\n const simulator: Simulator = await createSimulator();\n\n // verify endpoint is set correctly from flow prop\n expect(simulator.endpoint).to.equal(`/flow/simulate/${FLOW_UUID}/`);\n\n // change flow prop and verify endpoint updates\n simulator.flow = 'different-flow-456';\n await simulator.updateComplete;\n\n expect(simulator.endpoint).to.equal('/flow/simulate/different-flow-456/');\n });\n});\n"]}
|
|
@@ -173,7 +173,7 @@ export const waitForCondition = async (predicate, maxAttempts = 20, delayMs = 50
|
|
|
173
173
|
export const assertScreenshot = async (filename, clip, waitForNetwork = false) => {
|
|
174
174
|
// detect if we're running in copilot's environment and use adaptive threshold
|
|
175
175
|
const isCopilotEnvironment = window.isCopilotEnvironment;
|
|
176
|
-
const threshold = isCopilotEnvironment ? 1.0 : 0.
|
|
176
|
+
const threshold = isCopilotEnvironment ? 1.0 : 0.2;
|
|
177
177
|
const exclude = [];
|
|
178
178
|
try {
|
|
179
179
|
await window.matchPageSnapshot(`${filename}.png`, clip, exclude, threshold, waitForNetwork);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAQjC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEjE,sEAAsE;AACtE,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,KAAK,CAAC,WAAW,GAAG;;;;CAInB,CAAC;AACF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAEjC,+DAA+D;AAC/D,sEAAsE;AACtE,MAAM,wBAAwB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACzD,MAAM,CAAC,gBAAgB,GAAG,UAAU,IAAI,EAAE,QAAQ,EAAE,OAAO;IACzD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,4CAA4C;QAC5C,OAAO;IACT,CAAC;IACD,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACtE,CAAmC,CAAC;AACpC,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAa7B,MAAM,IAAI,GAAe,EAAE,CAAC;AAC5B,IAAI,KAAK,GAAe,EAAE,CAAC;AAC3B,IAAI,WAAW,CAAC;AAEhB,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;IAClC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA,kBAAkB,CAAC,CAAC;IACpD,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAa,EAAE,EAAE,EAAE;IAC/C,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;SACzB,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE;QACpB,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACpC,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,GAAG,EACH,QAAa,EAAE,EACf,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,GAAG,EACX,MAAM,GAAG,CAAC,EACV,KAAK,GAAG,EAAE,EACV,EAAE;IACF,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,GAAG,GAAG,CAAC;IAChE,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG;MACnB,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE;MACpC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE;MACvC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;GACrB,CAAC;IACF,UAAU,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACjD,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,EAAE;IAChC,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE;QACpD,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE;YACP,cAAc,EAAE,WAAW;YAC3B,GAAG,MAAM,CAAC,OAAO;SAClB;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,EAAE;IACpC,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;QACpE,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,GAAG,MAAM,CAAC,OAAO;SAClB;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;IACpE,4CAA4C;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEpE,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,uCAAuC;YACvC,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,OAAO,cAAc,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,4BAA4B;IAC5B,OAAO,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,CAAC,KAAK,IAAI,EAAE;IAChB,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,GAAG,EAAE;IACR,MAAM,CAAC,KAAa,CAAC,OAAO,EAAE,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG;IAClB,oCAAoC,EAAE;QACpC,iDAAiD;KAClD;IACD,qCAAqC,EAAE;QACrC,kDAAkD;KACnD;IACD,oCAAoC,EAAE;QACpC,iDAAiD;KAClD;IACD,qCAAqC,EAAE;QACrC,kDAAkD;KACnD;IACD,4CAA4C,EAAE;QAC5C,uEAAuE;KACxE;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE;IAC1B,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,2BAA2B,EAAE;QACnC,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,EAAE;YAC5C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,EAAE;YAC5C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE;YACvC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,oBAAoB,EAAE;SAC/C;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,4BAA4B,EAAE;QACpC,OAAO,EAAE;YACP,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE;YAC/B,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE;YAC/B,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC9B,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE;YAClC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC/B;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,QAAgB,EAChB,IAAS,EACT,UAAe,EAAE,EACjB,MAAM,GAAG,KAAK,EACd,EAAE;IACF,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,QAAgB,EAChB,IAAS,EACT,UAAe,EAAE,EACjB,MAAM,GAAG,KAAK,EACd,EAAE;IACF,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,KAAK,GAAG,EAAE,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAU,EAAE,EAAE;IACxC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACnE,MAAM,CACJ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAChC,0BAA0B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CACzD,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAc,EAAE,EAAE;IACtC,OAAO,IAAI,OAAO,CAAC,UAAU,OAAO;QAClC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,SAAwB,EACxB,cAAsB,EAAE,EACxB,UAAkB,EAAE,EACL,EAAE;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,OAAO,CAAC,SAAS,EAAE,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC9C,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,QAAQ,EAAE,CAAC;IACb,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,2BAA2B,WAAW,cACpC,WAAW,GAAG,OAChB,KAAK,CACN,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,QAAgB,EAChB,IAAU,EACV,iBAA0B,KAAK,EAC/B,EAAE;IACF,8EAA8E;IAC9E,MAAM,oBAAoB,GAAI,MAAc,CAAC,oBAAoB,CAAC;IAClE,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACnD,MAAM,OAAO,GAAW,EAAE,CAAC;IAE3B,IAAI,CAAC;QACH,MAAO,MAAc,CAAC,iBAAiB,CACrC,GAAG,QAAQ,MAAM,EACjB,IAAI,EACJ,OAAO,EACP,SAAS,EACT,cAAc,CACf,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,OAAO,IACd,KAAK,CAAC,QAAQ;gBACZ,CAAC,CAAC,YAAY,KAAK,CAAC,QAAQ,YAAY,KAAK,CAAC,MAAM,EAAE;gBACtD,CAAC,CAAC,EACN,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvD,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAgB,EAAE,EAAE;IAC1C,IAAI,IAAI,GAAQ,GAAG,CAAC,qBAAqB,EAAE,CAAC;IAC5C,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC;IAClE,CAAC;IAED,mBAAmB;IACnB,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC;IAE3B,MAAM,OAAO,GAAG;QACd,CAAC;QACD,CAAC;QACD,KAAK;QACL,MAAM;QACN,MAAM,EAAE,CAAC,GAAG,MAAM;QAClB,KAAK,EAAE,CAAC,GAAG,KAAK;QAChB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;KACR,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAA0B,EAAE,EAAE;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;IAC3C,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAa,EAAE,EAAE,EAAE;IAC9C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;SACtB,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;SACjD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,QAAa,EAAE,EAAE,EAAE;IACtD,OAAO,IAAI,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;IAClC,MAAM,KAAK,GAAU,MAAM,OAAO,CAChC;;;;;;;OAOG,CACJ,CAAC;IACF,MAAM,KAAK,CAAC,mBAAmB,CAAC;IAChC,MAAM,KAAK,CAAC,mBAAmB,CAAC;IAEhC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;IACzC,OAAO,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAA4B,EAAW,EAAE;IAClE,OAAO,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,KAAU,EACV,MAA4B,EAC5B,KAAa,EACb,EAAE;;IACF,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,mFAAmF;IACnF,MAAM,cAAc,GAAG,MAAA,OAAO,CAAC,UAAU,0CAAE,aAAa,CACtD,uBAAuB,KAAK,IAAI,CACjC,CAAC;IACF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,uDAAuD;YACvD,MAAM,gBAAgB,CACpB,GAAG,EAAE;;gBACH,MAAM,MAAM,GAAG,MAAA,OAAO,CAAC,UAAU,0CAAE,aAAa,CAC9C,uBAAuB,KAAK,IAAI,CACjC,CAAC;gBACF,OAAO,CAAC,CAAC,MAAM,CAAC;YAClB,CAAC,EACD,EAAE,EACF,EAAE,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,0BAA0B,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAC7C,uBAAuB,KAAK,IAAI,CACf,CAAC;IAEpB,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,OAAO,CAAC,cAAc,CAAC;IAC7B,MAAM,MAAM,CAAC,cAAc,CAAC;IAC5B,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;IAErB,WAAW,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,KAAU,EAAE,MAA4B,EAAE,EAAE;IAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACvE,SAAS,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEpE,KAAK,CAAC,MAAM,EAAE,CAAC;IAEf,4CAA4C;IAC5C,MAAM,MAAM,CAAC,cAAc,CAAC;IAC5B,KAAK,CAAC,MAAM,EAAE,CAAC;IAEf,iDAAiD;IACjD,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAClB,KAAK,CAAC,MAAM,EAAE,CAAC;IAEf,mEAAmE;IACnE,yDAAyD;IACzD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,uFAAuF;YACvF,0DAA0D;YAC1D,MAAM,gBAAgB,CACpB,GAAG,EAAE;gBACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,aAAa,CAC7C,wBAAwB,CACzB,CAAC;gBACF,OAAO,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;YACxC,CAAC,EACD,EAAE,EACF,EAAE,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,6FAA6F;QAC/F,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,KAAU,EACV,MAA4B,EAC5B,GAAW,EACX,EAAE;IACF,MAAM,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEhC,6EAA6E;IAC7E,MAAM,MAAM,CAAC,cAAc,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,6DAA6D;IAE7E,MAAM,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAgB,EAAE;IAChE,MAAM,WAAW,GAAG,EAAE,CAAC;IACvB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC;QACtB,MAAM,UAAU,GAAG;YACjB,IAAI,EAAE,CAAC;YACP,YAAY,EAAE,WAAW;YACzB,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,OAAO,GAAG,CAAC;YACrB,GAAG,EAAE,MAAM,GAAG,CAAC;YACf,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;SACE,CAAC;QAChB,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,KAAK,EAAE,CAAC;IACV,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,OAAgB,EAChB,IAAa,EACb,WAA0B,EACX,EAAE;IACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACvC,OAAO,CAAC,kBAAkB,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,OAAO,CAAC,cAAc,CAAC;AAC/B,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,EAAE;IAC/B,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AAEF,uDAAuD;AACvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,MAA4B,EAC5B,KAAU,EACV,aAAqB,EACrB,cAAsB,EAAE,EACT,EAAE;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,OAAO,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC9B,kCAAkC;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,CAAC,cAAc,CAAC;QAC5B,KAAK,CAAC,MAAM,EAAE,CAAC;QAEf,2DAA2D;QAC3D,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhB,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,MAAM,IAAI,KAAK,CACb,qCAAqC,WAAW,cAC9C,WAAW,GAAG,EAChB,OAAO;QACL,YAAY,aAAa,iBAAiB,MAAM,CAAC,cAAc,CAAC,MAAM,IAAI;QAC1E,aAAa,MAAM,CAAC,QAAQ,EAAE,CACjC,CAAC;AACJ,CAAC,CAAC","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 } from '@open-wc/testing';\n\n// disable transitions for all tests to prevent flaky screenshot tests\nconst style = document.createElement('style');\nstyle.textContent = `\n * {\n --transition-speed: 0ms !important;\n }\n`;\ndocument.head.appendChild(style);\n\n// prevent resize event listeners from being added during tests\n// this prevents flaky positioning in components that adjust on resize\nconst originalAddEventListener = window.addEventListener;\nwindow.addEventListener = function (type, listener, options) {\n if (type === 'resize') {\n // skip adding resize listeners during tests\n return;\n }\n return originalAddEventListener.call(this, type, listener, options);\n} as typeof window.addEventListener;\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: 1920, height: 1080, 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 // Add mock data for contact form endpoints\n mockGET(/\\/api\\/v2\\/channels\\.json/, {\n results: [\n { uuid: 'chan-1', name: 'WhatsApp Channel' },\n { uuid: 'chan-2', name: 'Telegram Channel' },\n { uuid: 'chan-3', name: 'SMS Channel' },\n { uuid: 'chan-4', name: 'Facebook Messenger' }\n ]\n });\n\n mockGET(/\\/api\\/v2\\/languages\\.json/, {\n results: [\n { iso: 'eng', name: 'English' },\n { iso: 'spa', name: 'Spanish' },\n { iso: 'fra', name: 'French' },\n { iso: 'por', name: 'Portuguese' },\n { iso: 'deu', name: 'German' }\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 waitForNetwork: boolean = false\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 waitForNetwork\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 // add some padding\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 // Increased wait time to handle slower CI environments\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 // Increased max attempts to handle slower CI environments\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 } from '@open-wc/testing';\n\n// disable transitions for all tests to prevent flaky screenshot tests\nconst style = document.createElement('style');\nstyle.textContent = `\n * {\n --transition-speed: 0ms !important;\n }\n`;\ndocument.head.appendChild(style);\n\n// prevent resize event listeners from being added during tests\n// this prevents flaky positioning in components that adjust on resize\nconst originalAddEventListener = window.addEventListener;\nwindow.addEventListener = function (type, listener, options) {\n if (type === 'resize') {\n // skip adding resize listeners during tests\n return;\n }\n return originalAddEventListener.call(this, type, listener, options);\n} as typeof window.addEventListener;\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: 1920, height: 1080, 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 // Add mock data for contact form endpoints\n mockGET(/\\/api\\/v2\\/channels\\.json/, {\n results: [\n { uuid: 'chan-1', name: 'WhatsApp Channel' },\n { uuid: 'chan-2', name: 'Telegram Channel' },\n { uuid: 'chan-3', name: 'SMS Channel' },\n { uuid: 'chan-4', name: 'Facebook Messenger' }\n ]\n });\n\n mockGET(/\\/api\\/v2\\/languages\\.json/, {\n results: [\n { iso: 'eng', name: 'English' },\n { iso: 'spa', name: 'Spanish' },\n { iso: 'fra', name: 'French' },\n { iso: 'por', name: 'Portuguese' },\n { iso: 'deu', name: 'German' }\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 waitForNetwork: boolean = false\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.2;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold,\n waitForNetwork\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 // add some padding\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 // Increased wait time to handle slower CI environments\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 // Increased max attempts to handle slower CI environments\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"]}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/Icons.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-duplicate-enum-values */
|
|
2
2
|
// for cache busting we dynamically generate a fingerprint, use yarn svg to update
|
|
3
|
-
export const SVG_FINGERPRINT = '
|
|
3
|
+
export const SVG_FINGERPRINT = '129c04a9f99f9f4e99c436a68bc95470';
|
|
4
4
|
|
|
5
5
|
// only icons below are included in the sprite sheet
|
|
6
6
|
export enum Icon {
|
|
@@ -76,6 +76,7 @@ export enum Icon {
|
|
|
76
76
|
flow_surveyor = 'tablet-01',
|
|
77
77
|
flow_user = 'hard-drive',
|
|
78
78
|
flows = 'flow',
|
|
79
|
+
follow = 'route',
|
|
79
80
|
global = 'at-sign',
|
|
80
81
|
grid = 'dots-grid',
|
|
81
82
|
group = 'users-01',
|
|
@@ -64,7 +64,7 @@ export class FloatingTab extends RapidElement {
|
|
|
64
64
|
`;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
static TAB_HEIGHT =
|
|
67
|
+
static TAB_HEIGHT = 50; // height of tab for auto-stacking
|
|
68
68
|
static allTabs: FloatingTab[] = [];
|
|
69
69
|
|
|
70
70
|
@property({ type: String })
|
|
@@ -99,18 +99,13 @@ export class FloatingTab extends RapidElement {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
private updatePosition() {
|
|
102
|
-
// if top is manually set, use it
|
|
103
|
-
if (this.top !== -1) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
102
|
// auto-calculate position based on index
|
|
108
103
|
const index = FloatingTab.allTabs.indexOf(this);
|
|
109
104
|
if (index === -1) {
|
|
110
105
|
this.top = 100; // default fallback
|
|
111
106
|
} else {
|
|
112
107
|
// start at 100px and stack with 10px gap between tabs
|
|
113
|
-
this.top = 100 + index * (FloatingTab.TAB_HEIGHT +
|
|
108
|
+
this.top = 100 + index * (FloatingTab.TAB_HEIGHT + 0);
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
|
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -43,6 +43,9 @@ export class CanvasNode extends RapidElement {
|
|
|
43
43
|
)
|
|
44
44
|
private includeCategoriesInTranslation!: boolean;
|
|
45
45
|
|
|
46
|
+
@fromStore(zustand, (state: AppState) => state.getCurrentActivity())
|
|
47
|
+
private activity!: any;
|
|
48
|
+
|
|
46
49
|
// Track exits that are in "removing" state
|
|
47
50
|
private exitRemovalTimeouts: Map<string, number> = new Map();
|
|
48
51
|
|
|
@@ -95,6 +98,22 @@ export class CanvasNode extends RapidElement {
|
|
|
95
98
|
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
/* Flow start indicator */
|
|
102
|
+
temba-flow-node.flow-start .node::before {
|
|
103
|
+
content: 'FLOW START';
|
|
104
|
+
position: absolute;
|
|
105
|
+
top: -16px;
|
|
106
|
+
left: 50%;
|
|
107
|
+
transform: translateX(-50%);
|
|
108
|
+
font-size: 10px;
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
letter-spacing: 0.5px;
|
|
111
|
+
color: var(--color-primary-dark, #3b82f6);
|
|
112
|
+
opacity: 0.7;
|
|
113
|
+
z-index: 10;
|
|
114
|
+
white-space: nowrap;
|
|
115
|
+
}
|
|
116
|
+
|
|
98
117
|
/* Cap width for execute_actions nodes */
|
|
99
118
|
.node.execute-actions {
|
|
100
119
|
max-width: 200px;
|
|
@@ -280,11 +299,12 @@ export class CanvasNode extends RapidElement {
|
|
|
280
299
|
.categories {
|
|
281
300
|
display: flex;
|
|
282
301
|
flex-direction: row;
|
|
302
|
+
border-collapse: collapse;
|
|
283
303
|
|
|
284
304
|
}
|
|
285
305
|
|
|
286
306
|
.category {
|
|
287
|
-
|
|
307
|
+
border-collapse: collapse;
|
|
288
308
|
border: 1px solid #f3f3f3;
|
|
289
309
|
padding: 0.75em;
|
|
290
310
|
flex-grow:1;
|
|
@@ -1572,6 +1592,10 @@ export class CanvasNode extends RapidElement {
|
|
|
1572
1592
|
supportsLocalization &&
|
|
1573
1593
|
!this.includeCategoriesInTranslation;
|
|
1574
1594
|
|
|
1595
|
+
// Get active contact count for this node
|
|
1596
|
+
const activeCount =
|
|
1597
|
+
(this.activity?.nodes && this.activity.nodes[this.node.uuid]) || 0;
|
|
1598
|
+
|
|
1575
1599
|
return html`
|
|
1576
1600
|
<div
|
|
1577
1601
|
id="${this.node.uuid}"
|
|
@@ -1582,6 +1606,11 @@ export class CanvasNode extends RapidElement {
|
|
|
1582
1606
|
})}
|
|
1583
1607
|
style="left:${this.ui.position.left}px;top:${this.ui.position.top}px"
|
|
1584
1608
|
>
|
|
1609
|
+
${activeCount > 0
|
|
1610
|
+
? html`<div class="active-count">
|
|
1611
|
+
${activeCount.toLocaleString()}
|
|
1612
|
+
</div>`
|
|
1613
|
+
: ''}
|
|
1585
1614
|
${nodeConfig && nodeConfig.type !== 'execute_actions'
|
|
1586
1615
|
? html`<div class="router" style="position: relative;">
|
|
1587
1616
|
<div
|