@nyaruka/temba-components 0.131.0 → 0.131.2

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 (430) hide show
  1. package/.github/workflows/publish.yml +4 -1
  2. package/CHANGELOG.md +67 -1
  3. package/demo/data/flows/food-order.json +2 -2
  4. package/demo/data/flows/sample-flow.json +74 -125
  5. package/dist/static/svg/index.svg +1 -1
  6. package/dist/temba-components.js +1156 -619
  7. package/dist/temba-components.js.map +1 -1
  8. package/out-tsc/src/Icons.js +4 -1
  9. package/out-tsc/src/Icons.js.map +1 -1
  10. package/out-tsc/src/events.js.map +1 -1
  11. package/out-tsc/src/flow/CanvasMenu.js +200 -0
  12. package/out-tsc/src/flow/CanvasMenu.js.map +1 -0
  13. package/out-tsc/src/flow/CanvasNode.js +327 -19
  14. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  15. package/out-tsc/src/flow/Editor.js +562 -66
  16. package/out-tsc/src/flow/Editor.js.map +1 -1
  17. package/out-tsc/src/flow/NodeEditor.js +240 -93
  18. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  19. package/out-tsc/src/flow/NodeTypeSelector.js +499 -0
  20. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
  21. package/out-tsc/src/flow/actions/add_contact_groups.js +3 -3
  22. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  23. package/out-tsc/src/flow/actions/add_contact_urn.js +62 -4
  24. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  25. package/out-tsc/src/flow/actions/add_input_labels.js +3 -3
  26. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  27. package/out-tsc/src/flow/actions/play_audio.js +2 -2
  28. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  29. package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -5
  30. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  31. package/out-tsc/src/flow/actions/request_optin.js +2 -2
  32. package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
  33. package/out-tsc/src/flow/actions/say_msg.js +2 -2
  34. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  35. package/out-tsc/src/flow/actions/send_broadcast.js +76 -23
  36. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  37. package/out-tsc/src/flow/actions/send_email.js +4 -5
  38. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  39. package/out-tsc/src/flow/actions/send_msg.js +9 -19
  40. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  41. package/out-tsc/src/flow/actions/set_contact_channel.js +5 -9
  42. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  43. package/out-tsc/src/flow/actions/set_contact_field.js +19 -20
  44. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  45. package/out-tsc/src/flow/actions/set_contact_language.js +2 -2
  46. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  47. package/out-tsc/src/flow/actions/set_contact_name.js +2 -12
  48. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  49. package/out-tsc/src/flow/actions/set_contact_status.js +2 -2
  50. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  51. package/out-tsc/src/flow/actions/set_run_result.js +3 -3
  52. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  53. package/out-tsc/src/flow/actions/start_session.js +180 -6
  54. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  55. package/out-tsc/src/flow/config.js +11 -15
  56. package/out-tsc/src/flow/config.js.map +1 -1
  57. package/out-tsc/src/flow/currencies.js +45 -0
  58. package/out-tsc/src/flow/currencies.js.map +1 -0
  59. package/out-tsc/src/flow/nodes/shared-rules.js +257 -0
  60. package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -0
  61. package/out-tsc/src/flow/nodes/shared.js +17 -0
  62. package/out-tsc/src/flow/nodes/shared.js.map +1 -0
  63. package/out-tsc/src/flow/nodes/split_by_airtime.js +205 -5
  64. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
  65. package/out-tsc/src/flow/nodes/split_by_contact_field.js +147 -3
  66. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  67. package/out-tsc/src/flow/nodes/split_by_expression.js +68 -2
  68. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  69. package/out-tsc/src/flow/nodes/split_by_groups.js +12 -9
  70. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  71. package/out-tsc/src/flow/nodes/split_by_intent.js +7 -0
  72. package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
  73. package/out-tsc/src/flow/nodes/split_by_llm.js +3 -2
  74. package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
  75. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +2 -2
  76. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  77. package/out-tsc/src/flow/nodes/split_by_random.js +3 -3
  78. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  79. package/out-tsc/src/flow/nodes/split_by_resthook.js +108 -0
  80. package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -0
  81. package/out-tsc/src/flow/nodes/split_by_run_result.js +206 -3
  82. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  83. package/out-tsc/src/flow/nodes/split_by_scheme.js +153 -2
  84. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
  85. package/out-tsc/src/flow/nodes/split_by_subflow.js +6 -4
  86. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  87. package/out-tsc/src/flow/nodes/split_by_ticket.js +3 -2
  88. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  89. package/out-tsc/src/flow/nodes/split_by_webhook.js +3 -2
  90. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  91. package/out-tsc/src/flow/nodes/wait_for_audio.js +2 -2
  92. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -1
  93. package/out-tsc/src/flow/nodes/wait_for_digits.js +2 -2
  94. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  95. package/out-tsc/src/flow/nodes/wait_for_image.js +2 -2
  96. package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -1
  97. package/out-tsc/src/flow/nodes/wait_for_location.js +2 -2
  98. package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -1
  99. package/out-tsc/src/flow/nodes/wait_for_menu.js +2 -2
  100. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  101. package/out-tsc/src/flow/nodes/wait_for_response.js +32 -567
  102. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  103. package/out-tsc/src/flow/nodes/wait_for_video.js +2 -2
  104. package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -1
  105. package/out-tsc/src/flow/types.js +71 -12
  106. package/out-tsc/src/flow/types.js.map +1 -1
  107. package/out-tsc/src/flow/utils.js +101 -14
  108. package/out-tsc/src/flow/utils.js.map +1 -1
  109. package/out-tsc/src/form/ContactSearch.js +1 -1
  110. package/out-tsc/src/form/ContactSearch.js.map +1 -1
  111. package/out-tsc/src/form/FieldRenderer.js +2 -4
  112. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  113. package/out-tsc/src/interfaces.js +3 -0
  114. package/out-tsc/src/interfaces.js.map +1 -1
  115. package/out-tsc/src/list/SortableList.js +98 -33
  116. package/out-tsc/src/list/SortableList.js.map +1 -1
  117. package/out-tsc/src/live/ContactChat.js +15 -18
  118. package/out-tsc/src/live/ContactChat.js.map +1 -1
  119. package/out-tsc/src/store/AppState.js +53 -0
  120. package/out-tsc/src/store/AppState.js.map +1 -1
  121. package/out-tsc/src/utils.js +254 -13
  122. package/out-tsc/src/utils.js.map +1 -1
  123. package/out-tsc/temba-modules.js +4 -0
  124. package/out-tsc/temba-modules.js.map +1 -1
  125. package/out-tsc/test/ActionHelper.js +3 -3
  126. package/out-tsc/test/ActionHelper.js.map +1 -1
  127. package/out-tsc/test/NodeHelper.js +6 -3
  128. package/out-tsc/test/NodeHelper.js.map +1 -1
  129. package/out-tsc/test/actions/add_contact_urn.test.js +202 -0
  130. package/out-tsc/test/actions/add_contact_urn.test.js.map +1 -0
  131. package/out-tsc/test/actions/send_broadcast.test.js +148 -0
  132. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -0
  133. package/out-tsc/test/actions/send_email.test.js +17 -23
  134. package/out-tsc/test/actions/send_email.test.js.map +1 -1
  135. package/out-tsc/test/actions/send_msg.test.js +33 -15
  136. package/out-tsc/test/actions/send_msg.test.js.map +1 -1
  137. package/out-tsc/test/actions/start_session.test.js +116 -0
  138. package/out-tsc/test/actions/start_session.test.js.map +1 -0
  139. package/out-tsc/test/nodes/split_by_airtime.test.js +604 -0
  140. package/out-tsc/test/nodes/split_by_airtime.test.js.map +1 -0
  141. package/out-tsc/test/nodes/split_by_contact_field.test.js +387 -0
  142. package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -0
  143. package/out-tsc/test/nodes/split_by_expression.test.js +614 -0
  144. package/out-tsc/test/nodes/split_by_expression.test.js.map +1 -0
  145. package/out-tsc/test/nodes/split_by_random.test.js +3 -3
  146. package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
  147. package/out-tsc/test/nodes/split_by_resthook.test.js +337 -0
  148. package/out-tsc/test/nodes/split_by_resthook.test.js.map +1 -0
  149. package/out-tsc/test/nodes/split_by_run_result.test.js +920 -0
  150. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -0
  151. package/out-tsc/test/nodes/split_by_scheme.test.js +399 -0
  152. package/out-tsc/test/nodes/split_by_scheme.test.js.map +1 -0
  153. package/out-tsc/test/nodes/split_by_subflow.test.js +333 -0
  154. package/out-tsc/test/nodes/split_by_subflow.test.js.map +1 -0
  155. package/out-tsc/test/nodes/wait_for_digits.test.js +2 -2
  156. package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
  157. package/out-tsc/test/nodes/wait_for_response.test.js +2 -1
  158. package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
  159. package/out-tsc/test/temba-action-drag-between-nodes.test.js +252 -0
  160. package/out-tsc/test/temba-action-drag-between-nodes.test.js.map +1 -0
  161. package/out-tsc/test/temba-canvas-menu.test.js +122 -0
  162. package/out-tsc/test/temba-canvas-menu.test.js.map +1 -0
  163. package/out-tsc/test/temba-flow-editor-node.test.js +85 -2
  164. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  165. package/out-tsc/test/temba-flow-editor.test.js +7 -8
  166. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  167. package/out-tsc/test/temba-node-editor.test.js +3 -1
  168. package/out-tsc/test/temba-node-editor.test.js.map +1 -1
  169. package/out-tsc/test/temba-node-type-selector.test.js +115 -0
  170. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -0
  171. package/out-tsc/test/temba-omnibox.test.js +2 -1
  172. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  173. package/out-tsc/test/temba-sortable-list.test.js +51 -0
  174. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  175. package/out-tsc/test/temba-utils-index.test.js +1 -27
  176. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  177. package/out-tsc/test/utils.test.js +2 -0
  178. package/out-tsc/test/utils.test.js.map +1 -1
  179. package/package.json +2 -1
  180. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  181. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  182. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  183. package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
  184. package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
  185. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  186. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  187. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  188. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  189. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  190. package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
  191. package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
  192. package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
  193. package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
  194. package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
  195. package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
  196. package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
  197. package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
  198. package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
  199. package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
  200. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  201. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  202. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  203. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  204. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  205. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  206. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  207. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  208. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  209. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  210. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  211. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  212. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  213. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  214. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  215. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  216. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  217. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  218. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  219. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  220. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  221. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  222. package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
  223. package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
  224. package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
  225. package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
  226. package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
  227. package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
  228. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  229. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  230. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  231. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  232. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  233. package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
  234. package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
  235. package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
  236. package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
  237. package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
  238. package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
  239. package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
  240. package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
  241. package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
  242. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  243. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  244. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  245. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  246. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  247. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  248. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  249. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  250. package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
  251. package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
  252. package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
  253. package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
  254. package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
  255. package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
  256. package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
  257. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  258. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  259. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  260. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  261. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  262. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  263. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  264. package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
  265. package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
  266. package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
  267. package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
  268. package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
  269. package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
  270. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  271. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  272. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  273. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  274. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  275. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  276. package/screenshots/truth/canvas-menu/open.png +0 -0
  277. package/screenshots/truth/editor/router.png +0 -0
  278. package/screenshots/truth/editor/wait.png +0 -0
  279. package/screenshots/truth/list/fields-dragging.png +0 -0
  280. package/screenshots/truth/list/sortable-dragging.png +0 -0
  281. package/screenshots/truth/node-type-selector/action-mode.png +0 -0
  282. package/screenshots/truth/node-type-selector/split-mode.png +0 -0
  283. package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
  284. package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
  285. package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
  286. package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
  287. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  288. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  289. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  290. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  291. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  292. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  293. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  294. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  295. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  296. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  297. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  298. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  299. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  300. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  301. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  302. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  303. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  304. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  305. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  306. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  307. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  308. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  309. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  310. package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
  311. package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
  312. package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
  313. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  314. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  315. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  316. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
  317. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  318. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  319. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  320. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  321. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  322. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  323. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  324. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  325. package/src/Icons.ts +4 -1
  326. package/src/events.ts +2 -6
  327. package/src/flow/CanvasMenu.ts +217 -0
  328. package/src/flow/CanvasNode.ts +408 -10
  329. package/src/flow/Editor.ts +683 -44
  330. package/src/flow/NodeEditor.ts +304 -125
  331. package/src/flow/NodeTypeSelector.ts +592 -0
  332. package/src/flow/actions/add_contact_groups.ts +4 -4
  333. package/src/flow/actions/add_contact_urn.ts +76 -4
  334. package/src/flow/actions/add_input_labels.ts +4 -4
  335. package/src/flow/actions/play_audio.ts +2 -2
  336. package/src/flow/actions/remove_contact_groups.ts +14 -6
  337. package/src/flow/actions/request_optin.ts +2 -2
  338. package/src/flow/actions/say_msg.ts +2 -2
  339. package/src/flow/actions/send_broadcast.ts +85 -23
  340. package/src/flow/actions/send_email.ts +10 -6
  341. package/src/flow/actions/send_msg.ts +22 -32
  342. package/src/flow/actions/set_contact_channel.ts +5 -11
  343. package/src/flow/actions/set_contact_field.ts +20 -25
  344. package/src/flow/actions/set_contact_language.ts +9 -4
  345. package/src/flow/actions/set_contact_name.ts +3 -15
  346. package/src/flow/actions/set_contact_status.ts +3 -3
  347. package/src/flow/actions/set_run_result.ts +4 -4
  348. package/src/flow/actions/start_session.ts +208 -6
  349. package/src/flow/config.ts +13 -15
  350. package/src/flow/currencies.ts +51 -0
  351. package/src/flow/nodes/shared-rules.ts +301 -0
  352. package/src/flow/nodes/shared.ts +18 -0
  353. package/src/flow/nodes/split_by_airtime.ts +238 -5
  354. package/src/flow/nodes/split_by_contact_field.ts +185 -3
  355. package/src/flow/nodes/split_by_expression.ts +94 -2
  356. package/src/flow/nodes/split_by_groups.ts +15 -10
  357. package/src/flow/nodes/split_by_intent.ts +7 -0
  358. package/src/flow/nodes/split_by_llm.ts +4 -3
  359. package/src/flow/nodes/split_by_llm_categorize.ts +4 -4
  360. package/src/flow/nodes/split_by_random.ts +5 -5
  361. package/src/flow/nodes/split_by_resthook.ts +130 -0
  362. package/src/flow/nodes/split_by_run_result.ts +249 -3
  363. package/src/flow/nodes/split_by_scheme.ts +192 -2
  364. package/src/flow/nodes/split_by_subflow.ts +6 -4
  365. package/src/flow/nodes/split_by_ticket.ts +4 -3
  366. package/src/flow/nodes/split_by_webhook.ts +6 -5
  367. package/src/flow/nodes/wait_for_audio.ts +2 -2
  368. package/src/flow/nodes/wait_for_digits.ts +2 -2
  369. package/src/flow/nodes/wait_for_image.ts +2 -2
  370. package/src/flow/nodes/wait_for_location.ts +2 -2
  371. package/src/flow/nodes/wait_for_menu.ts +2 -2
  372. package/src/flow/nodes/wait_for_response.ts +48 -679
  373. package/src/flow/nodes/wait_for_video.ts +2 -2
  374. package/src/flow/types.ts +109 -23
  375. package/src/flow/utils.ts +108 -14
  376. package/src/form/ContactSearch.ts +1 -1
  377. package/src/form/FieldRenderer.ts +2 -4
  378. package/src/interfaces.ts +3 -0
  379. package/src/list/SortableList.ts +109 -34
  380. package/src/live/ContactChat.ts +15 -18
  381. package/src/store/AppState.ts +69 -0
  382. package/src/store/flow-definition.d.ts +2 -5
  383. package/src/utils.ts +332 -12
  384. package/static/api/channels.json +46 -0
  385. package/static/api/resthooks.json +31 -0
  386. package/static/svg/index.svg +1 -1
  387. package/static/svg/work/traced/lightning-02.svg +1 -0
  388. package/static/svg/work/used/lightning-02.svg +3 -0
  389. package/temba-modules.ts +4 -0
  390. package/test/ActionHelper.ts +3 -3
  391. package/test/NodeHelper.ts +6 -3
  392. package/test/actions/add_contact_urn.test.ts +287 -0
  393. package/test/actions/send_broadcast.test.ts +190 -0
  394. package/test/actions/send_email.test.ts +17 -23
  395. package/test/actions/send_msg.test.ts +39 -15
  396. package/test/actions/start_session.test.ts +151 -0
  397. package/test/nodes/split_by_airtime.test.ts +673 -0
  398. package/test/nodes/split_by_contact_field.test.ts +451 -0
  399. package/test/nodes/split_by_expression.test.ts +751 -0
  400. package/test/nodes/split_by_random.test.ts +3 -3
  401. package/test/nodes/split_by_resthook.test.ts +398 -0
  402. package/test/nodes/split_by_run_result.test.ts +1109 -0
  403. package/test/nodes/split_by_scheme.test.ts +486 -0
  404. package/test/nodes/split_by_subflow.test.ts +381 -0
  405. package/test/nodes/wait_for_digits.test.ts +2 -2
  406. package/test/nodes/wait_for_response.test.ts +2 -1
  407. package/test/temba-action-drag-between-nodes.test.ts +301 -0
  408. package/test/temba-canvas-menu.test.ts +156 -0
  409. package/test/temba-flow-editor-node.test.ts +102 -2
  410. package/test/temba-flow-editor.test.ts +7 -8
  411. package/test/temba-node-editor.test.ts +3 -1
  412. package/test/temba-node-type-selector.test.ts +152 -0
  413. package/test/temba-omnibox.test.ts +2 -1
  414. package/test/temba-sortable-list.test.ts +69 -0
  415. package/test/temba-utils-index.test.ts +0 -35
  416. package/test/utils.test.ts +2 -0
  417. package/test-assets/contacts/history.json +14 -20
  418. package/web-dev-server.config.mjs +3 -1
  419. package/out-tsc/src/flow/actions/call_classifier.js +0 -11
  420. package/out-tsc/src/flow/actions/call_classifier.js.map +0 -1
  421. package/out-tsc/src/flow/actions/call_resthook.js +0 -11
  422. package/out-tsc/src/flow/actions/call_resthook.js.map +0 -1
  423. package/out-tsc/src/flow/actions/split_by_expression_example.js +0 -77
  424. package/out-tsc/src/flow/actions/split_by_expression_example.js.map +0 -1
  425. package/out-tsc/src/flow/actions/transfer_airtime.js +0 -11
  426. package/out-tsc/src/flow/actions/transfer_airtime.js.map +0 -1
  427. package/src/flow/actions/call_classifier.ts +0 -12
  428. package/src/flow/actions/call_resthook.ts +0 -12
  429. package/src/flow/actions/split_by_expression_example.ts +0 -88
  430. package/src/flow/actions/transfer_airtime.ts +0 -12
@@ -0,0 +1,202 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { add_contact_urn } from '../../src/flow/actions/add_contact_urn';
3
+ import { ActionTest } from '../ActionHelper';
4
+ /**
5
+ * Test suite for the add_contact_urn action configuration.
6
+ */
7
+ describe('add_contact_urn action config', () => {
8
+ const helper = new ActionTest(add_contact_urn, 'add_contact_urn');
9
+ describe('basic properties', () => {
10
+ helper.testBasicProperties();
11
+ it('has correct name', () => {
12
+ expect(add_contact_urn.name).to.equal('Add URN');
13
+ });
14
+ });
15
+ describe('action scenarios', () => {
16
+ helper.testAction({
17
+ uuid: 'test-action-1',
18
+ type: 'add_contact_urn',
19
+ scheme: 'tel',
20
+ path: '+12065551212'
21
+ }, 'phone-number');
22
+ helper.testAction({
23
+ uuid: 'test-action-2',
24
+ type: 'add_contact_urn',
25
+ scheme: 'whatsapp',
26
+ path: '+447123456789'
27
+ }, 'whatsapp');
28
+ helper.testAction({
29
+ uuid: 'test-action-3',
30
+ type: 'add_contact_urn',
31
+ scheme: 'facebook',
32
+ path: '1234567890'
33
+ }, 'facebook-id');
34
+ helper.testAction({
35
+ uuid: 'test-action-4',
36
+ type: 'add_contact_urn',
37
+ scheme: 'telegram',
38
+ path: '987654321'
39
+ }, 'telegram-id');
40
+ helper.testAction({
41
+ uuid: 'test-action-5',
42
+ type: 'add_contact_urn',
43
+ scheme: 'instagram',
44
+ path: 'user_instagram_handle'
45
+ }, 'instagram-handle');
46
+ helper.testAction({
47
+ uuid: 'test-action-6',
48
+ type: 'add_contact_urn',
49
+ scheme: 'tel',
50
+ path: '@run.results.phone_number'
51
+ }, 'expression-phone');
52
+ helper.testAction({
53
+ uuid: 'test-action-7',
54
+ type: 'add_contact_urn',
55
+ scheme: 'facebook',
56
+ path: '@fields.facebook_id'
57
+ }, 'expression-facebook');
58
+ helper.testAction({
59
+ uuid: 'test-action-8',
60
+ type: 'add_contact_urn',
61
+ scheme: 'line',
62
+ path: 'U1234567890abcdef1234567890abcdef'
63
+ }, 'line-id');
64
+ helper.testAction({
65
+ uuid: 'test-action-9',
66
+ type: 'add_contact_urn',
67
+ scheme: 'viber',
68
+ path: '0123456789ABC='
69
+ }, 'viber-id');
70
+ helper.testAction({
71
+ uuid: 'test-action-10',
72
+ type: 'add_contact_urn',
73
+ scheme: 'wechat',
74
+ path: 'wechatuser123'
75
+ }, 'wechat-id');
76
+ });
77
+ describe('validation', () => {
78
+ it('validates that scheme is required', () => {
79
+ const formData = {
80
+ scheme: [],
81
+ path: '+12065551212'
82
+ };
83
+ const result = add_contact_urn.validate(formData);
84
+ expect(result.valid).to.be.false;
85
+ expect(result.errors.scheme).to.equal('URN type is required');
86
+ });
87
+ it('validates that path is required', () => {
88
+ const formData = {
89
+ scheme: [{ name: 'Phone Number', value: 'tel' }],
90
+ path: ''
91
+ };
92
+ const result = add_contact_urn.validate(formData);
93
+ expect(result.valid).to.be.false;
94
+ expect(result.errors.path).to.equal('URN value is required');
95
+ });
96
+ it('validates that path with only whitespace is invalid', () => {
97
+ const formData = {
98
+ scheme: [{ name: 'Phone Number', value: 'tel' }],
99
+ path: ' '
100
+ };
101
+ const result = add_contact_urn.validate(formData);
102
+ expect(result.valid).to.be.false;
103
+ expect(result.errors.path).to.equal('URN value is required');
104
+ });
105
+ it('validates successfully with both scheme and path', () => {
106
+ const formData = {
107
+ scheme: [{ name: 'Phone Number', value: 'tel' }],
108
+ path: '+12065551212'
109
+ };
110
+ const result = add_contact_urn.validate(formData);
111
+ expect(result.valid).to.be.true;
112
+ expect(Object.keys(result.errors)).to.have.lengthOf(0);
113
+ });
114
+ it('validates successfully with expression in path', () => {
115
+ const formData = {
116
+ scheme: [{ name: 'Facebook ID', value: 'facebook' }],
117
+ path: '@fields.facebook_id'
118
+ };
119
+ const result = add_contact_urn.validate(formData);
120
+ expect(result.valid).to.be.true;
121
+ expect(Object.keys(result.errors)).to.have.lengthOf(0);
122
+ });
123
+ });
124
+ describe('round-trip transformation', () => {
125
+ it('should preserve action structure through toFormData -> fromFormData', () => {
126
+ const originalAction = {
127
+ uuid: 'test-uuid-123',
128
+ type: 'add_contact_urn',
129
+ scheme: 'whatsapp',
130
+ path: '+447123456789'
131
+ };
132
+ const formData = add_contact_urn.toFormData(originalAction);
133
+ const convertedAction = add_contact_urn.fromFormData(formData);
134
+ expect(convertedAction.uuid).to.equal(originalAction.uuid);
135
+ expect(convertedAction.type).to.equal(originalAction.type);
136
+ expect(convertedAction.scheme).to.equal(originalAction.scheme);
137
+ expect(convertedAction.path).to.equal(originalAction.path);
138
+ });
139
+ it('should handle different URN schemes correctly', () => {
140
+ const schemes = ['tel', 'facebook', 'telegram', 'instagram', 'whatsapp'];
141
+ schemes.forEach((scheme) => {
142
+ const originalAction = {
143
+ uuid: 'test-uuid',
144
+ type: 'add_contact_urn',
145
+ scheme: scheme,
146
+ path: 'test-value'
147
+ };
148
+ const formData = add_contact_urn.toFormData(originalAction);
149
+ const convertedAction = add_contact_urn.fromFormData(formData);
150
+ expect(convertedAction.scheme).to.equal(scheme);
151
+ });
152
+ });
153
+ it('should handle expressions in path', () => {
154
+ const originalAction = {
155
+ uuid: 'test-uuid',
156
+ type: 'add_contact_urn',
157
+ scheme: 'tel',
158
+ path: '@run.results.phone_number'
159
+ };
160
+ const formData = add_contact_urn.toFormData(originalAction);
161
+ const convertedAction = add_contact_urn.fromFormData(formData);
162
+ expect(convertedAction.path).to.equal('@run.results.phone_number');
163
+ });
164
+ it('should default to tel scheme if scheme is missing in form data', () => {
165
+ const formData = {
166
+ uuid: 'test-uuid',
167
+ scheme: [],
168
+ path: '+12065551212'
169
+ };
170
+ const convertedAction = add_contact_urn.fromFormData(formData);
171
+ expect(convertedAction.scheme).to.equal('tel');
172
+ });
173
+ });
174
+ describe('form data structure', () => {
175
+ it('should convert scheme to select array format in toFormData', () => {
176
+ const action = {
177
+ uuid: 'test-uuid',
178
+ type: 'add_contact_urn',
179
+ scheme: 'whatsapp',
180
+ path: '+447123456789'
181
+ };
182
+ const formData = add_contact_urn.toFormData(action);
183
+ expect(formData.scheme).to.be.an('array');
184
+ expect(formData.scheme).to.have.lengthOf(1);
185
+ expect(formData.scheme[0]).to.deep.include({
186
+ name: 'WhatsApp Number',
187
+ value: 'whatsapp'
188
+ });
189
+ });
190
+ it('should handle unknown scheme gracefully', () => {
191
+ const action = {
192
+ uuid: 'test-uuid',
193
+ type: 'add_contact_urn',
194
+ scheme: 'unknown_scheme',
195
+ path: 'some-value'
196
+ };
197
+ const formData = add_contact_urn.toFormData(action);
198
+ expect(formData.scheme).to.be.null;
199
+ });
200
+ });
201
+ });
202
+ //# sourceMappingURL=add_contact_urn.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add_contact_urn.test.js","sourceRoot":"","sources":["../../../test/actions/add_contact_urn.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { add_contact_urn } from '../../src/flow/actions/add_contact_urn';\nimport { AddContactUrn } from '../../src/store/flow-definition';\nimport { ActionTest } from '../ActionHelper';\n\n/**\n * Test suite for the add_contact_urn action configuration.\n */\ndescribe('add_contact_urn action config', () => {\n const helper = new ActionTest(add_contact_urn, 'add_contact_urn');\n\n describe('basic properties', () => {\n helper.testBasicProperties();\n\n it('has correct name', () => {\n expect(add_contact_urn.name).to.equal('Add URN');\n });\n });\n\n describe('action scenarios', () => {\n helper.testAction(\n {\n uuid: 'test-action-1',\n type: 'add_contact_urn',\n scheme: 'tel',\n path: '+12065551212'\n } as AddContactUrn,\n 'phone-number'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-2',\n type: 'add_contact_urn',\n scheme: 'whatsapp',\n path: '+447123456789'\n } as AddContactUrn,\n 'whatsapp'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-3',\n type: 'add_contact_urn',\n scheme: 'facebook',\n path: '1234567890'\n } as AddContactUrn,\n 'facebook-id'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-4',\n type: 'add_contact_urn',\n scheme: 'telegram',\n path: '987654321'\n } as AddContactUrn,\n 'telegram-id'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-5',\n type: 'add_contact_urn',\n scheme: 'instagram',\n path: 'user_instagram_handle'\n } as AddContactUrn,\n 'instagram-handle'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-6',\n type: 'add_contact_urn',\n scheme: 'tel',\n path: '@run.results.phone_number'\n } as AddContactUrn,\n 'expression-phone'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-7',\n type: 'add_contact_urn',\n scheme: 'facebook',\n path: '@fields.facebook_id'\n } as AddContactUrn,\n 'expression-facebook'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-8',\n type: 'add_contact_urn',\n scheme: 'line',\n path: 'U1234567890abcdef1234567890abcdef'\n } as AddContactUrn,\n 'line-id'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-9',\n type: 'add_contact_urn',\n scheme: 'viber',\n path: '0123456789ABC='\n } as AddContactUrn,\n 'viber-id'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-10',\n type: 'add_contact_urn',\n scheme: 'wechat',\n path: 'wechatuser123'\n } as AddContactUrn,\n 'wechat-id'\n );\n });\n\n describe('validation', () => {\n it('validates that scheme is required', () => {\n const formData = {\n scheme: [],\n path: '+12065551212'\n };\n\n const result = add_contact_urn.validate!(formData);\n\n expect(result.valid).to.be.false;\n expect(result.errors.scheme).to.equal('URN type is required');\n });\n\n it('validates that path is required', () => {\n const formData = {\n scheme: [{ name: 'Phone Number', value: 'tel' }],\n path: ''\n };\n\n const result = add_contact_urn.validate!(formData);\n\n expect(result.valid).to.be.false;\n expect(result.errors.path).to.equal('URN value is required');\n });\n\n it('validates that path with only whitespace is invalid', () => {\n const formData = {\n scheme: [{ name: 'Phone Number', value: 'tel' }],\n path: ' '\n };\n\n const result = add_contact_urn.validate!(formData);\n\n expect(result.valid).to.be.false;\n expect(result.errors.path).to.equal('URN value is required');\n });\n\n it('validates successfully with both scheme and path', () => {\n const formData = {\n scheme: [{ name: 'Phone Number', value: 'tel' }],\n path: '+12065551212'\n };\n\n const result = add_contact_urn.validate!(formData);\n\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.lengthOf(0);\n });\n\n it('validates successfully with expression in path', () => {\n const formData = {\n scheme: [{ name: 'Facebook ID', value: 'facebook' }],\n path: '@fields.facebook_id'\n };\n\n const result = add_contact_urn.validate!(formData);\n\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.lengthOf(0);\n });\n });\n\n describe('round-trip transformation', () => {\n it('should preserve action structure through toFormData -> fromFormData', () => {\n const originalAction: AddContactUrn = {\n uuid: 'test-uuid-123',\n type: 'add_contact_urn',\n scheme: 'whatsapp',\n path: '+447123456789'\n };\n\n const formData = add_contact_urn.toFormData!(originalAction);\n const convertedAction = add_contact_urn.fromFormData!(\n formData\n ) as AddContactUrn;\n\n expect(convertedAction.uuid).to.equal(originalAction.uuid);\n expect(convertedAction.type).to.equal(originalAction.type);\n expect(convertedAction.scheme).to.equal(originalAction.scheme);\n expect(convertedAction.path).to.equal(originalAction.path);\n });\n\n it('should handle different URN schemes correctly', () => {\n const schemes = ['tel', 'facebook', 'telegram', 'instagram', 'whatsapp'];\n\n schemes.forEach((scheme) => {\n const originalAction: AddContactUrn = {\n uuid: 'test-uuid',\n type: 'add_contact_urn',\n scheme: scheme,\n path: 'test-value'\n };\n\n const formData = add_contact_urn.toFormData!(originalAction);\n const convertedAction = add_contact_urn.fromFormData!(\n formData\n ) as AddContactUrn;\n\n expect(convertedAction.scheme).to.equal(scheme);\n });\n });\n\n it('should handle expressions in path', () => {\n const originalAction: AddContactUrn = {\n uuid: 'test-uuid',\n type: 'add_contact_urn',\n scheme: 'tel',\n path: '@run.results.phone_number'\n };\n\n const formData = add_contact_urn.toFormData!(originalAction);\n const convertedAction = add_contact_urn.fromFormData!(\n formData\n ) as AddContactUrn;\n\n expect(convertedAction.path).to.equal('@run.results.phone_number');\n });\n\n it('should default to tel scheme if scheme is missing in form data', () => {\n const formData = {\n uuid: 'test-uuid',\n scheme: [],\n path: '+12065551212'\n };\n\n const convertedAction = add_contact_urn.fromFormData!(\n formData\n ) as AddContactUrn;\n\n expect(convertedAction.scheme).to.equal('tel');\n });\n });\n\n describe('form data structure', () => {\n it('should convert scheme to select array format in toFormData', () => {\n const action: AddContactUrn = {\n uuid: 'test-uuid',\n type: 'add_contact_urn',\n scheme: 'whatsapp',\n path: '+447123456789'\n };\n\n const formData = add_contact_urn.toFormData!(action);\n\n expect(formData.scheme).to.be.an('array');\n expect(formData.scheme).to.have.lengthOf(1);\n expect(formData.scheme[0]).to.deep.include({\n name: 'WhatsApp Number',\n value: 'whatsapp'\n });\n });\n\n it('should handle unknown scheme gracefully', () => {\n const action: AddContactUrn = {\n uuid: 'test-uuid',\n type: 'add_contact_urn',\n scheme: 'unknown_scheme',\n path: 'some-value'\n };\n\n const formData = add_contact_urn.toFormData!(action);\n\n expect(formData.scheme).to.be.null;\n });\n });\n});\n"]}
@@ -0,0 +1,148 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { send_broadcast } from '../../src/flow/actions/send_broadcast';
3
+ import { ActionTest } from '../ActionHelper';
4
+ /**
5
+ * Test suite for the send_broadcast action configuration.
6
+ */
7
+ describe('send_broadcast action config', () => {
8
+ const helper = new ActionTest(send_broadcast, 'send_broadcast');
9
+ describe('basic properties', () => {
10
+ helper.testBasicProperties();
11
+ it('has correct name', () => {
12
+ expect(send_broadcast.name).to.equal('Send Broadcast');
13
+ });
14
+ });
15
+ describe('action scenarios', () => {
16
+ helper.testAction({
17
+ uuid: 'test-action-1',
18
+ type: 'send_broadcast',
19
+ text: 'Important announcement for all subscribers!',
20
+ groups: [
21
+ { uuid: 'group-1', name: 'Subscribers' },
22
+ { uuid: 'group-2', name: 'VIP Members' }
23
+ ],
24
+ contacts: []
25
+ }, 'groups-only');
26
+ helper.testAction({
27
+ uuid: 'test-action-2',
28
+ type: 'send_broadcast',
29
+ text: 'Personal message to specific contacts.',
30
+ groups: [],
31
+ contacts: [
32
+ { uuid: 'contact-1', name: 'Alice Johnson' },
33
+ { uuid: 'contact-2', name: 'Bob Smith' }
34
+ ]
35
+ }, 'contacts-only');
36
+ helper.testAction({
37
+ uuid: 'test-action-3',
38
+ type: 'send_broadcast',
39
+ text: 'Urgent update for everyone!',
40
+ groups: [{ uuid: 'group-1', name: 'All Members' }],
41
+ contacts: [{ uuid: 'contact-1', name: 'Admin' }]
42
+ }, 'groups-and-contacts');
43
+ helper.testAction({
44
+ uuid: 'test-action-4',
45
+ type: 'send_broadcast',
46
+ text: 'Multi-line broadcast message.\n\nThis is the second paragraph.\n\nAnd the third.',
47
+ groups: [{ uuid: 'group-1', name: 'Newsletter Subscribers' }],
48
+ contacts: []
49
+ }, 'multiline-text');
50
+ helper.testAction({
51
+ uuid: 'test-action-5',
52
+ type: 'send_broadcast',
53
+ text: 'Broadcast with attachments',
54
+ groups: [{ uuid: 'group-1', name: 'Members' }],
55
+ contacts: [],
56
+ attachments: [
57
+ 'image/jpeg:https://example.com/photo.jpg',
58
+ 'application/pdf:https://example.com/document.pdf'
59
+ ]
60
+ }, 'with-attachments');
61
+ helper.testAction({
62
+ uuid: 'test-action-6',
63
+ type: 'send_broadcast',
64
+ text: 'Message to many groups',
65
+ groups: [
66
+ { uuid: 'group-1', name: 'Group A' },
67
+ { uuid: 'group-2', name: 'Group B' },
68
+ { uuid: 'group-3', name: 'Group C' },
69
+ { uuid: 'group-4', name: 'Group D' }
70
+ ],
71
+ contacts: []
72
+ }, 'many-groups');
73
+ });
74
+ describe('form data conversion', () => {
75
+ it('converts action to form data correctly', () => {
76
+ const action = {
77
+ uuid: 'test-uuid',
78
+ type: 'send_broadcast',
79
+ text: 'Test message',
80
+ groups: [{ uuid: 'group-1', name: 'Test Group' }],
81
+ contacts: [{ uuid: 'contact-1', name: 'Test Contact' }],
82
+ attachments: ['image/jpeg:test.jpg']
83
+ };
84
+ const formData = send_broadcast.toFormData(action);
85
+ expect(formData.uuid).to.equal('test-uuid');
86
+ expect(formData.text).to.equal('Test message');
87
+ expect(formData.recipients).to.have.lengthOf(2);
88
+ expect(formData.attachments).to.deep.equal(['image/jpeg:test.jpg']);
89
+ });
90
+ it('converts form data to action correctly with contacts only', () => {
91
+ const formData = {
92
+ uuid: 'test-uuid',
93
+ recipients: [
94
+ { uuid: 'contact-1', name: 'Contact 1' },
95
+ { uuid: 'contact-2', name: 'Contact 2' }
96
+ ],
97
+ text: 'Test message',
98
+ attachments: []
99
+ };
100
+ const action = send_broadcast.fromFormData(formData);
101
+ expect(action.uuid).to.equal('test-uuid');
102
+ expect(action.type).to.equal('send_broadcast');
103
+ expect(action.text).to.equal('Test message');
104
+ expect(action.contacts).to.have.lengthOf(2);
105
+ expect(action.groups).to.have.lengthOf(0);
106
+ expect(action.attachments).to.be.undefined;
107
+ });
108
+ it('converts form data to action correctly with groups only', () => {
109
+ const formData = {
110
+ uuid: 'test-uuid',
111
+ recipients: [
112
+ { uuid: 'group-1', name: 'Group 1', group: true },
113
+ { uuid: 'group-2', name: 'Group 2', group: true }
114
+ ],
115
+ text: 'Test message',
116
+ attachments: []
117
+ };
118
+ const action = send_broadcast.fromFormData(formData);
119
+ expect(action.contacts).to.have.lengthOf(0);
120
+ expect(action.groups).to.have.lengthOf(2);
121
+ });
122
+ it('converts form data to action correctly with mixed recipients', () => {
123
+ const formData = {
124
+ uuid: 'test-uuid',
125
+ recipients: [
126
+ { uuid: 'contact-1', name: 'Contact 1' },
127
+ { uuid: 'group-1', name: 'Group 1', group: true }
128
+ ],
129
+ text: 'Test message',
130
+ attachments: ['image/jpeg:test.jpg']
131
+ };
132
+ const action = send_broadcast.fromFormData(formData);
133
+ expect(action.contacts).to.have.lengthOf(1);
134
+ expect(action.groups).to.have.lengthOf(1);
135
+ expect(action.attachments).to.deep.equal(['image/jpeg:test.jpg']);
136
+ });
137
+ it('sanitizes text by trimming whitespace', () => {
138
+ const formData = {
139
+ uuid: 'test-uuid',
140
+ recipients: [{ uuid: 'contact-1', name: 'Test Contact' }],
141
+ text: ' Test message \n '
142
+ };
143
+ send_broadcast.sanitize(formData);
144
+ expect(formData.text).to.equal('Test message');
145
+ });
146
+ });
147
+ });
148
+ //# sourceMappingURL=send_broadcast.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send_broadcast.test.js","sourceRoot":"","sources":["../../../test/actions/send_broadcast.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { send_broadcast } from '../../src/flow/actions/send_broadcast';\nimport { SendBroadcast } from '../../src/store/flow-definition';\nimport { ActionTest } from '../ActionHelper';\n\n/**\n * Test suite for the send_broadcast action configuration.\n */\ndescribe('send_broadcast action config', () => {\n const helper = new ActionTest(send_broadcast, 'send_broadcast');\n\n describe('basic properties', () => {\n helper.testBasicProperties();\n\n it('has correct name', () => {\n expect(send_broadcast.name).to.equal('Send Broadcast');\n });\n });\n\n describe('action scenarios', () => {\n helper.testAction(\n {\n uuid: 'test-action-1',\n type: 'send_broadcast',\n text: 'Important announcement for all subscribers!',\n groups: [\n { uuid: 'group-1', name: 'Subscribers' },\n { uuid: 'group-2', name: 'VIP Members' }\n ],\n contacts: []\n } as SendBroadcast,\n 'groups-only'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-2',\n type: 'send_broadcast',\n text: 'Personal message to specific contacts.',\n groups: [],\n contacts: [\n { uuid: 'contact-1', name: 'Alice Johnson' },\n { uuid: 'contact-2', name: 'Bob Smith' }\n ]\n } as SendBroadcast,\n 'contacts-only'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-3',\n type: 'send_broadcast',\n text: 'Urgent update for everyone!',\n groups: [{ uuid: 'group-1', name: 'All Members' }],\n contacts: [{ uuid: 'contact-1', name: 'Admin' }]\n } as SendBroadcast,\n 'groups-and-contacts'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-4',\n type: 'send_broadcast',\n text: 'Multi-line broadcast message.\\n\\nThis is the second paragraph.\\n\\nAnd the third.',\n groups: [{ uuid: 'group-1', name: 'Newsletter Subscribers' }],\n contacts: []\n } as SendBroadcast,\n 'multiline-text'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-5',\n type: 'send_broadcast',\n text: 'Broadcast with attachments',\n groups: [{ uuid: 'group-1', name: 'Members' }],\n contacts: [],\n attachments: [\n 'image/jpeg:https://example.com/photo.jpg',\n 'application/pdf:https://example.com/document.pdf'\n ]\n } as SendBroadcast,\n 'with-attachments'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-6',\n type: 'send_broadcast',\n text: 'Message to many groups',\n groups: [\n { uuid: 'group-1', name: 'Group A' },\n { uuid: 'group-2', name: 'Group B' },\n { uuid: 'group-3', name: 'Group C' },\n { uuid: 'group-4', name: 'Group D' }\n ],\n contacts: []\n } as SendBroadcast,\n 'many-groups'\n );\n });\n\n describe('form data conversion', () => {\n it('converts action to form data correctly', () => {\n const action: SendBroadcast = {\n uuid: 'test-uuid',\n type: 'send_broadcast',\n text: 'Test message',\n groups: [{ uuid: 'group-1', name: 'Test Group' }],\n contacts: [{ uuid: 'contact-1', name: 'Test Contact' }],\n attachments: ['image/jpeg:test.jpg']\n };\n\n const formData = send_broadcast.toFormData(action);\n\n expect(formData.uuid).to.equal('test-uuid');\n expect(formData.text).to.equal('Test message');\n expect(formData.recipients).to.have.lengthOf(2);\n expect(formData.attachments).to.deep.equal(['image/jpeg:test.jpg']);\n });\n\n it('converts form data to action correctly with contacts only', () => {\n const formData = {\n uuid: 'test-uuid',\n recipients: [\n { uuid: 'contact-1', name: 'Contact 1' },\n { uuid: 'contact-2', name: 'Contact 2' }\n ],\n text: 'Test message',\n attachments: []\n };\n\n const action = send_broadcast.fromFormData(formData) as SendBroadcast;\n\n expect(action.uuid).to.equal('test-uuid');\n expect(action.type).to.equal('send_broadcast');\n expect(action.text).to.equal('Test message');\n expect(action.contacts).to.have.lengthOf(2);\n expect(action.groups).to.have.lengthOf(0);\n expect(action.attachments).to.be.undefined;\n });\n\n it('converts form data to action correctly with groups only', () => {\n const formData = {\n uuid: 'test-uuid',\n recipients: [\n { uuid: 'group-1', name: 'Group 1', group: true },\n { uuid: 'group-2', name: 'Group 2', group: true }\n ],\n text: 'Test message',\n attachments: []\n };\n\n const action = send_broadcast.fromFormData(formData) as SendBroadcast;\n\n expect(action.contacts).to.have.lengthOf(0);\n expect(action.groups).to.have.lengthOf(2);\n });\n\n it('converts form data to action correctly with mixed recipients', () => {\n const formData = {\n uuid: 'test-uuid',\n recipients: [\n { uuid: 'contact-1', name: 'Contact 1' },\n { uuid: 'group-1', name: 'Group 1', group: true }\n ],\n text: 'Test message',\n attachments: ['image/jpeg:test.jpg']\n };\n\n const action = send_broadcast.fromFormData(formData) as SendBroadcast;\n\n expect(action.contacts).to.have.lengthOf(1);\n expect(action.groups).to.have.lengthOf(1);\n expect(action.attachments).to.deep.equal(['image/jpeg:test.jpg']);\n });\n\n it('sanitizes text by trimming whitespace', () => {\n const formData = {\n uuid: 'test-uuid',\n recipients: [{ uuid: 'contact-1', name: 'Test Contact' }],\n text: ' Test message \\n '\n };\n\n send_broadcast.sanitize(formData);\n\n expect(formData.text).to.equal('Test message');\n });\n });\n});\n"]}
@@ -80,78 +80,72 @@ describe('send_email action config', () => {
80
80
  });
81
81
  describe('validation edge cases', () => {
82
82
  it('fails validation for empty addresses array', () => {
83
- const action = {
83
+ const formData = {
84
84
  uuid: 'test-action',
85
- type: 'send_email',
86
85
  addresses: [],
87
86
  subject: 'Test Subject',
88
87
  body: 'Test Body'
89
88
  };
90
- const result = send_email.validate(action);
89
+ const result = send_email.validate(formData);
91
90
  expect(result.valid).to.be.false;
92
91
  expect(result.errors.addresses).to.equal('At least one recipient email address is required');
93
92
  });
94
93
  it('fails validation for null addresses', () => {
95
- const action = {
94
+ const formData = {
96
95
  uuid: 'test-action',
97
- type: 'send_email',
98
96
  addresses: null,
99
97
  subject: 'Test Subject',
100
98
  body: 'Test Body'
101
99
  };
102
- const result = send_email.validate(action);
100
+ const result = send_email.validate(formData);
103
101
  expect(result.valid).to.be.false;
104
102
  expect(result.errors.addresses).to.equal('At least one recipient email address is required');
105
103
  });
106
104
  it('fails validation for undefined addresses', () => {
107
- const action = {
105
+ const formData = {
108
106
  uuid: 'test-action',
109
- type: 'send_email',
110
107
  addresses: undefined,
111
108
  subject: 'Test Subject',
112
109
  body: 'Test Body'
113
110
  };
114
- const result = send_email.validate(action);
111
+ const result = send_email.validate(formData);
115
112
  expect(result.valid).to.be.false;
116
113
  expect(result.errors.addresses).to.equal('At least one recipient email address is required');
117
114
  });
118
115
  it('passes validation with valid email addresses', () => {
119
- const action = {
116
+ const formData = {
120
117
  uuid: 'test-action',
121
- type: 'send_email',
122
- addresses: ['valid@example.com'],
118
+ addresses: [{ name: 'valid@example.com', value: 'valid@example.com' }],
123
119
  subject: 'Test Subject',
124
120
  body: 'Test Body'
125
121
  };
126
- const result = send_email.validate(action);
122
+ const result = send_email.validate(formData);
127
123
  expect(result.valid).to.be.true;
128
124
  expect(Object.keys(result.errors)).to.have.length(0);
129
125
  });
130
126
  it('passes validation with multiple email addresses', () => {
131
- const action = {
127
+ const formData = {
132
128
  uuid: 'test-action',
133
- type: 'send_email',
134
129
  addresses: [
135
- 'user1@example.com',
136
- 'user2@example.com',
137
- 'user3@example.com'
130
+ { name: 'user1@example.com', value: 'user1@example.com' },
131
+ { name: 'user2@example.com', value: 'user2@example.com' },
132
+ { name: 'user3@example.com', value: 'user3@example.com' }
138
133
  ],
139
134
  subject: 'Test Subject',
140
135
  body: 'Test Body'
141
136
  };
142
- const result = send_email.validate(action);
137
+ const result = send_email.validate(formData);
143
138
  expect(result.valid).to.be.true;
144
139
  expect(Object.keys(result.errors)).to.have.length(0);
145
140
  });
146
141
  it('passes validation with empty subject and body', () => {
147
- const action = {
142
+ const formData = {
148
143
  uuid: 'test-action',
149
- type: 'send_email',
150
- addresses: ['test@example.com'],
144
+ addresses: [{ name: 'test@example.com', value: 'test@example.com' }],
151
145
  subject: '',
152
146
  body: ''
153
147
  };
154
- const result = send_email.validate(action);
148
+ const result = send_email.validate(formData);
155
149
  expect(result.valid).to.be.true;
156
150
  expect(Object.keys(result.errors)).to.have.length(0);
157
151
  });
@@ -1 +1 @@
1
- {"version":3,"file":"send_email.test.js","sourceRoot":"","sources":["../../../test/actions/send_email.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAExD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAE7B,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;YAC1B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,kBAAkB,CAAC;YAC/B,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,2BAA2B;SACrB,EACd,cAAc,CACf,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE;gBACT,mBAAmB;gBACnB,mBAAmB;gBACnB,mBAAmB;aACpB;YACD,OAAO,EAAE,qBAAqB;YAC9B,IAAI,EAAE,4CAA4C;SACtC,EACd,qBAAqB,CACtB,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,mBAAmB,CAAC;YAChC,OAAO,EAAE,0BAA0B;YACnC,IAAI,EAAE,+HAA+H;SACzH,EACd,gBAAgB,CACjB,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,qBAAqB,CAAC;YAClC,OAAO,EAAE,wBAAwB;YACjC,IAAI,EAAE,4FAA4F;SACtF,EACd,kBAAkB,CACnB,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,0BAA0B,CAAC;YACvC,OAAO,EACL,0GAA0G;YAC5G,IAAI,EAAE,qBAAqB;SACf,EACd,cAAc,CACf,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE;gBACT,yCAAyC;gBACzC,0CAA0C;gBAC1C,0CAA0C;aAC3C;YACD,OAAO,EAAE,6BAA6B;YACtC,IAAI,EAAE,4MAA4M;SACtM,EACd,wBAAwB,CACzB,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,oBAAoB,CAAC;YACjC,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,0BAA0B;SACpB,EACd,eAAe,CAChB,CAAC;QAEF,MAAM,CAAC,UAAU,CACf;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC,kBAAkB,CAAC;YAC/B,OAAO,EAAE,iBAAiB;YAC1B,IAAI,EAAE,EAAE;SACI,EACd,YAAY,CACb,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,EAAE;gBACb,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CACtC,kDAAkD,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,IAAW;gBACtB,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CACtC,kDAAkD,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,SAAgB;gBAC3B,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CACtC,kDAAkD,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,CAAC,mBAAmB,CAAC;gBAChC,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE;oBACT,mBAAmB;oBACnB,mBAAmB;oBACnB,mBAAmB;iBACpB;gBACD,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,MAAM,GAAc;gBACxB,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,CAAC,kBAAkB,CAAC;gBAC/B,OAAO,EAAE,EAAE;gBACX,IAAI,EAAE,EAAE;aACT,CAAC;YAEF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { send_email } from '../../src/flow/actions/send_email';\nimport { SendEmail } from '../../src/store/flow-definition';\nimport { ActionTest } from '../ActionHelper';\n\n/**\n * Test suite for the send_email action configuration.\n */\ndescribe('send_email action config', () => {\n const helper = new ActionTest(send_email, 'send_email');\n\n describe('basic properties', () => {\n helper.testBasicProperties();\n\n it('has correct name', () => {\n expect(send_email.name).to.equal('Send Email');\n });\n });\n\n describe('action scenarios', () => {\n helper.testAction(\n {\n uuid: 'test-action-1',\n type: 'send_email',\n addresses: ['user@example.com'],\n subject: 'Welcome!',\n body: 'Thank you for signing up.'\n } as SendEmail,\n 'simple-email'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-2',\n type: 'send_email',\n addresses: [\n 'user1@example.com',\n 'user2@example.com',\n 'user3@example.com'\n ],\n subject: 'Multiple Recipients',\n body: 'This email is sent to multiple recipients.'\n } as SendEmail,\n 'multiple-recipients'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-3',\n type: 'send_email',\n addresses: ['admin@company.com'],\n subject: 'Multi-line Email Content',\n body: 'Dear User,\\n\\nThis is a multi-line email body.\\n\\nIt contains multiple paragraphs and line breaks.\\n\\nBest regards,\\nThe Team'\n } as SendEmail,\n 'multiline-body'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-4',\n type: 'send_email',\n addresses: ['support@company.com'],\n subject: 'Email with expressions',\n body: 'Hello @contact.name,\\n\\nYour order @run.results.order_id has been processed.\\n\\nThank you!'\n } as SendEmail,\n 'with-expressions'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-5',\n type: 'send_email',\n addresses: ['notification@company.com'],\n subject:\n 'Very Long Subject Line That Could Potentially Exceed Normal Length Limits To Test Subject Field Handling',\n body: 'Short body content.'\n } as SendEmail,\n 'long-subject'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-6',\n type: 'send_email',\n addresses: [\n 'customer.service@department.company.com',\n 'technical.support@department.company.com',\n 'billing.inquiries@department.company.com'\n ],\n subject: 'Customer Support Escalation',\n body: 'Customer Name: @contact.name\\nTicket ID: @run.results.ticket_id\\n\\nIssue Description:\\n@run.results.issue_description\\n\\nPriority: High\\nCategory: @run.results.category\\n\\nPlease respond within 2 hours.'\n } as SendEmail,\n 'complex-business-email'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-7',\n type: 'send_email',\n addresses: ['alerts@company.com'],\n subject: '',\n body: 'Email with empty subject'\n } as SendEmail,\n 'empty-subject'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-8',\n type: 'send_email',\n addresses: ['test@company.com'],\n subject: 'Empty body test',\n body: ''\n } as SendEmail,\n 'empty-body'\n );\n });\n\n describe('validation edge cases', () => {\n it('fails validation for empty addresses array', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: [],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('fails validation for null addresses', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: null as any,\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('fails validation for undefined addresses', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: undefined as any,\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('passes validation with valid email addresses', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: ['valid@example.com'],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n\n it('passes validation with multiple email addresses', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: [\n 'user1@example.com',\n 'user2@example.com',\n 'user3@example.com'\n ],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n\n it('passes validation with empty subject and body', () => {\n const action: SendEmail = {\n uuid: 'test-action',\n type: 'send_email',\n addresses: ['test@example.com'],\n subject: '',\n body: ''\n };\n\n const result = send_email.validate(action);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n });\n});\n"]}
1
+ {"version":3,"file":"send_email.test.js","sourceRoot":"","sources":["../../../test/actions/send_email.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { send_email } from '../../src/flow/actions/send_email';\nimport { SendEmail } from '../../src/store/flow-definition';\nimport { ActionTest } from '../ActionHelper';\n\n/**\n * Test suite for the send_email action configuration.\n */\ndescribe('send_email action config', () => {\n const helper = new ActionTest(send_email, 'send_email');\n\n describe('basic properties', () => {\n helper.testBasicProperties();\n\n it('has correct name', () => {\n expect(send_email.name).to.equal('Send Email');\n });\n });\n\n describe('action scenarios', () => {\n helper.testAction(\n {\n uuid: 'test-action-1',\n type: 'send_email',\n addresses: ['user@example.com'],\n subject: 'Welcome!',\n body: 'Thank you for signing up.'\n } as SendEmail,\n 'simple-email'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-2',\n type: 'send_email',\n addresses: [\n 'user1@example.com',\n 'user2@example.com',\n 'user3@example.com'\n ],\n subject: 'Multiple Recipients',\n body: 'This email is sent to multiple recipients.'\n } as SendEmail,\n 'multiple-recipients'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-3',\n type: 'send_email',\n addresses: ['admin@company.com'],\n subject: 'Multi-line Email Content',\n body: 'Dear User,\\n\\nThis is a multi-line email body.\\n\\nIt contains multiple paragraphs and line breaks.\\n\\nBest regards,\\nThe Team'\n } as SendEmail,\n 'multiline-body'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-4',\n type: 'send_email',\n addresses: ['support@company.com'],\n subject: 'Email with expressions',\n body: 'Hello @contact.name,\\n\\nYour order @run.results.order_id has been processed.\\n\\nThank you!'\n } as SendEmail,\n 'with-expressions'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-5',\n type: 'send_email',\n addresses: ['notification@company.com'],\n subject:\n 'Very Long Subject Line That Could Potentially Exceed Normal Length Limits To Test Subject Field Handling',\n body: 'Short body content.'\n } as SendEmail,\n 'long-subject'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-6',\n type: 'send_email',\n addresses: [\n 'customer.service@department.company.com',\n 'technical.support@department.company.com',\n 'billing.inquiries@department.company.com'\n ],\n subject: 'Customer Support Escalation',\n body: 'Customer Name: @contact.name\\nTicket ID: @run.results.ticket_id\\n\\nIssue Description:\\n@run.results.issue_description\\n\\nPriority: High\\nCategory: @run.results.category\\n\\nPlease respond within 2 hours.'\n } as SendEmail,\n 'complex-business-email'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-7',\n type: 'send_email',\n addresses: ['alerts@company.com'],\n subject: '',\n body: 'Email with empty subject'\n } as SendEmail,\n 'empty-subject'\n );\n\n helper.testAction(\n {\n uuid: 'test-action-8',\n type: 'send_email',\n addresses: ['test@company.com'],\n subject: 'Empty body test',\n body: ''\n } as SendEmail,\n 'empty-body'\n );\n });\n\n describe('validation edge cases', () => {\n it('fails validation for empty addresses array', () => {\n const formData = {\n uuid: 'test-action',\n addresses: [],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('fails validation for null addresses', () => {\n const formData = {\n uuid: 'test-action',\n addresses: null as any,\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('fails validation for undefined addresses', () => {\n const formData = {\n uuid: 'test-action',\n addresses: undefined as any,\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.false;\n expect(result.errors.addresses).to.equal(\n 'At least one recipient email address is required'\n );\n });\n\n it('passes validation with valid email addresses', () => {\n const formData = {\n uuid: 'test-action',\n addresses: [{ name: 'valid@example.com', value: 'valid@example.com' }],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n\n it('passes validation with multiple email addresses', () => {\n const formData = {\n uuid: 'test-action',\n addresses: [\n { name: 'user1@example.com', value: 'user1@example.com' },\n { name: 'user2@example.com', value: 'user2@example.com' },\n { name: 'user3@example.com', value: 'user3@example.com' }\n ],\n subject: 'Test Subject',\n body: 'Test Body'\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n\n it('passes validation with empty subject and body', () => {\n const formData = {\n uuid: 'test-action',\n addresses: [{ name: 'test@example.com', value: 'test@example.com' }],\n subject: '',\n body: ''\n };\n\n const result = send_email.validate(formData);\n expect(result.valid).to.be.true;\n expect(Object.keys(result.errors)).to.have.length(0);\n });\n });\n});\n"]}
@@ -68,27 +68,45 @@ describe('send_msg action config', () => {
68
68
  }, 'text-without-quick-replies');
69
69
  });
70
70
  describe('validation edge cases', () => {
71
- it('fails validation for empty text', () => {
72
- const action = {
71
+ it('passes validation with valid text', () => {
72
+ const formData = {
73
73
  uuid: 'test-action',
74
- type: 'send_msg',
75
- text: '',
76
- quick_replies: []
74
+ text: 'Hello world',
75
+ attachments: [],
76
+ runtime_attachments: []
77
77
  };
78
- const result = send_msg.validate(action);
79
- expect(result.valid).to.be.false;
80
- expect(result.errors.text).to.equal('Message text is required');
78
+ const result = send_msg.validate(formData);
79
+ expect(result.valid).to.be.true;
80
+ expect(Object.keys(result.errors)).to.have.length(0);
81
81
  });
82
- it('fails validation for whitespace-only text', () => {
83
- const action = {
82
+ it('fails validation when total attachments exceed 10', () => {
83
+ const formData = {
84
84
  uuid: 'test-action',
85
- type: 'send_msg',
86
- text: ' \n\t ',
87
- quick_replies: []
85
+ text: 'Hello world',
86
+ attachments: Array(6).fill('image/jpeg:http://example.com/image.jpg'),
87
+ runtime_attachments: Array(5).fill({
88
+ type: [{ name: 'Image', value: 'image' }],
89
+ expression: '@contact.photo'
90
+ })
88
91
  };
89
- const result = send_msg.validate(action);
92
+ const result = send_msg.validate(formData);
90
93
  expect(result.valid).to.be.false;
91
- expect(result.errors.text).to.equal('Message text is required');
94
+ expect(result.errors.text).to.equal('Each message can only have up to 10 total attachments');
95
+ expect(result.errors.runtime_attachments).to.equal('Each message can only have up to 10 attachments');
96
+ });
97
+ it('passes validation with exactly 10 attachments', () => {
98
+ const formData = {
99
+ uuid: 'test-action',
100
+ text: 'Hello world',
101
+ attachments: Array(5).fill('image/jpeg:http://example.com/image.jpg'),
102
+ runtime_attachments: Array(5).fill({
103
+ type: [{ name: 'Image', value: 'image' }],
104
+ expression: '@contact.photo'
105
+ })
106
+ };
107
+ const result = send_msg.validate(formData);
108
+ expect(result.valid).to.be.true;
109
+ expect(Object.keys(result.errors)).to.have.length(0);
92
110
  });
93
111
  });
94
112
  });