@nyaruka/temba-components 0.133.0 → 0.134.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 (72) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/demo/components/webchat/example.html +1 -1
  3. package/dist/locales/es.js +5 -5
  4. package/dist/locales/es.js.map +1 -1
  5. package/dist/locales/fr.js +5 -5
  6. package/dist/locales/fr.js.map +1 -1
  7. package/dist/locales/locale-codes.js +2 -11
  8. package/dist/locales/locale-codes.js.map +1 -1
  9. package/dist/locales/pt.js +5 -5
  10. package/dist/locales/pt.js.map +1 -1
  11. package/dist/temba-components.js +306 -259
  12. package/dist/temba-components.js.map +1 -1
  13. package/out-tsc/src/display/Chat.js +223 -90
  14. package/out-tsc/src/display/Chat.js.map +1 -1
  15. package/out-tsc/src/display/TembaUser.js +3 -3
  16. package/out-tsc/src/display/TembaUser.js.map +1 -1
  17. package/out-tsc/src/events.js.map +1 -1
  18. package/out-tsc/src/flow/CanvasNode.js +8 -0
  19. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  20. package/out-tsc/src/flow/Editor.js +117 -28
  21. package/out-tsc/src/flow/Editor.js.map +1 -1
  22. package/out-tsc/src/flow/utils.js +141 -0
  23. package/out-tsc/src/flow/utils.js.map +1 -1
  24. package/out-tsc/src/interfaces.js.map +1 -1
  25. package/out-tsc/src/live/ContactChat.js +121 -170
  26. package/out-tsc/src/live/ContactChat.js.map +1 -1
  27. package/out-tsc/src/locales/es.js +5 -5
  28. package/out-tsc/src/locales/es.js.map +1 -1
  29. package/out-tsc/src/locales/fr.js +5 -5
  30. package/out-tsc/src/locales/fr.js.map +1 -1
  31. package/out-tsc/src/locales/locale-codes.js +2 -11
  32. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  33. package/out-tsc/src/locales/pt.js +5 -5
  34. package/out-tsc/src/locales/pt.js.map +1 -1
  35. package/out-tsc/src/store/AppState.js +3 -0
  36. package/out-tsc/src/store/AppState.js.map +1 -1
  37. package/out-tsc/src/store/Store.js +5 -5
  38. package/out-tsc/src/store/Store.js.map +1 -1
  39. package/out-tsc/src/webchat/WebChat.js +22 -9
  40. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  41. package/out-tsc/test/actions/send_broadcast.test.js +9 -4
  42. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  43. package/out-tsc/test/temba-flow-collision.test.js +673 -0
  44. package/out-tsc/test/temba-flow-collision.test.js.map +1 -0
  45. package/out-tsc/test/temba-flow-editor-node.test.js +128 -42
  46. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  47. package/package.json +1 -1
  48. package/screenshots/truth/contacts/chat-failure.png +0 -0
  49. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  50. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  51. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  52. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  53. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  54. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  55. package/src/display/Chat.ts +303 -129
  56. package/src/display/TembaUser.ts +3 -2
  57. package/src/events.ts +11 -8
  58. package/src/flow/CanvasNode.ts +10 -0
  59. package/src/flow/Editor.ts +156 -28
  60. package/src/flow/utils.ts +207 -1
  61. package/src/interfaces.ts +7 -0
  62. package/src/live/ContactChat.ts +128 -180
  63. package/src/locales/es.ts +13 -18
  64. package/src/locales/fr.ts +13 -18
  65. package/src/locales/locale-codes.ts +2 -11
  66. package/src/locales/pt.ts +13 -18
  67. package/src/store/AppState.ts +2 -0
  68. package/src/store/Store.ts +5 -5
  69. package/src/webchat/WebChat.ts +24 -10
  70. package/test/actions/send_broadcast.test.ts +2 -1
  71. package/test/temba-flow-collision.test.ts +833 -0
  72. package/test/temba-flow-editor-node.test.ts +142 -47
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temba-flow-collision.test.js","sourceRoot":"","sources":["../../test/temba-flow-collision.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport {\n getNodeBounds,\n nodesOverlap,\n detectCollisions,\n calculateReflowPositions,\n NodeBounds\n} from '../src/flow/utils';\n\ndescribe('Collision Detection Utilities', () => {\n describe('getNodeBounds', () => {\n it('returns null when element not found', () => {\n const position = { left: 100, top: 200 };\n const bounds = getNodeBounds('nonexistent-uuid', position);\n expect(bounds).to.be.null;\n });\n\n it('calculates bounds correctly from element', () => {\n // Create a mock element\n const mockElement = document.createElement('div');\n mockElement.id = 'test-node';\n mockElement.style.width = '200px';\n mockElement.style.height = '150px';\n document.body.appendChild(mockElement);\n\n const position = { left: 100, top: 200 };\n const bounds = getNodeBounds('test-node', position, mockElement);\n\n expect(bounds).to.not.be.null;\n expect(bounds!.uuid).to.equal('test-node');\n expect(bounds!.left).to.equal(100);\n expect(bounds!.top).to.equal(200);\n expect(bounds!.right).to.equal(300); // left + width\n expect(bounds!.bottom).to.equal(350); // top + height\n expect(bounds!.width).to.equal(200);\n expect(bounds!.height).to.equal(150);\n\n document.body.removeChild(mockElement);\n });\n });\n\n describe('nodesOverlap', () => {\n it('detects overlapping nodes horizontally and vertically', () => {\n const bounds1: NodeBounds = {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const bounds2: NodeBounds = {\n uuid: 'node2',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n };\n\n expect(nodesOverlap(bounds1, bounds2)).to.be.true;\n });\n\n it('detects non-overlapping nodes to the right', () => {\n const bounds1: NodeBounds = {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const bounds2: NodeBounds = {\n uuid: 'node2',\n left: 300,\n top: 100,\n right: 400,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n expect(nodesOverlap(bounds1, bounds2)).to.be.false;\n });\n\n it('detects non-overlapping nodes below', () => {\n const bounds1: NodeBounds = {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const bounds2: NodeBounds = {\n uuid: 'node2',\n left: 100,\n top: 300,\n right: 200,\n bottom: 400,\n width: 100,\n height: 100\n };\n\n expect(nodesOverlap(bounds1, bounds2)).to.be.false;\n });\n\n it('detects edge touching as overlapping (within buffer)', () => {\n const bounds1: NodeBounds = {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const bounds2: NodeBounds = {\n uuid: 'node2',\n left: 200,\n top: 100,\n right: 300,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n // edges touching should be considered overlapping due to buffer\n expect(nodesOverlap(bounds1, bounds2)).to.be.true;\n });\n\n it('detects partial vertical overlap', () => {\n const bounds1: NodeBounds = {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const bounds2: NodeBounds = {\n uuid: 'node2',\n left: 150,\n top: 50,\n right: 250,\n bottom: 150,\n width: 100,\n height: 100\n };\n\n expect(nodesOverlap(bounds1, bounds2)).to.be.true;\n });\n });\n\n describe('detectCollisions', () => {\n it('returns empty array when no collisions', () => {\n const targetBounds: NodeBounds = {\n uuid: 'target',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n {\n uuid: 'node1',\n left: 300,\n top: 100,\n right: 400,\n bottom: 200,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 100,\n top: 300,\n right: 200,\n bottom: 400,\n width: 100,\n height: 100\n }\n ];\n\n const collisions = detectCollisions(targetBounds, allBounds);\n expect(collisions).to.have.length(0);\n });\n\n it('detects single collision', () => {\n const targetBounds: NodeBounds = {\n uuid: 'target',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n {\n uuid: 'node1',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 300,\n top: 300,\n right: 400,\n bottom: 400,\n width: 100,\n height: 100\n }\n ];\n\n const collisions = detectCollisions(targetBounds, allBounds);\n expect(collisions).to.have.length(1);\n expect(collisions[0].uuid).to.equal('node1');\n });\n\n it('detects multiple collisions', () => {\n const targetBounds: NodeBounds = {\n uuid: 'target',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n {\n uuid: 'node1',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 50,\n top: 50,\n right: 150,\n bottom: 150,\n width: 100,\n height: 100\n }\n ];\n\n const collisions = detectCollisions(targetBounds, allBounds);\n expect(collisions).to.have.length(2);\n });\n\n it('excludes target node from collisions', () => {\n const targetBounds: NodeBounds = {\n uuid: 'target',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n targetBounds,\n {\n uuid: 'node1',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n }\n ];\n\n const collisions = detectCollisions(targetBounds, allBounds);\n expect(collisions).to.have.length(1);\n expect(collisions[0].uuid).to.equal('node1');\n });\n });\n\n describe('calculateReflowPositions', () => {\n it('returns empty map when no collisions', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 300,\n top: 100,\n right: 400,\n bottom: 200,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n expect(positions.size).to.equal(0);\n });\n\n it('moves colliding node down', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n expect(positions.size).to.equal(1);\n expect(positions.has('node1')).to.be.true;\n\n const newPos = positions.get('node1')!;\n expect(newPos.left).to.equal(150); // left unchanged\n expect(newPos.top).to.be.greaterThan(200); // moved below the moved node\n });\n\n it('handles droppedBelowMidpoint by moving dropped node down', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 150,\n right: 200,\n bottom: 250,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'existing',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n true // droppedBelowMidpoint\n );\n\n expect(positions.size).to.equal(1);\n expect(positions.has('moved')).to.be.true;\n\n const newPos = positions.get('moved')!;\n expect(newPos.top).to.be.greaterThan(200); // moved below existing node\n });\n\n it('gives priority to dropped node when dropped above midpoint', () => {\n // Dropped node overlaps with bottom of existing node\n // Bottom of dropped (180) is above midpoint of existing (150)\n // So dropped node should keep position, existing moves down\n const movedBounds: NodeBounds = {\n uuid: 'dropped',\n left: 100,\n top: 80,\n right: 200,\n bottom: 180,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'existing',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'dropped',\n movedBounds,\n allBounds,\n false // dropped node's bottom is above target midpoint, dropped node gets priority\n );\n\n // Existing node should be moved down\n expect(positions.has('existing')).to.be.true;\n expect(positions.has('dropped')).to.be.false; // dropped keeps its position\n\n const existingNewPos = positions.get('existing')!;\n expect(existingNewPos.top).to.be.greaterThan(180); // moved below dropped node\n });\n\n it('gives priority to existing node when dropped below midpoint', () => {\n // Dropped node overlaps with top of existing node\n // Bottom of dropped (220) is below midpoint of existing (150)\n // So existing node keeps position, dropped moves down\n const movedBounds: NodeBounds = {\n uuid: 'dropped',\n left: 100,\n top: 120,\n right: 200,\n bottom: 220,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'existing',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'dropped',\n movedBounds,\n allBounds,\n true // dropped node's bottom is below target midpoint, target gets priority\n );\n\n // Dropped node should be moved down\n expect(positions.has('dropped')).to.be.true;\n expect(positions.has('existing')).to.be.false; // existing keeps its position\n\n const droppedNewPos = positions.get('dropped')!;\n expect(droppedNewPos.top).to.be.greaterThan(200); // moved below existing node\n });\n\n it('resolves cascading collisions', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 100,\n top: 150,\n right: 200,\n bottom: 250,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 100,\n top: 200,\n right: 200,\n bottom: 300,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n // Both nodes should be repositioned to avoid collision\n expect(positions.size).to.be.greaterThan(0);\n\n // Check that moved nodes maintain vertical order and spacing\n if (positions.has('node1') && positions.has('node2')) {\n const node1Pos = positions.get('node1')!;\n const node2Pos = positions.get('node2')!;\n\n // node2 should be below node1\n expect(node2Pos.top).to.be.greaterThan(node1Pos.top);\n }\n });\n\n it('handles multiple iterations for complex cascading collisions', () => {\n // Test case that requires multiple iterations to resolve all collisions\n // This scenario has nodes that initially don't collide with moved node,\n // but will collide with other nodes that get moved\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 50,\n right: 200,\n bottom: 150,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 100,\n top: 180,\n right: 200,\n bottom: 280,\n width: 100,\n height: 100\n },\n {\n uuid: 'node3',\n left: 100,\n top: 260,\n right: 200,\n bottom: 360,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n // All three nodes should be repositioned to be stacked below the moved node\n expect(positions.size).to.equal(3);\n expect(positions.has('node1')).to.be.true;\n expect(positions.has('node2')).to.be.true;\n expect(positions.has('node3')).to.be.true;\n\n const node1Pos = positions.get('node1')!;\n const node2Pos = positions.get('node2')!;\n const node3Pos = positions.get('node3')!;\n\n // Nodes should be stacked vertically with proper spacing\n expect(node1Pos.top).to.be.at.least(170); // 150 (bottom of moved) + 20\n expect(node2Pos.top).to.be.at.least(node1Pos.top + 120); // node1 top + height + spacing\n expect(node3Pos.top).to.be.at.least(node2Pos.top + 120); // node2 top + height + spacing\n });\n\n it('handles nodes that collide with already repositioned nodes', () => {\n // This test creates a scenario where node3 doesn't collide with the moved node,\n // but collides with node2 which itself got repositioned due to collision with node1\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 100,\n top: 150,\n right: 200,\n bottom: 250,\n width: 100,\n height: 100\n },\n {\n uuid: 'node2',\n left: 100,\n top: 240,\n right: 200,\n bottom: 340,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n // Both nodes should be moved\n expect(positions.size).to.equal(2);\n expect(positions.has('node1')).to.be.true;\n expect(positions.has('node2')).to.be.true;\n\n const node1Pos = positions.get('node1')!;\n const node2Pos = positions.get('node2')!;\n\n // node1 should be moved below moved node\n expect(node1Pos.top).to.be.at.least(220); // 200 + 20\n\n // node2 should be moved below the new position of node1\n // This tests the code path where we check against already repositioned nodes\n expect(node2Pos.top).to.be.at.least(node1Pos.top + 120);\n });\n\n it('maintains horizontal position while moving vertically', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 150,\n top: 150,\n right: 250,\n bottom: 250,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n const newPos = positions.get('node1')!;\n // Horizontal position should remain unchanged\n expect(newPos.left).to.equal(150);\n });\n\n it('adds minimum spacing between nodes', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const allBounds: NodeBounds[] = [\n movedBounds,\n {\n uuid: 'node1',\n left: 100,\n top: 150,\n right: 200,\n bottom: 250,\n width: 100,\n height: 100\n }\n ];\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n const newPos = positions.get('node1')!;\n // Should have at least 20px spacing (MIN_NODE_SPACING)\n expect(newPos.top).to.be.at.least(220); // 200 (bottom of moved) + 20\n });\n });\n\n describe('edge cases', () => {\n it('handles empty allBounds array', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n [],\n false\n );\n\n expect(positions.size).to.equal(0);\n });\n\n it('handles single node (no other nodes to collide with)', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n [movedBounds],\n false\n );\n\n expect(positions.size).to.equal(0);\n });\n\n it('prevents infinite loops with complex collisions', () => {\n const movedBounds: NodeBounds = {\n uuid: 'moved',\n left: 100,\n top: 100,\n right: 200,\n bottom: 200,\n width: 100,\n height: 100\n };\n\n // Create a complex scenario with many overlapping nodes\n const allBounds: NodeBounds[] = [movedBounds];\n\n for (let i = 0; i < 20; i++) {\n allBounds.push({\n uuid: `node${i}`,\n left: 100 + i * 10,\n top: 100 + i * 10,\n right: 200 + i * 10,\n bottom: 200 + i * 10,\n width: 100,\n height: 100\n });\n }\n\n // Should complete without hanging\n const positions = calculateReflowPositions(\n 'moved',\n movedBounds,\n allBounds,\n false\n );\n\n // Should have resolved some collisions\n expect(positions.size).to.be.greaterThan(0);\n });\n });\n});\n"]}
@@ -950,45 +950,51 @@ describe('EditorNode', () => {
950
950
  { uuid: 'exit-3', destination_uuid: 'node-after' }
951
951
  ]
952
952
  };
953
- editorNode['node'] = mockNode;
954
953
  const mockFlowDefinition = {
954
+ language: 'en',
955
+ localization: {},
956
+ name: 'Test Flow',
957
+ type: 'messaging',
958
+ uuid: 'test-uuid',
959
+ revision: 1,
960
+ spec_version: '14.3',
955
961
  nodes: [
956
962
  {
957
963
  uuid: 'node-before',
964
+ actions: [],
958
965
  exits: [{ uuid: 'exit-before', destination_uuid: 'test-node' }]
959
966
  },
960
967
  mockNode,
961
968
  {
962
969
  uuid: 'node-after',
970
+ actions: [],
963
971
  exits: []
964
972
  }
965
- ]
966
- };
967
- // Verify all exits point to the same destination
968
- const destinations = mockNode.exits
969
- .map((exit) => exit.destination_uuid)
970
- .filter((dest) => dest);
971
- expect(destinations).to.have.length(3);
972
- expect(destinations.every((dest) => dest === 'node-after')).to.be.true;
973
- // Find incoming connections
974
- const incomingConnections = [];
975
- for (const node of mockFlowDefinition.nodes) {
976
- if (node.uuid !== mockNode.uuid) {
977
- for (const exit of node.exits) {
978
- if (exit.destination_uuid === mockNode.uuid) {
979
- incomingConnections.push({
980
- exitUuid: exit.uuid,
981
- sourceNodeUuid: node.uuid
982
- });
983
- }
984
- }
973
+ ],
974
+ _ui: {
975
+ nodes: {},
976
+ languages: []
985
977
  }
986
- }
987
- // Verify we found incoming connections
988
- expect(incomingConnections).to.have.length(1);
989
- expect(incomingConnections[0].exitUuid).to.equal('exit-before');
990
- // This validates that when a node has multiple exits but they all point
991
- // to the same destination, the rerouting logic should still apply
978
+ };
979
+ // Set up the zustand store with our test flow
980
+ const { zustand } = await import('../src/store/AppState');
981
+ zustand.setState({
982
+ flowDefinition: mockFlowDefinition
983
+ });
984
+ // Verify initial state - node-before points to test-node
985
+ const initialNodeBefore = zustand
986
+ .getState()
987
+ .flowDefinition.nodes.find((n) => n.uuid === 'node-before');
988
+ expect(initialNodeBefore.exits[0].destination_uuid).to.equal('test-node');
989
+ // Call removeNodes to trigger the rerouting logic
990
+ zustand.getState().removeNodes(['test-node']);
991
+ // Verify that the node was removed
992
+ const remainingNodes = zustand.getState().flowDefinition.nodes;
993
+ expect(remainingNodes.find((n) => n.uuid === 'test-node')).to.be
994
+ .undefined;
995
+ // Verify that node-before's exit was rerouted to node-after
996
+ const updatedNodeBefore = remainingNodes.find((n) => n.uuid === 'node-before');
997
+ expect(updatedNodeBefore.exits[0].destination_uuid).to.equal('node-after');
992
998
  });
993
999
  it('does not reroute connections when node has exits with different destinations', async () => {
994
1000
  // Test case: node with multiple exits pointing to different destinations
@@ -1007,14 +1013,56 @@ describe('EditorNode', () => {
1007
1013
  { uuid: 'exit-2', destination_uuid: 'node-after-2' }
1008
1014
  ]
1009
1015
  };
1010
- const destinations = mockNode.exits
1011
- .map((exit) => exit.destination_uuid)
1012
- .filter((dest) => dest);
1013
- // Verify exits point to different destinations
1014
- expect(destinations).to.have.length(2);
1015
- expect(destinations.every((dest) => dest === destinations[0])).to.be
1016
- .false;
1017
- // This validates that rerouting does NOT apply when exits point to different places
1016
+ const mockFlowDefinition = {
1017
+ language: 'en',
1018
+ localization: {},
1019
+ name: 'Test Flow',
1020
+ type: 'messaging',
1021
+ uuid: 'test-uuid',
1022
+ revision: 1,
1023
+ spec_version: '14.3',
1024
+ nodes: [
1025
+ {
1026
+ uuid: 'node-before',
1027
+ actions: [],
1028
+ exits: [{ uuid: 'exit-before', destination_uuid: 'test-node' }]
1029
+ },
1030
+ mockNode,
1031
+ {
1032
+ uuid: 'node-after-1',
1033
+ actions: [],
1034
+ exits: []
1035
+ },
1036
+ {
1037
+ uuid: 'node-after-2',
1038
+ actions: [],
1039
+ exits: []
1040
+ }
1041
+ ],
1042
+ _ui: {
1043
+ nodes: {},
1044
+ languages: []
1045
+ }
1046
+ };
1047
+ // Set up the zustand store with our test flow
1048
+ const { zustand } = await import('../src/store/AppState');
1049
+ zustand.setState({
1050
+ flowDefinition: mockFlowDefinition
1051
+ });
1052
+ // Verify initial state
1053
+ const initialNodeBefore = zustand
1054
+ .getState()
1055
+ .flowDefinition.nodes.find((n) => n.uuid === 'node-before');
1056
+ expect(initialNodeBefore.exits[0].destination_uuid).to.equal('test-node');
1057
+ // Call removeNodes
1058
+ zustand.getState().removeNodes(['test-node']);
1059
+ // Verify that the node was removed
1060
+ const remainingNodes = zustand.getState().flowDefinition.nodes;
1061
+ expect(remainingNodes.find((n) => n.uuid === 'test-node')).to.be
1062
+ .undefined;
1063
+ // Verify that incoming connection was cleared (set to null), not rerouted
1064
+ const updatedNodeBefore = remainingNodes.find((n) => n.uuid === 'node-before');
1065
+ expect(updatedNodeBefore.exits[0].destination_uuid).to.be.null;
1018
1066
  });
1019
1067
  it('does not reroute connections when node has exits with null destinations', async () => {
1020
1068
  // Test case: node with some exits having null destinations
@@ -1033,13 +1081,51 @@ describe('EditorNode', () => {
1033
1081
  { uuid: 'exit-2', destination_uuid: null }
1034
1082
  ]
1035
1083
  };
1036
- const destinations = mockNode.exits
1037
- .map((exit) => exit.destination_uuid)
1038
- .filter((dest) => dest);
1039
- // Verify not all exits have destinations
1040
- expect(destinations).to.have.length(1);
1041
- expect(destinations.length).to.not.equal(mockNode.exits.length);
1042
- // This validates that rerouting does NOT apply when some exits have no destination
1084
+ const mockFlowDefinition = {
1085
+ language: 'en',
1086
+ localization: {},
1087
+ name: 'Test Flow',
1088
+ type: 'messaging',
1089
+ uuid: 'test-uuid',
1090
+ revision: 1,
1091
+ spec_version: '14.3',
1092
+ nodes: [
1093
+ {
1094
+ uuid: 'node-before',
1095
+ actions: [],
1096
+ exits: [{ uuid: 'exit-before', destination_uuid: 'test-node' }]
1097
+ },
1098
+ mockNode,
1099
+ {
1100
+ uuid: 'node-after',
1101
+ actions: [],
1102
+ exits: []
1103
+ }
1104
+ ],
1105
+ _ui: {
1106
+ nodes: {},
1107
+ languages: []
1108
+ }
1109
+ };
1110
+ // Set up the zustand store with our test flow
1111
+ const { zustand } = await import('../src/store/AppState');
1112
+ zustand.setState({
1113
+ flowDefinition: mockFlowDefinition
1114
+ });
1115
+ // Verify initial state
1116
+ const initialNodeBefore = zustand
1117
+ .getState()
1118
+ .flowDefinition.nodes.find((n) => n.uuid === 'node-before');
1119
+ expect(initialNodeBefore.exits[0].destination_uuid).to.equal('test-node');
1120
+ // Call removeNodes
1121
+ zustand.getState().removeNodes(['test-node']);
1122
+ // Verify that the node was removed
1123
+ const remainingNodes = zustand.getState().flowDefinition.nodes;
1124
+ expect(remainingNodes.find((n) => n.uuid === 'test-node')).to.be
1125
+ .undefined;
1126
+ // Verify that incoming connection was cleared (set to null), not rerouted
1127
+ const updatedNodeBefore = remainingNodes.find((n) => n.uuid === 'node-before');
1128
+ expect(updatedNodeBefore.exits[0].destination_uuid).to.be.null;
1043
1129
  });
1044
1130
  });
1045
1131
  describe('add action button', () => {