@nyaruka/temba-components 0.137.0 → 0.138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/temba-components.js +392 -258
  3. package/dist/temba-components.js.map +1 -1
  4. package/out-tsc/src/display/FloatingTab.js +2 -2
  5. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  6. package/out-tsc/src/flow/CanvasNode.js +45 -24
  7. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  8. package/out-tsc/src/flow/Editor.js +305 -16
  9. package/out-tsc/src/flow/Editor.js.map +1 -1
  10. package/out-tsc/src/flow/Plumber.js +110 -64
  11. package/out-tsc/src/flow/Plumber.js.map +1 -1
  12. package/out-tsc/src/simulator/Simulator.js +11 -4
  13. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  14. package/out-tsc/src/store/AppState.js +12 -2
  15. package/out-tsc/src/store/AppState.js.map +1 -1
  16. package/out-tsc/test/temba-flow-editor-node.test.js +2 -1
  17. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  18. package/out-tsc/test/temba-flow-editor-revisions.test.js +106 -0
  19. package/out-tsc/test/temba-flow-editor-revisions.test.js.map +1 -0
  20. package/out-tsc/test/temba-flow-editor.test.js +14 -10
  21. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  22. package/out-tsc/test/temba-flow-plumber-connections.test.js +7 -1
  23. package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
  24. package/out-tsc/test/temba-flow-plumber.test.js +6 -0
  25. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/display/FloatingTab.ts +2 -2
  28. package/src/flow/CanvasNode.ts +54 -29
  29. package/src/flow/Editor.ts +357 -17
  30. package/src/flow/Plumber.ts +123 -69
  31. package/src/simulator/Simulator.ts +11 -5
  32. package/src/store/AppState.ts +13 -2
  33. package/test/temba-flow-editor-node.test.ts +2 -1
  34. package/test/temba-flow-editor-revisions.test.ts +134 -0
  35. package/test/temba-flow-editor.test.ts +16 -10
  36. package/test/temba-flow-plumber-connections.test.ts +7 -1
  37. package/test/temba-flow-plumber.test.ts +6 -0
@@ -542,11 +542,13 @@ describe('Editor', () => {
542
542
  </temba-flow-editor>
543
543
  `);
544
544
  await editor.updateComplete;
545
- // node-2 should be first (top: 100 < top: 200)
546
- const flowNodes = editor.querySelectorAll('temba-flow-node');
547
- expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');
548
- expect(flowNodes[0].classList.contains('flow-start')).to.be.true;
549
- expect(flowNodes[1].classList.contains('flow-start')).to.be.false;
545
+ // node-2 is at top (top: 100 < top: 200) so it should be flow-start
546
+ const node1 = editor.querySelector('temba-flow-node[uuid="node-1"]');
547
+ const node2 = editor.querySelector('temba-flow-node[uuid="node-2"]');
548
+ expect(node2).to.exist;
549
+ expect(node1).to.exist;
550
+ expect(node2.classList.contains('flow-start')).to.be.true;
551
+ expect(node1.classList.contains('flow-start')).to.be.false;
550
552
  // move node-1 to the top
551
553
  zustand.getState().updateCanvasPositions({
552
554
  'node-1': { left: 100, top: 50 }
@@ -600,7 +602,7 @@ describe('Editor', () => {
600
602
  </temba-flow-editor>
601
603
  `);
602
604
  await editor.updateComplete;
603
- let flowNodes = editor.querySelectorAll('temba-flow-node');
605
+ const flowNodes = editor.querySelectorAll('temba-flow-node');
604
606
  expect(flowNodes[0].classList.contains('flow-start')).to.be.true;
605
607
  // add a new node at the top
606
608
  const newNode = {
@@ -617,10 +619,12 @@ describe('Editor', () => {
617
619
  zustand.getState().addNode(newNode, newNodeUI);
618
620
  await editor.updateComplete;
619
621
  // new node should now be the flow-start
620
- flowNodes = editor.querySelectorAll('temba-flow-node');
621
- expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');
622
- expect(flowNodes[0].classList.contains('flow-start')).to.be.true;
623
- expect(flowNodes[1].classList.contains('flow-start')).to.be.false;
622
+ const node1 = editor.querySelector('temba-flow-node[uuid="node-1"]');
623
+ const node2 = editor.querySelector('temba-flow-node[uuid="node-2"]');
624
+ expect(node2).to.exist;
625
+ expect(node1).to.exist;
626
+ expect(node2.classList.contains('flow-start')).to.be.true;
627
+ expect(node1.classList.contains('flow-start')).to.be.false;
624
628
  });
625
629
  it('should handle flow-start when first node is removed', async () => {
626
630
  const { zustand } = await import('../src/store/AppState');
@@ -1 +1 @@
1
- {"version":3,"file":"temba-flow-editor.test.js","sourceRoot":"","sources":["../../test/temba-flow-editor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, fixture, expect } from '@open-wc/testing';\nimport { Editor } from '../src/flow/Editor';\nimport { Plumber } from '../src/flow/Plumber';\nimport { stub, restore } from 'sinon';\n\n// Register the component\ncustomElements.define('temba-flow-editor', Editor);\n\ndescribe('Editor', () => {\n let editor: Editor;\n\n beforeEach(() => {\n // Reset any stubs\n restore();\n });\n\n afterEach(() => {\n restore();\n });\n\n describe('basic functionality', () => {\n it('creates render root as element itself', () => {\n const editor = new Editor();\n expect(editor.createRenderRoot()).to.equal(editor);\n });\n\n it('has correct CSS styles defined', () => {\n const styles = Editor.styles;\n expect(styles).to.exist;\n expect(styles.cssText).to.contain('#editor');\n expect(styles.cssText).to.contain('#grid');\n expect(styles.cssText).to.contain('#canvas');\n expect(styles.cssText).to.contain('.plumb-source');\n expect(styles.cssText).to.contain('.plumb-target');\n expect(styles.cssText).to.contain('.plumb-connector');\n });\n\n it('creates with default properties', () => {\n editor = new Editor();\n expect(editor.flow).to.be.undefined;\n expect(editor.version).to.be.undefined;\n });\n\n it('accepts flow and version properties without getStore call', async () => {\n editor = document.createElement('temba-flow-editor') as Editor;\n editor.flow = 'test-flow-uuid';\n editor.version = '1.0';\n\n expect(editor.flow).to.equal('test-flow-uuid');\n expect(editor.version).to.equal('1.0');\n });\n });\n\n describe('lifecycle methods', () => {\n it('calls firstUpdated and initializes plumber', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Verify that plumber is initialized\n expect((editor as any).plumber).to.be.instanceOf(Plumber);\n });\n\n it('verifies firstUpdated method exists and can be called', () => {\n editor = new Editor();\n\n // Mock canvas element\n const mockCanvas = document.createElement('div');\n mockCanvas.id = 'canvas';\n\n // Mock querySelector to return our mock canvas\n stub(editor, 'querySelector').returns(mockCanvas);\n\n // Verify firstUpdated method exists\n expect(typeof (editor as any).firstUpdated).to.equal('function');\n\n // Test that calling firstUpdated doesn't throw (without getStore)\n expect(() => {\n // Only test the plumber initialization part\n (editor as any).plumber = new Plumber(mockCanvas, editor);\n }).to.not.throw();\n });\n\n it('handles updated with canvasSize changes', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Simulate canvasSize change\n (editor as any).canvasSize = { width: 800, height: 600 };\n const changes = new Map();\n changes.set('canvasSize', true);\n\n (editor as any).updated(changes);\n\n // Verify the canvasSize was set correctly\n expect((editor as any).canvasSize).to.deep.equal({\n width: 800,\n height: 600\n });\n });\n\n it('handles updated without canvasSize changes', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n const consoleStub = stub(console, 'log');\n\n const changes = new Map();\n changes.set('other', true);\n\n (editor as any).updated(changes);\n\n expect(consoleStub).to.not.have.been.called;\n\n consoleStub.restore();\n });\n });\n\n describe('render method', () => {\n it('renders loading when no definition', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set canvas size to avoid undefined errors\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const loadingElement = editor.querySelector('temba-loading');\n expect(loadingElement).to.exist;\n });\n\n it('renders nodes when definition exists', async () => {\n const mockDefinition = {\n nodes: [\n {\n uuid: 'node-1',\n actions: [],\n exits: []\n },\n {\n uuid: 'node-2',\n actions: [],\n exits: []\n }\n ],\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 } },\n 'node-2': { position: { left: 300, top: 400 } }\n }\n }\n };\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set properties\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes).to.have.length(2);\n });\n\n it('includes style elements in light DOM', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set canvas size\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const styleElements = editor.querySelectorAll('style');\n expect(styleElements.length).to.be.greaterThan(0);\n });\n\n it('renders with correct grid dimensions', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n (editor as any).canvasSize = { width: 1200, height: 800 };\n await editor.updateComplete;\n\n const gridElement = editor.querySelector('#grid');\n expect(gridElement).to.exist;\n\n const style = gridElement?.getAttribute('style');\n expect(style).to.contain('width:1200px');\n expect(style).to.contain('height:800px');\n });\n\n it('renders editor structure', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const editorElement = editor.querySelector('#editor');\n expect(editorElement).to.exist;\n\n const gridElement = editor.querySelector('#grid');\n expect(gridElement).to.exist;\n\n const canvasElement = editor.querySelector('#canvas');\n expect(canvasElement).to.exist;\n });\n });\n\n describe('property handling', () => {\n it('handles flow property change', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Change flow property\n editor.flow = 'new-flow-uuid';\n await editor.updateComplete;\n\n expect(editor.flow).to.equal('new-flow-uuid');\n });\n\n it('handles version property change', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n editor.version = '2.0';\n await editor.updateComplete;\n\n expect(editor.version).to.equal('2.0');\n });\n });\n\n describe('store integration', () => {\n it('has fromStore decorators for definition and canvasSize', () => {\n editor = new Editor();\n\n // Check that the properties exist (they are private but we can verify they exist)\n expect(editor).to.have.property('definition');\n expect(editor).to.have.property('canvasSize');\n });\n });\n\n describe('constructor behavior', () => {\n it('calls super in constructor', () => {\n // This mainly verifies the constructor doesn't throw\n expect(() => {\n new Editor();\n }).to.not.throw();\n });\n });\n\n describe('multi-selection functionality', () => {\n let mockDefinition: any;\n\n beforeEach(() => {\n mockDefinition = {\n nodes: [\n {\n uuid: 'node-1',\n actions: [],\n exits: []\n },\n {\n uuid: 'node-2',\n actions: [],\n exits: []\n }\n ],\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 } },\n 'node-2': { position: { left: 300, top: 400 } }\n },\n stickies: {\n 'sticky-1': {\n position: { left: 200, top: 100 },\n title: 'Test Sticky',\n body: 'Test content',\n color: 'yellow'\n }\n }\n }\n };\n });\n\n it('initializes with empty selection', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n expect((editor as any).selectedItems.size).to.equal(0);\n expect((editor as any).isSelecting).to.be.false;\n expect((editor as any).selectionBox).to.be.null;\n });\n\n it('adds visual selection styling to selected items', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up mock definition and selection\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n (editor as any).selectedItems = new Set(['node-1']);\n await editor.updateComplete;\n\n const selectedNode = editor.querySelector(\n 'temba-flow-node[uuid=\"node-1\"]'\n );\n expect(selectedNode).to.exist;\n expect(selectedNode.classList.contains('selected')).to.be.true;\n });\n\n it('renders selection box when selecting', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up selection state\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n (editor as any).isSelecting = true;\n (editor as any).selectionBox = {\n startX: 50,\n startY: 50,\n endX: 150,\n endY: 150\n };\n await editor.updateComplete;\n\n const selectionBox = editor.querySelector('.selection-box');\n expect(selectionBox).to.exist;\n\n const style = selectionBox.getAttribute('style');\n expect(style).to.contain('left: 50px');\n expect(style).to.contain('top: 50px');\n expect(style).to.contain('width: 100px');\n expect(style).to.contain('height: 100px');\n });\n\n it('handles escape key to clear selection', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up selection\n (editor as any).selectedItems.add('node-1');\n (editor as any).selectedItems.add('node-2');\n\n const mockEvent = new KeyboardEvent('keydown', { key: 'Escape' });\n (editor as any).handleKeyDown(mockEvent);\n\n expect((editor as any).selectedItems.size).to.equal(0);\n });\n });\n\n describe('canvas initialization', () => {\n it('initializes plumber with canvas element', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n const plumber = (editor as any).plumber;\n expect(plumber).to.be.instanceOf(Plumber);\n });\n\n it('handles missing canvas element gracefully', async () => {\n editor = await fixture(html`<temba-flow-editor></temba-flow-editor>`);\n\n // Should not throw even without canvas\n expect((editor as any).plumber).to.be.instanceOf(Plumber);\n });\n });\n\n describe('canvas menu functionality', () => {\n afterEach(() => {\n restore();\n });\n\n it('has context menu handler set up', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"grid\">\n <div\n id=\"canvas\"\n style=\"position: relative; width: 800px; height: 600px;\"\n ></div>\n </div>\n </temba-flow-editor>\n `);\n\n // Set up required properties\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const canvas = editor.querySelector('#canvas') as HTMLElement;\n expect(canvas).to.exist;\n\n // Check that the context menu event listener is set up\n expect((editor as any).boundCanvasContextMenu).to.exist;\n expect(typeof (editor as any).boundCanvasContextMenu).to.equal(\n 'function'\n );\n\n // Test the snapToGrid functionality that would be used\n const snapToGrid = (value: number): number => {\n const snapped = Math.round(value / 20) * 20;\n return Math.max(snapped, 0);\n };\n\n // Test various snap positions\n expect(snapToGrid(245)).to.equal(240);\n expect(snapToGrid(255)).to.equal(260);\n expect(snapToGrid(150)).to.equal(160);\n expect(snapToGrid(-10)).to.equal(0); // Should not go negative\n });\n\n it('tests context menu handler logic independently', () => {\n // Test the logic that would be in handleCanvasContextMenu\n\n // Mock event with canvas target\n const canvasTarget = { id: 'canvas' };\n const validEvent = { target: canvasTarget };\n\n // Mock event with non-canvas target\n const nonCanvasTarget = { id: 'other-element' };\n const invalidEvent = { target: nonCanvasTarget };\n\n // Test the early return condition\n const shouldReturnEarly = (event: any) => {\n const target = event.target as HTMLElement;\n return target.id !== 'canvas';\n };\n\n expect(shouldReturnEarly(validEvent)).to.be.false;\n expect(shouldReturnEarly(invalidEvent)).to.be.true;\n });\n\n it('tests position calculation logic', () => {\n // Mock canvas getBoundingClientRect\n const mockCanvas = {\n getBoundingClientRect: () => ({\n left: 50,\n top: 100,\n right: 850,\n bottom: 700,\n width: 800,\n height: 600\n })\n };\n\n // Mock event\n const mockEvent = {\n clientX: 300,\n clientY: 250\n };\n\n // Calculate relative position (this is what handleCanvasDoubleClick does)\n const canvasRect = mockCanvas.getBoundingClientRect();\n const relativeX = mockEvent.clientX - canvasRect.left; // 300 - 50 = 250\n const relativeY = mockEvent.clientY - canvasRect.top; // 250 - 100 = 150\n\n // Apply snap to grid\n const snapToGrid = (value: number) =>\n Math.max(Math.round(value / 20) * 20, 0);\n const snappedLeft = snapToGrid(relativeX); // 250 -> 260\n const snappedTop = snapToGrid(relativeY); // 150 -> 160\n\n // Verify calculations\n expect(relativeX).to.equal(250);\n expect(relativeY).to.equal(150);\n expect(snappedLeft).to.equal(260);\n expect(snappedTop).to.equal(160);\n\n // This position would be passed to createStickyNote\n const expectedPosition = {\n left: snappedLeft,\n top: snappedTop\n };\n\n expect(expectedPosition).to.deep.equal({ left: 260, top: 160 });\n });\n });\n\n describe('flow-start indicator', () => {\n it('should mark the first node as flow-start', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create a flow definition with multiple nodes\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n },\n {\n uuid: 'node-3',\n actions: [\n { type: 'send_msg', uuid: 'action-3', text: 'Message 3' }\n ],\n exits: [{ uuid: 'exit-3', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 100 }, type: 'send_msg' },\n 'node-2': { position: { left: 200, top: 200 }, type: 'send_msg' },\n 'node-3': { position: { left: 300, top: 300 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 3, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n // get all flow nodes\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes.length).to.equal(3);\n\n // first node should have flow-start class\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // other nodes should not have flow-start class\n expect(flowNodes[1].classList.contains('flow-start')).to.be.false;\n expect(flowNodes[2].classList.contains('flow-start')).to.be.false;\n });\n\n it('should update flow-start when node positions change', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create a flow with nodes in a specific order\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 }, type: 'send_msg' },\n 'node-2': { position: { left: 100, top: 100 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 2, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n // node-2 should be first (top: 100 < top: 200)\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n expect(flowNodes[1].classList.contains('flow-start')).to.be.false;\n\n // move node-1 to the top\n zustand.getState().updateCanvasPositions({\n 'node-1': { left: 100, top: 50 }\n });\n\n await editor.updateComplete;\n\n // now node-1 should be first\n const updatedFlowNodes = editor.querySelectorAll('temba-flow-node');\n expect(updatedFlowNodes[0].getAttribute('uuid')).to.equal('node-1');\n expect(updatedFlowNodes[0].classList.contains('flow-start')).to.be.true;\n expect(updatedFlowNodes[1].classList.contains('flow-start')).to.be.false;\n });\n\n it('should maintain flow-start when nodes are added', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // start with one node\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 1, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n let flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // add a new node at the top\n const newNode = {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg' as const, uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n };\n const newNodeUI = {\n position: { left: 100, top: 100 },\n type: 'send_msg' as const\n };\n\n zustand.getState().addNode(newNode, newNodeUI);\n\n await editor.updateComplete;\n\n // new node should now be the flow-start\n flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n expect(flowNodes[1].classList.contains('flow-start')).to.be.false;\n });\n\n it('should handle flow-start when first node is removed', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create flow with multiple nodes\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 100 }, type: 'send_msg' },\n 'node-2': { position: { left: 100, top: 200 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 2, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n let flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-1');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // remove the first node\n zustand.getState().removeNodes(['node-1']);\n\n await editor.updateComplete;\n\n // node-2 should now be the flow-start\n flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes.length).to.equal(1);\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n });\n });\n});\n"]}
1
+ {"version":3,"file":"temba-flow-editor.test.js","sourceRoot":"","sources":["../../test/temba-flow-editor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, fixture, expect } from '@open-wc/testing';\nimport { Editor } from '../src/flow/Editor';\nimport { Plumber } from '../src/flow/Plumber';\nimport { stub, restore } from 'sinon';\n\n// Register the component\ncustomElements.define('temba-flow-editor', Editor);\n\ndescribe('Editor', () => {\n let editor: Editor;\n\n beforeEach(() => {\n // Reset any stubs\n restore();\n });\n\n afterEach(() => {\n restore();\n });\n\n describe('basic functionality', () => {\n it('creates render root as element itself', () => {\n const editor = new Editor();\n expect(editor.createRenderRoot()).to.equal(editor);\n });\n\n it('has correct CSS styles defined', () => {\n const styles = Editor.styles;\n expect(styles).to.exist;\n expect(styles.cssText).to.contain('#editor');\n expect(styles.cssText).to.contain('#grid');\n expect(styles.cssText).to.contain('#canvas');\n expect(styles.cssText).to.contain('.plumb-source');\n expect(styles.cssText).to.contain('.plumb-target');\n expect(styles.cssText).to.contain('.plumb-connector');\n });\n\n it('creates with default properties', () => {\n editor = new Editor();\n expect(editor.flow).to.be.undefined;\n expect(editor.version).to.be.undefined;\n });\n\n it('accepts flow and version properties without getStore call', async () => {\n editor = document.createElement('temba-flow-editor') as Editor;\n editor.flow = 'test-flow-uuid';\n editor.version = '1.0';\n\n expect(editor.flow).to.equal('test-flow-uuid');\n expect(editor.version).to.equal('1.0');\n });\n });\n\n describe('lifecycle methods', () => {\n it('calls firstUpdated and initializes plumber', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Verify that plumber is initialized\n expect((editor as any).plumber).to.be.instanceOf(Plumber);\n });\n\n it('verifies firstUpdated method exists and can be called', () => {\n editor = new Editor();\n\n // Mock canvas element\n const mockCanvas = document.createElement('div');\n mockCanvas.id = 'canvas';\n\n // Mock querySelector to return our mock canvas\n stub(editor, 'querySelector').returns(mockCanvas);\n\n // Verify firstUpdated method exists\n expect(typeof (editor as any).firstUpdated).to.equal('function');\n\n // Test that calling firstUpdated doesn't throw (without getStore)\n expect(() => {\n // Only test the plumber initialization part\n (editor as any).plumber = new Plumber(mockCanvas, editor);\n }).to.not.throw();\n });\n\n it('handles updated with canvasSize changes', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Simulate canvasSize change\n (editor as any).canvasSize = { width: 800, height: 600 };\n const changes = new Map();\n changes.set('canvasSize', true);\n\n (editor as any).updated(changes);\n\n // Verify the canvasSize was set correctly\n expect((editor as any).canvasSize).to.deep.equal({\n width: 800,\n height: 600\n });\n });\n\n it('handles updated without canvasSize changes', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n const consoleStub = stub(console, 'log');\n\n const changes = new Map();\n changes.set('other', true);\n\n (editor as any).updated(changes);\n\n expect(consoleStub).to.not.have.been.called;\n\n consoleStub.restore();\n });\n });\n\n describe('render method', () => {\n it('renders loading when no definition', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set canvas size to avoid undefined errors\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const loadingElement = editor.querySelector('temba-loading');\n expect(loadingElement).to.exist;\n });\n\n it('renders nodes when definition exists', async () => {\n const mockDefinition = {\n nodes: [\n {\n uuid: 'node-1',\n actions: [],\n exits: []\n },\n {\n uuid: 'node-2',\n actions: [],\n exits: []\n }\n ],\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 } },\n 'node-2': { position: { left: 300, top: 400 } }\n }\n }\n };\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set properties\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes).to.have.length(2);\n });\n\n it('includes style elements in light DOM', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set canvas size\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const styleElements = editor.querySelectorAll('style');\n expect(styleElements.length).to.be.greaterThan(0);\n });\n\n it('renders with correct grid dimensions', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n (editor as any).canvasSize = { width: 1200, height: 800 };\n await editor.updateComplete;\n\n const gridElement = editor.querySelector('#grid');\n expect(gridElement).to.exist;\n\n const style = gridElement?.getAttribute('style');\n expect(style).to.contain('width:1200px');\n expect(style).to.contain('height:800px');\n });\n\n it('renders editor structure', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const editorElement = editor.querySelector('#editor');\n expect(editorElement).to.exist;\n\n const gridElement = editor.querySelector('#grid');\n expect(gridElement).to.exist;\n\n const canvasElement = editor.querySelector('#canvas');\n expect(canvasElement).to.exist;\n });\n });\n\n describe('property handling', () => {\n it('handles flow property change', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Change flow property\n editor.flow = 'new-flow-uuid';\n await editor.updateComplete;\n\n expect(editor.flow).to.equal('new-flow-uuid');\n });\n\n it('handles version property change', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n editor.version = '2.0';\n await editor.updateComplete;\n\n expect(editor.version).to.equal('2.0');\n });\n });\n\n describe('store integration', () => {\n it('has fromStore decorators for definition and canvasSize', () => {\n editor = new Editor();\n\n // Check that the properties exist (they are private but we can verify they exist)\n expect(editor).to.have.property('definition');\n expect(editor).to.have.property('canvasSize');\n });\n });\n\n describe('constructor behavior', () => {\n it('calls super in constructor', () => {\n // This mainly verifies the constructor doesn't throw\n expect(() => {\n new Editor();\n }).to.not.throw();\n });\n });\n\n describe('multi-selection functionality', () => {\n let mockDefinition: any;\n\n beforeEach(() => {\n mockDefinition = {\n nodes: [\n {\n uuid: 'node-1',\n actions: [],\n exits: []\n },\n {\n uuid: 'node-2',\n actions: [],\n exits: []\n }\n ],\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 } },\n 'node-2': { position: { left: 300, top: 400 } }\n },\n stickies: {\n 'sticky-1': {\n position: { left: 200, top: 100 },\n title: 'Test Sticky',\n body: 'Test content',\n color: 'yellow'\n }\n }\n }\n };\n });\n\n it('initializes with empty selection', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n expect((editor as any).selectedItems.size).to.equal(0);\n expect((editor as any).isSelecting).to.be.false;\n expect((editor as any).selectionBox).to.be.null;\n });\n\n it('adds visual selection styling to selected items', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up mock definition and selection\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n (editor as any).selectedItems = new Set(['node-1']);\n await editor.updateComplete;\n\n const selectedNode = editor.querySelector(\n 'temba-flow-node[uuid=\"node-1\"]'\n );\n expect(selectedNode).to.exist;\n expect(selectedNode.classList.contains('selected')).to.be.true;\n });\n\n it('renders selection box when selecting', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up selection state\n (editor as any).definition = mockDefinition;\n (editor as any).canvasSize = { width: 800, height: 600 };\n (editor as any).isSelecting = true;\n (editor as any).selectionBox = {\n startX: 50,\n startY: 50,\n endX: 150,\n endY: 150\n };\n await editor.updateComplete;\n\n const selectionBox = editor.querySelector('.selection-box');\n expect(selectionBox).to.exist;\n\n const style = selectionBox.getAttribute('style');\n expect(style).to.contain('left: 50px');\n expect(style).to.contain('top: 50px');\n expect(style).to.contain('width: 100px');\n expect(style).to.contain('height: 100px');\n });\n\n it('handles escape key to clear selection', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n // Set up selection\n (editor as any).selectedItems.add('node-1');\n (editor as any).selectedItems.add('node-2');\n\n const mockEvent = new KeyboardEvent('keydown', { key: 'Escape' });\n (editor as any).handleKeyDown(mockEvent);\n\n expect((editor as any).selectedItems.size).to.equal(0);\n });\n });\n\n describe('canvas initialization', () => {\n it('initializes plumber with canvas element', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n const plumber = (editor as any).plumber;\n expect(plumber).to.be.instanceOf(Plumber);\n });\n\n it('handles missing canvas element gracefully', async () => {\n editor = await fixture(html`<temba-flow-editor></temba-flow-editor>`);\n\n // Should not throw even without canvas\n expect((editor as any).plumber).to.be.instanceOf(Plumber);\n });\n });\n\n describe('canvas menu functionality', () => {\n afterEach(() => {\n restore();\n });\n\n it('has context menu handler set up', async () => {\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"grid\">\n <div\n id=\"canvas\"\n style=\"position: relative; width: 800px; height: 600px;\"\n ></div>\n </div>\n </temba-flow-editor>\n `);\n\n // Set up required properties\n (editor as any).canvasSize = { width: 800, height: 600 };\n await editor.updateComplete;\n\n const canvas = editor.querySelector('#canvas') as HTMLElement;\n expect(canvas).to.exist;\n\n // Check that the context menu event listener is set up\n expect((editor as any).boundCanvasContextMenu).to.exist;\n expect(typeof (editor as any).boundCanvasContextMenu).to.equal(\n 'function'\n );\n\n // Test the snapToGrid functionality that would be used\n const snapToGrid = (value: number): number => {\n const snapped = Math.round(value / 20) * 20;\n return Math.max(snapped, 0);\n };\n\n // Test various snap positions\n expect(snapToGrid(245)).to.equal(240);\n expect(snapToGrid(255)).to.equal(260);\n expect(snapToGrid(150)).to.equal(160);\n expect(snapToGrid(-10)).to.equal(0); // Should not go negative\n });\n\n it('tests context menu handler logic independently', () => {\n // Test the logic that would be in handleCanvasContextMenu\n\n // Mock event with canvas target\n const canvasTarget = { id: 'canvas' };\n const validEvent = { target: canvasTarget };\n\n // Mock event with non-canvas target\n const nonCanvasTarget = { id: 'other-element' };\n const invalidEvent = { target: nonCanvasTarget };\n\n // Test the early return condition\n const shouldReturnEarly = (event: any) => {\n const target = event.target as HTMLElement;\n return target.id !== 'canvas';\n };\n\n expect(shouldReturnEarly(validEvent)).to.be.false;\n expect(shouldReturnEarly(invalidEvent)).to.be.true;\n });\n\n it('tests position calculation logic', () => {\n // Mock canvas getBoundingClientRect\n const mockCanvas = {\n getBoundingClientRect: () => ({\n left: 50,\n top: 100,\n right: 850,\n bottom: 700,\n width: 800,\n height: 600\n })\n };\n\n // Mock event\n const mockEvent = {\n clientX: 300,\n clientY: 250\n };\n\n // Calculate relative position (this is what handleCanvasDoubleClick does)\n const canvasRect = mockCanvas.getBoundingClientRect();\n const relativeX = mockEvent.clientX - canvasRect.left; // 300 - 50 = 250\n const relativeY = mockEvent.clientY - canvasRect.top; // 250 - 100 = 150\n\n // Apply snap to grid\n const snapToGrid = (value: number) =>\n Math.max(Math.round(value / 20) * 20, 0);\n const snappedLeft = snapToGrid(relativeX); // 250 -> 260\n const snappedTop = snapToGrid(relativeY); // 150 -> 160\n\n // Verify calculations\n expect(relativeX).to.equal(250);\n expect(relativeY).to.equal(150);\n expect(snappedLeft).to.equal(260);\n expect(snappedTop).to.equal(160);\n\n // This position would be passed to createStickyNote\n const expectedPosition = {\n left: snappedLeft,\n top: snappedTop\n };\n\n expect(expectedPosition).to.deep.equal({ left: 260, top: 160 });\n });\n });\n\n describe('flow-start indicator', () => {\n it('should mark the first node as flow-start', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create a flow definition with multiple nodes\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n },\n {\n uuid: 'node-3',\n actions: [\n { type: 'send_msg', uuid: 'action-3', text: 'Message 3' }\n ],\n exits: [{ uuid: 'exit-3', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 100 }, type: 'send_msg' },\n 'node-2': { position: { left: 200, top: 200 }, type: 'send_msg' },\n 'node-3': { position: { left: 300, top: 300 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 3, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n // get all flow nodes\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes.length).to.equal(3);\n\n // first node should have flow-start class\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // other nodes should not have flow-start class\n expect(flowNodes[1].classList.contains('flow-start')).to.be.false;\n expect(flowNodes[2].classList.contains('flow-start')).to.be.false;\n });\n\n it('should update flow-start when node positions change', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create a flow with nodes in a specific order\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 }, type: 'send_msg' },\n 'node-2': { position: { left: 100, top: 100 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 2, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n // node-2 is at top (top: 100 < top: 200) so it should be flow-start\n const node1 = editor.querySelector('temba-flow-node[uuid=\"node-1\"]');\n const node2 = editor.querySelector('temba-flow-node[uuid=\"node-2\"]');\n\n expect(node2).to.exist;\n expect(node1).to.exist;\n expect(node2.classList.contains('flow-start')).to.be.true;\n expect(node1.classList.contains('flow-start')).to.be.false;\n\n // move node-1 to the top\n zustand.getState().updateCanvasPositions({\n 'node-1': { left: 100, top: 50 }\n });\n\n await editor.updateComplete;\n\n // now node-1 should be first\n const updatedFlowNodes = editor.querySelectorAll('temba-flow-node');\n expect(updatedFlowNodes[0].getAttribute('uuid')).to.equal('node-1');\n expect(updatedFlowNodes[0].classList.contains('flow-start')).to.be.true;\n expect(updatedFlowNodes[1].classList.contains('flow-start')).to.be.false;\n });\n\n it('should maintain flow-start when nodes are added', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // start with one node\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 200 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 1, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n const flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // add a new node at the top\n const newNode = {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg' as const, uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n };\n const newNodeUI = {\n position: { left: 100, top: 100 },\n type: 'send_msg' as const\n };\n\n zustand.getState().addNode(newNode, newNodeUI);\n\n await editor.updateComplete;\n\n // new node should now be the flow-start\n const node1 = editor.querySelector('temba-flow-node[uuid=\"node-1\"]');\n const node2 = editor.querySelector('temba-flow-node[uuid=\"node-2\"]');\n\n expect(node2).to.exist;\n expect(node1).to.exist;\n expect(node2.classList.contains('flow-start')).to.be.true;\n expect(node1.classList.contains('flow-start')).to.be.false;\n });\n\n it('should handle flow-start when first node is removed', async () => {\n const { zustand } = await import('../src/store/AppState');\n\n // create flow with multiple nodes\n const mockFlowDefinition = {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [\n {\n uuid: 'node-1',\n actions: [\n { type: 'send_msg', uuid: 'action-1', text: 'Message 1' }\n ],\n exits: [{ uuid: 'exit-1', destination_uuid: null }]\n },\n {\n uuid: 'node-2',\n actions: [\n { type: 'send_msg', uuid: 'action-2', text: 'Message 2' }\n ],\n exits: [{ uuid: 'exit-2', destination_uuid: null }]\n }\n ],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {\n 'node-1': { position: { left: 100, top: 100 }, type: 'send_msg' },\n 'node-2': { position: { left: 100, top: 200 }, type: 'send_msg' }\n },\n languages: []\n }\n };\n\n zustand.getState().setFlowContents({\n definition: mockFlowDefinition as any,\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 2, languages: 1 },\n locals: []\n }\n });\n\n editor = await fixture(html`\n <temba-flow-editor>\n <div id=\"canvas\"></div>\n </temba-flow-editor>\n `);\n\n await editor.updateComplete;\n\n let flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-1');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n\n // remove the first node\n zustand.getState().removeNodes(['node-1']);\n\n await editor.updateComplete;\n\n // node-2 should now be the flow-start\n flowNodes = editor.querySelectorAll('temba-flow-node');\n expect(flowNodes.length).to.equal(1);\n expect(flowNodes[0].getAttribute('uuid')).to.equal('node-2');\n expect(flowNodes[0].classList.contains('flow-start')).to.be.true;\n });\n });\n});\n"]}
@@ -23,7 +23,14 @@ describe('Plumber - Connection Management', () => {
23
23
  removeClass: stub(),
24
24
  batch: stub().callsFake((fn) => fn()),
25
25
  addEndpoint: stub().returns({}),
26
+ revalidate: stub(),
26
27
  connect: stub(),
28
+ getEndpoints: stub().returns([
29
+ { elementId: 'test-from', addClass: stub() }
30
+ ]),
31
+ select: stub().returns({
32
+ deleteAll: stub()
33
+ }),
27
34
  selectEndpoints: stub().returns({
28
35
  deleteAll: stub()
29
36
  }),
@@ -103,7 +110,6 @@ describe('Plumber - Connection Management', () => {
103
110
  expect(result).to.be.true;
104
111
  expect(plumber.jsPlumb.deleteConnection).to.have.been
105
112
  .calledTwice;
106
- expect(plumber.jsPlumb.removeAllEndpoints).to.have.been.called;
107
113
  });
108
114
  it('returns false when no connections exist', () => {
109
115
  plumber.jsPlumb.getConnections = stub().returns([]);
@@ -1 +1 @@
1
- {"version":3,"file":"temba-flow-plumber-connections.test.js","sourceRoot":"","sources":["../../test/temba-flow-plumber-connections.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { stub, useFakeTimers, SinonFakeTimers } from 'sinon';\nimport { Plumber } from '../src/flow/Plumber';\n\ndescribe('Plumber - Connection Management', () => {\n let plumber: Plumber;\n let mockCanvas: HTMLElement;\n let clock: SinonFakeTimers;\n\n beforeEach(() => {\n // Use fake timers to control setTimeout\n clock = useFakeTimers();\n\n // Create mock canvas and make getElementById return a mock element\n mockCanvas = document.createElement('div');\n const mockElement = document.createElement('div');\n stub(document, 'getElementById').returns(mockElement);\n\n // Create a mock editor with fireCustomEvent\n const mockEditor = { fireCustomEvent: stub() };\n\n // Create a new plumber instance\n plumber = new Plumber(mockCanvas, mockEditor);\n\n // Replace the internal jsPlumb instance with mocks\n (plumber as any).jsPlumb = {\n getConnections: stub().returns([]),\n addClass: stub(),\n removeClass: stub(),\n batch: stub().callsFake((fn: any) => fn()),\n addEndpoint: stub().returns({}),\n connect: stub(),\n selectEndpoints: stub().returns({\n deleteAll: stub()\n }),\n deleteConnection: stub(),\n removeAllEndpoints: stub(),\n repaintEverything: stub()\n };\n });\n\n afterEach(() => {\n // Restore the original document.getElementById\n (document.getElementById as any).restore?.();\n clock.restore();\n });\n\n describe('setConnectionRemovingState', () => {\n it('returns false when no connections are found', () => {\n const result = plumber.setConnectionRemovingState('test-exit', true);\n expect(result).to.be.false;\n expect((plumber as any).jsPlumb.getConnections).to.have.been.called;\n });\n\n it('sets removing class on connections when isRemoving is true', () => {\n const mockConnections = [\n { id: 'conn1', addClass: stub() },\n { id: 'conn2', addClass: stub() }\n ];\n\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.setConnectionRemovingState('test-exit', true);\n expect(result).to.be.true;\n expect(mockConnections[0].addClass).to.have.been.calledWith('removing');\n expect(mockConnections[1].addClass).to.have.been.calledWith('removing');\n });\n\n it('removes removing class from connections when isRemoving is false', () => {\n const mockConnections = [\n { id: 'conn1', removeClass: stub() },\n { id: 'conn2', removeClass: stub() }\n ];\n\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.setConnectionRemovingState('test-exit', false);\n expect(result).to.be.true;\n expect(mockConnections[0].removeClass).to.have.been.calledWith(\n 'removing'\n );\n expect(mockConnections[1].removeClass).to.have.been.calledWith(\n 'removing'\n );\n });\n });\n\n describe('connectIds and processPendingConnections', () => {\n it('adds connection to pending connections', () => {\n // Call connectIds which should add to pending connections\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Verify pendingConnections has the new connection\n expect((plumber as any).pendingConnections.length).to.equal(1);\n\n // Advance timer to trigger the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n // Now the batch should have been called\n expect((plumber as any).jsPlumb.batch).to.have.been.called;\n expect((plumber as any).jsPlumb.addEndpoint).to.have.been.called;\n expect((plumber as any).jsPlumb.connect).to.have.been.called;\n });\n\n it('clears previous timeout when called multiple times', () => {\n // Set up spies for window.setTimeout and window.clearTimeout instead of global\n const clearTimeoutSpy = stub(window, 'clearTimeout');\n const setTimeoutSpy = stub(window, 'setTimeout').returns(123 as any);\n\n // Call twice\n plumber.processPendingConnections();\n plumber.processPendingConnections();\n\n // Should have called clearTimeout once and setTimeout twice\n expect(clearTimeoutSpy).to.have.been.calledOnce;\n expect(setTimeoutSpy).to.have.been.calledTwice;\n\n // Clean up\n clearTimeoutSpy.restore();\n setTimeoutSpy.restore();\n });\n });\n\n describe('removeExitConnection', () => {\n it('removes connections for an exit', () => {\n const mockConnections = [{ id: 'conn1' }, { id: 'conn2' }];\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.removeExitConnection('test-exit');\n\n expect(result).to.be.true;\n expect((plumber as any).jsPlumb.deleteConnection).to.have.been\n .calledTwice;\n expect((plumber as any).jsPlumb.removeAllEndpoints).to.have.been.called;\n });\n\n it('returns false when no connections exist', () => {\n (plumber as any).jsPlumb.getConnections = stub().returns([]);\n\n const result = plumber.removeExitConnection('test-exit');\n\n expect(result).to.be.false;\n });\n });\n});\n"]}
1
+ {"version":3,"file":"temba-flow-plumber-connections.test.js","sourceRoot":"","sources":["../../test/temba-flow-plumber-connections.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { stub, useFakeTimers, SinonFakeTimers } from 'sinon';\nimport { Plumber } from '../src/flow/Plumber';\n\ndescribe('Plumber - Connection Management', () => {\n let plumber: Plumber;\n let mockCanvas: HTMLElement;\n let clock: SinonFakeTimers;\n\n beforeEach(() => {\n // Use fake timers to control setTimeout\n clock = useFakeTimers();\n\n // Create mock canvas and make getElementById return a mock element\n mockCanvas = document.createElement('div');\n const mockElement = document.createElement('div');\n stub(document, 'getElementById').returns(mockElement);\n\n // Create a mock editor with fireCustomEvent\n const mockEditor = { fireCustomEvent: stub() };\n\n // Create a new plumber instance\n plumber = new Plumber(mockCanvas, mockEditor);\n\n // Replace the internal jsPlumb instance with mocks\n (plumber as any).jsPlumb = {\n getConnections: stub().returns([]),\n addClass: stub(),\n removeClass: stub(),\n batch: stub().callsFake((fn: any) => fn()),\n addEndpoint: stub().returns({}),\n revalidate: stub(),\n connect: stub(),\n getEndpoints: stub().returns([\n { elementId: 'test-from', addClass: stub() }\n ]),\n select: stub().returns({\n deleteAll: stub()\n }),\n selectEndpoints: stub().returns({\n deleteAll: stub()\n }),\n deleteConnection: stub(),\n removeAllEndpoints: stub(),\n repaintEverything: stub()\n };\n });\n\n afterEach(() => {\n // Restore the original document.getElementById\n (document.getElementById as any).restore?.();\n clock.restore();\n });\n\n describe('setConnectionRemovingState', () => {\n it('returns false when no connections are found', () => {\n const result = plumber.setConnectionRemovingState('test-exit', true);\n expect(result).to.be.false;\n expect((plumber as any).jsPlumb.getConnections).to.have.been.called;\n });\n\n it('sets removing class on connections when isRemoving is true', () => {\n const mockConnections = [\n { id: 'conn1', addClass: stub() },\n { id: 'conn2', addClass: stub() }\n ];\n\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.setConnectionRemovingState('test-exit', true);\n expect(result).to.be.true;\n expect(mockConnections[0].addClass).to.have.been.calledWith('removing');\n expect(mockConnections[1].addClass).to.have.been.calledWith('removing');\n });\n\n it('removes removing class from connections when isRemoving is false', () => {\n const mockConnections = [\n { id: 'conn1', removeClass: stub() },\n { id: 'conn2', removeClass: stub() }\n ];\n\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.setConnectionRemovingState('test-exit', false);\n expect(result).to.be.true;\n expect(mockConnections[0].removeClass).to.have.been.calledWith(\n 'removing'\n );\n expect(mockConnections[1].removeClass).to.have.been.calledWith(\n 'removing'\n );\n });\n });\n\n describe('connectIds and processPendingConnections', () => {\n it('adds connection to pending connections', () => {\n // Call connectIds which should add to pending connections\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Verify pendingConnections has the new connection\n expect((plumber as any).pendingConnections.length).to.equal(1);\n\n // Advance timer to trigger the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n // Now the batch should have been called\n expect((plumber as any).jsPlumb.batch).to.have.been.called;\n expect((plumber as any).jsPlumb.addEndpoint).to.have.been.called;\n expect((plumber as any).jsPlumb.connect).to.have.been.called;\n });\n\n it('clears previous timeout when called multiple times', () => {\n // Set up spies for window.setTimeout and window.clearTimeout instead of global\n const clearTimeoutSpy = stub(window, 'clearTimeout');\n const setTimeoutSpy = stub(window, 'setTimeout').returns(123 as any);\n\n // Call twice\n plumber.processPendingConnections();\n plumber.processPendingConnections();\n\n // Should have called clearTimeout once and setTimeout twice\n expect(clearTimeoutSpy).to.have.been.calledOnce;\n expect(setTimeoutSpy).to.have.been.calledTwice;\n\n // Clean up\n clearTimeoutSpy.restore();\n setTimeoutSpy.restore();\n });\n });\n\n describe('removeExitConnection', () => {\n it('removes connections for an exit', () => {\n const mockConnections = [{ id: 'conn1' }, { id: 'conn2' }];\n (plumber as any).jsPlumb.getConnections = stub().returns(mockConnections);\n\n const result = plumber.removeExitConnection('test-exit');\n\n expect(result).to.be.true;\n expect((plumber as any).jsPlumb.deleteConnection).to.have.been\n .calledTwice;\n });\n\n it('returns false when no connections exist', () => {\n (plumber as any).jsPlumb.getConnections = stub().returns([]);\n\n const result = plumber.removeExitConnection('test-exit');\n\n expect(result).to.be.false;\n });\n });\n});\n"]}
@@ -25,6 +25,12 @@ describe('Plumber', () => {
25
25
  batch: stub().callsFake((fn) => fn()),
26
26
  addEndpoint: stub().returns({}),
27
27
  connect: stub(),
28
+ getEndpoints: stub().returns([
29
+ { elementId: 'test-from', addClass: stub() }
30
+ ]),
31
+ select: stub().returns({
32
+ deleteAll: stub()
33
+ }),
28
34
  selectEndpoints: stub().returns({
29
35
  deleteAll: stub()
30
36
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"temba-flow-plumber.test.js","sourceRoot":"","sources":["../../test/temba-flow-plumber.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { Plumber, SOURCE_DEFAULTS, TARGET_DEFAULTS } from '../src/flow/Plumber';\nimport { stub, useFakeTimers, SinonFakeTimers } from 'sinon';\n\ndescribe('Plumber', () => {\n let plumber: Plumber;\n let mockJsPlumb: any;\n let mockCanvas: HTMLElement;\n let clock: SinonFakeTimers;\n\n beforeEach(() => {\n // Use fake timers to control setTimeout\n clock = useFakeTimers();\n\n // Create mock canvas and make getElementById return a mock element\n mockCanvas = document.createElement('div');\n const mockElement = document.createElement('div');\n stub(document, 'getElementById').returns(mockElement);\n\n // Create a mock editor with fireCustomEvent\n const mockEditor = { fireCustomEvent: stub() };\n\n // Create a new plumber instance\n plumber = new Plumber(mockCanvas, mockEditor);\n\n // Replace the internal jsPlumb instance with mocks\n mockJsPlumb = {\n getConnections: stub().returns([]),\n addClass: stub(),\n removeClass: stub(),\n batch: stub().callsFake((fn) => fn()),\n addEndpoint: stub().returns({}),\n connect: stub(),\n selectEndpoints: stub().returns({\n deleteAll: stub()\n }),\n deleteConnection: stub(),\n removeAllEndpoints: stub(),\n repaintEverything: stub(),\n revalidate: stub(),\n bind: stub()\n };\n\n (plumber as any).jsPlumb = mockJsPlumb;\n // Reset the connectionWait to avoid timing issues\n (plumber as any).connectionWait = null;\n });\n\n afterEach(() => {\n // Restore the original document.getElementById\n (document.getElementById as any).restore?.();\n clock.restore();\n });\n\n describe('constructor', () => {\n it('creates a new plumber instance', () => {\n expect(plumber).to.be.instanceOf(Plumber);\n });\n });\n\n describe('makeTarget', () => {\n it('creates a target endpoint for the specified element', () => {\n plumber.makeTarget('test-target');\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n });\n });\n\n describe('makeSource', () => {\n it('creates a source endpoint for the specified element', () => {\n plumber.makeSource('test-source');\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n });\n });\n\n describe('connectIds', () => {\n it('adds connection to pending connections and processes them', () => {\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Verify pendingConnections has the new connection\n expect((plumber as any).pendingConnections.length).to.equal(1);\n\n // Advance timer to trigger the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n // Now the batch should have been called\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n });\n\n describe('processPendingConnections', () => {\n it('processes pending connections with timeout', () => {\n // Add a connection to pending connections\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n\n it('creates endpoints and connections for pending connections', () => {\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n expect(mockJsPlumb.connect).to.have.been.called;\n });\n\n it('clears existing timeout when called multiple times', () => {\n // Set up spies for window.setTimeout and window.clearTimeout\n const clearTimeoutSpy = stub(window, 'clearTimeout');\n const setTimeoutSpy = stub(window, 'setTimeout').returns(123 as any);\n\n // Call twice\n plumber.processPendingConnections();\n plumber.processPendingConnections();\n\n // Should have called clearTimeout once and setTimeout twice\n expect(clearTimeoutSpy).to.have.been.calledOnce;\n expect(setTimeoutSpy).to.have.been.calledTwice;\n\n // Clean up\n clearTimeoutSpy.restore();\n setTimeoutSpy.restore();\n });\n\n it('handles empty pending connections', () => {\n // Call without adding any connections\n plumber.processPendingConnections();\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n });\n\n describe('constants', () => {\n it('has correct properties in SOURCE_DEFAULTS', () => {\n expect(SOURCE_DEFAULTS).to.have.property('endpoint');\n expect(SOURCE_DEFAULTS).to.have.property('anchors');\n expect(SOURCE_DEFAULTS).to.have.property('maxConnections');\n expect(SOURCE_DEFAULTS).to.have.property('source');\n });\n\n it('has correct properties in TARGET_DEFAULTS', () => {\n expect(TARGET_DEFAULTS).to.have.property('endpoint');\n expect(TARGET_DEFAULTS).to.have.property('anchor');\n expect(TARGET_DEFAULTS).to.have.property('maxConnections');\n expect(TARGET_DEFAULTS).to.have.property('target');\n });\n });\n});\n"]}
1
+ {"version":3,"file":"temba-flow-plumber.test.js","sourceRoot":"","sources":["../../test/temba-flow-plumber.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { Plumber, SOURCE_DEFAULTS, TARGET_DEFAULTS } from '../src/flow/Plumber';\nimport { stub, useFakeTimers, SinonFakeTimers } from 'sinon';\n\ndescribe('Plumber', () => {\n let plumber: Plumber;\n let mockJsPlumb: any;\n let mockCanvas: HTMLElement;\n let clock: SinonFakeTimers;\n\n beforeEach(() => {\n // Use fake timers to control setTimeout\n clock = useFakeTimers();\n\n // Create mock canvas and make getElementById return a mock element\n mockCanvas = document.createElement('div');\n const mockElement = document.createElement('div');\n stub(document, 'getElementById').returns(mockElement);\n\n // Create a mock editor with fireCustomEvent\n const mockEditor = { fireCustomEvent: stub() };\n\n // Create a new plumber instance\n plumber = new Plumber(mockCanvas, mockEditor);\n\n // Replace the internal jsPlumb instance with mocks\n mockJsPlumb = {\n getConnections: stub().returns([]),\n addClass: stub(),\n removeClass: stub(),\n batch: stub().callsFake((fn) => fn()),\n addEndpoint: stub().returns({}),\n connect: stub(),\n getEndpoints: stub().returns([\n { elementId: 'test-from', addClass: stub() }\n ]),\n select: stub().returns({\n deleteAll: stub()\n }),\n selectEndpoints: stub().returns({\n deleteAll: stub()\n }),\n deleteConnection: stub(),\n removeAllEndpoints: stub(),\n repaintEverything: stub(),\n revalidate: stub(),\n bind: stub()\n };\n\n (plumber as any).jsPlumb = mockJsPlumb;\n // Reset the connectionWait to avoid timing issues\n (plumber as any).connectionWait = null;\n });\n\n afterEach(() => {\n // Restore the original document.getElementById\n (document.getElementById as any).restore?.();\n clock.restore();\n });\n\n describe('constructor', () => {\n it('creates a new plumber instance', () => {\n expect(plumber).to.be.instanceOf(Plumber);\n });\n });\n\n describe('makeTarget', () => {\n it('creates a target endpoint for the specified element', () => {\n plumber.makeTarget('test-target');\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n });\n });\n\n describe('makeSource', () => {\n it('creates a source endpoint for the specified element', () => {\n plumber.makeSource('test-source');\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n });\n });\n\n describe('connectIds', () => {\n it('adds connection to pending connections and processes them', () => {\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Verify pendingConnections has the new connection\n expect((plumber as any).pendingConnections.length).to.equal(1);\n\n // Advance timer to trigger the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n // Now the batch should have been called\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n });\n\n describe('processPendingConnections', () => {\n it('processes pending connections with timeout', () => {\n // Add a connection to pending connections\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n\n it('creates endpoints and connections for pending connections', () => {\n plumber.connectIds('test-node', 'test-from', 'test-to');\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.addEndpoint).to.have.been.called;\n expect(mockJsPlumb.connect).to.have.been.called;\n });\n\n it('clears existing timeout when called multiple times', () => {\n // Set up spies for window.setTimeout and window.clearTimeout\n const clearTimeoutSpy = stub(window, 'clearTimeout');\n const setTimeoutSpy = stub(window, 'setTimeout').returns(123 as any);\n\n // Call twice\n plumber.processPendingConnections();\n plumber.processPendingConnections();\n\n // Should have called clearTimeout once and setTimeout twice\n expect(clearTimeoutSpy).to.have.been.calledOnce;\n expect(setTimeoutSpy).to.have.been.calledTwice;\n\n // Clean up\n clearTimeoutSpy.restore();\n setTimeoutSpy.restore();\n });\n\n it('handles empty pending connections', () => {\n // Call without adding any connections\n plumber.processPendingConnections();\n\n // Fast-forward clock past the timeout\n clock.tick(51); // Just past the 50ms timeout\n\n expect(mockJsPlumb.batch).to.have.been.called;\n });\n });\n\n describe('constants', () => {\n it('has correct properties in SOURCE_DEFAULTS', () => {\n expect(SOURCE_DEFAULTS).to.have.property('endpoint');\n expect(SOURCE_DEFAULTS).to.have.property('anchors');\n expect(SOURCE_DEFAULTS).to.have.property('maxConnections');\n expect(SOURCE_DEFAULTS).to.have.property('source');\n });\n\n it('has correct properties in TARGET_DEFAULTS', () => {\n expect(TARGET_DEFAULTS).to.have.property('endpoint');\n expect(TARGET_DEFAULTS).to.have.property('anchor');\n expect(TARGET_DEFAULTS).to.have.property('maxConnections');\n expect(TARGET_DEFAULTS).to.have.property('target');\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.137.0",
3
+ "version": "0.138.0",
4
4
  "description": "Web components to support rapidpro and related projects",
5
5
  "author": "Nyaruka <code@nyaruka.coim>",
6
6
  "main": "dist/index.js",
@@ -102,10 +102,10 @@ export class FloatingTab extends RapidElement {
102
102
  // auto-calculate position based on index
103
103
  const index = FloatingTab.allTabs.indexOf(this);
104
104
  if (index === -1) {
105
- this.top = 100; // default fallback
105
+ this.top = 150; // default fallback
106
106
  } else {
107
107
  // start at 100px and stack with 10px gap between tabs
108
- this.top = 100 + index * (FloatingTab.TAB_HEIGHT + 0);
108
+ this.top = 150 + index * (FloatingTab.TAB_HEIGHT + 0);
109
109
  }
110
110
  }
111
111