@nyaruka/temba-components 0.122.0 → 0.124.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 (262) hide show
  1. package/.github/copilot-instructions.md +181 -0
  2. package/.github/workflows/build.yml +3 -3
  3. package/.github/workflows/cla.yml +6 -6
  4. package/.github/workflows/copilot-setup-steps.yml +86 -0
  5. package/CHANGELOG.md +44 -0
  6. package/demo/drag-drop-demo.html +141 -0
  7. package/demo/index.html +57 -0
  8. package/demo/test-drag-drop.html +94 -0
  9. package/dist/locales/es.js +1 -0
  10. package/dist/locales/es.js.map +1 -1
  11. package/dist/locales/fr.js +1 -0
  12. package/dist/locales/fr.js.map +1 -1
  13. package/dist/locales/pt.js +1 -0
  14. package/dist/locales/pt.js.map +1 -1
  15. package/dist/temba-components.js +366 -247
  16. package/dist/temba-components.js.map +1 -1
  17. package/out-tsc/src/chart/TembaChart.js +81 -14
  18. package/out-tsc/src/chart/TembaChart.js.map +1 -1
  19. package/out-tsc/src/fields/FieldManager.js +27 -34
  20. package/out-tsc/src/fields/FieldManager.js.map +1 -1
  21. package/out-tsc/src/list/RunList.js +13 -8
  22. package/out-tsc/src/list/RunList.js.map +1 -1
  23. package/out-tsc/src/list/SortableList.js +257 -60
  24. package/out-tsc/src/list/SortableList.js.map +1 -1
  25. package/out-tsc/src/locales/es.js +1 -0
  26. package/out-tsc/src/locales/es.js.map +1 -1
  27. package/out-tsc/src/locales/fr.js +1 -0
  28. package/out-tsc/src/locales/fr.js.map +1 -1
  29. package/out-tsc/src/locales/pt.js +1 -0
  30. package/out-tsc/src/locales/pt.js.map +1 -1
  31. package/out-tsc/src/omnibox/Omnibox.js +1 -1
  32. package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
  33. package/out-tsc/src/options/Options.js +36 -13
  34. package/out-tsc/src/options/Options.js.map +1 -1
  35. package/out-tsc/src/select/Select.js +226 -43
  36. package/out-tsc/src/select/Select.js.map +1 -1
  37. package/out-tsc/src/store/AppState.js +3 -3
  38. package/out-tsc/src/store/AppState.js.map +1 -1
  39. package/out-tsc/src/utils/index.js +6 -1
  40. package/out-tsc/src/utils/index.js.map +1 -1
  41. package/out-tsc/src/vectoricon/VectorIcon.js +2 -1
  42. package/out-tsc/src/vectoricon/VectorIcon.js.map +1 -1
  43. package/out-tsc/src/webchat/WebChat.js +5 -2
  44. package/out-tsc/src/webchat/WebChat.js.map +1 -1
  45. package/out-tsc/temba-modules.js +0 -2
  46. package/out-tsc/temba-modules.js.map +1 -1
  47. package/out-tsc/test/temba-appstate-language.test.js +176 -0
  48. package/out-tsc/test/temba-appstate-language.test.js.map +1 -0
  49. package/out-tsc/test/temba-chart.test.js +125 -0
  50. package/out-tsc/test/temba-chart.test.js.map +1 -1
  51. package/out-tsc/test/temba-dropdown.test.js +317 -0
  52. package/out-tsc/test/temba-dropdown.test.js.map +1 -0
  53. package/out-tsc/test/temba-flow-editor-node.test.js +273 -0
  54. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -0
  55. package/out-tsc/test/temba-flow-editor.test.js +244 -0
  56. package/out-tsc/test/temba-flow-editor.test.js.map +1 -0
  57. package/out-tsc/test/temba-flow-plumber.test.js +145 -0
  58. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -0
  59. package/out-tsc/test/temba-flow-render.test.js +171 -0
  60. package/out-tsc/test/temba-flow-render.test.js.map +1 -0
  61. package/out-tsc/test/temba-omnibox.test.js +2 -3
  62. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  63. package/out-tsc/test/temba-run-list.test.js +588 -0
  64. package/out-tsc/test/temba-run-list.test.js.map +1 -0
  65. package/out-tsc/test/temba-select.test.js +149 -52
  66. package/out-tsc/test/temba-select.test.js.map +1 -1
  67. package/out-tsc/test/temba-sortable-list.test.js +91 -15
  68. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  69. package/out-tsc/test/temba-toast.test.js +299 -0
  70. package/out-tsc/test/temba-toast.test.js.map +1 -0
  71. package/out-tsc/test/temba-utils-index.test.js +1178 -0
  72. package/out-tsc/test/temba-utils-index.test.js.map +1 -0
  73. package/out-tsc/test/temba-webchat-lightbox-fix.test.js +42 -0
  74. package/out-tsc/test/temba-webchat-lightbox-fix.test.js.map +1 -0
  75. package/out-tsc/test/temba-webchat.test.js +816 -0
  76. package/out-tsc/test/temba-webchat.test.js.map +1 -0
  77. package/out-tsc/test/utils.test.js +33 -1
  78. package/out-tsc/test/utils.test.js.map +1 -1
  79. package/package.json +6 -8
  80. package/screenshots/truth/alert/error.png +0 -0
  81. package/screenshots/truth/alert/info.png +0 -0
  82. package/screenshots/truth/alert/warning.png +0 -0
  83. package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
  84. package/screenshots/truth/checkbox/checked.png +0 -0
  85. package/screenshots/truth/checkbox/default.png +0 -0
  86. package/screenshots/truth/colorpicker/default.png +0 -0
  87. package/screenshots/truth/colorpicker/focused.png +0 -0
  88. package/screenshots/truth/colorpicker/initialized.png +0 -0
  89. package/screenshots/truth/colorpicker/selected.png +0 -0
  90. package/screenshots/truth/compose/attachments-tab.png +0 -0
  91. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  92. package/screenshots/truth/compose/attachments-with-files.png +0 -0
  93. package/screenshots/truth/compose/intial-text.png +0 -0
  94. package/screenshots/truth/compose/no-counter.png +0 -0
  95. package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
  96. package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
  97. package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
  98. package/screenshots/truth/contacts/badges.png +0 -0
  99. package/screenshots/truth/contacts/chat-failure.png +0 -0
  100. package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
  101. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  102. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  103. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  104. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  105. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  106. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  107. package/screenshots/truth/content-menu/button-no-items.png +0 -0
  108. package/screenshots/truth/content-menu/items-and-buttons.png +0 -0
  109. package/screenshots/truth/counter/summary.png +0 -0
  110. package/screenshots/truth/counter/text.png +0 -0
  111. package/screenshots/truth/counter/unicode-variables.png +0 -0
  112. package/screenshots/truth/counter/unicode.png +0 -0
  113. package/screenshots/truth/counter/variable.png +0 -0
  114. package/screenshots/truth/date/date-inline.png +0 -0
  115. package/screenshots/truth/date/date.png +0 -0
  116. package/screenshots/truth/date/datetime.png +0 -0
  117. package/screenshots/truth/date/duration.png +0 -0
  118. package/screenshots/truth/date/timedate.png +0 -0
  119. package/screenshots/truth/datepicker/date-truncated-time.png +0 -0
  120. package/screenshots/truth/datepicker/date.png +0 -0
  121. package/screenshots/truth/datepicker/initial-timezone.png +0 -0
  122. package/screenshots/truth/datepicker/updated-keyboard-date.png +0 -0
  123. package/screenshots/truth/dialog/focused.png +0 -0
  124. package/screenshots/truth/dropdown/after-blur.png +0 -0
  125. package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
  126. package/screenshots/truth/dropdown/custom-arrow-size.png +0 -0
  127. package/screenshots/truth/dropdown/default.png +0 -0
  128. package/screenshots/truth/dropdown/narrow-toggle.png +0 -0
  129. package/screenshots/truth/dropdown/no-mask.png +0 -0
  130. package/screenshots/truth/dropdown/opened.png +0 -0
  131. package/screenshots/truth/dropdown/positioned.png +0 -0
  132. package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
  133. package/screenshots/truth/dropdown/with-mask.png +0 -0
  134. package/screenshots/truth/flow/editor-basic.png +0 -0
  135. package/screenshots/truth/label/custom.png +0 -0
  136. package/screenshots/truth/label/danger.png +0 -0
  137. package/screenshots/truth/label/dark.png +0 -0
  138. package/screenshots/truth/label/default-icon.png +0 -0
  139. package/screenshots/truth/label/no-icon.png +0 -0
  140. package/screenshots/truth/label/primary.png +0 -0
  141. package/screenshots/truth/label/secondary.png +0 -0
  142. package/screenshots/truth/label/shadow.png +0 -0
  143. package/screenshots/truth/label/tertiary.png +0 -0
  144. package/screenshots/truth/lightbox/img-zoomed.png +0 -0
  145. package/screenshots/truth/list/fields-dragging.png +0 -0
  146. package/screenshots/truth/list/fields-filtered.png +0 -0
  147. package/screenshots/truth/list/fields-hovered.png +0 -0
  148. package/screenshots/truth/list/fields.png +0 -0
  149. package/screenshots/truth/list/items-selected.png +0 -0
  150. package/screenshots/truth/list/items-updated.png +0 -0
  151. package/screenshots/truth/list/items.png +0 -0
  152. package/screenshots/truth/list/sortable-dragging.png +0 -0
  153. package/screenshots/truth/list/sortable-dropped.png +0 -0
  154. package/screenshots/truth/list/sortable.png +0 -0
  155. package/screenshots/truth/menu/menu-focused-with items.png +0 -0
  156. package/screenshots/truth/menu/menu-refresh-1.png +0 -0
  157. package/screenshots/truth/menu/menu-refresh-2.png +0 -0
  158. package/screenshots/truth/menu/menu-root.png +0 -0
  159. package/screenshots/truth/menu/menu-submenu.png +0 -0
  160. package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
  161. package/screenshots/truth/menu/menu-tasks.png +0 -0
  162. package/screenshots/truth/modax/form.png +0 -0
  163. package/screenshots/truth/modax/simple.png +0 -0
  164. package/screenshots/truth/omnibox/selected.png +0 -0
  165. package/screenshots/truth/options/block.png +0 -0
  166. package/screenshots/truth/run-list/basic.png +0 -0
  167. package/screenshots/truth/select/disabled-multi-selection.png +0 -0
  168. package/screenshots/truth/select/disabled-selection.png +0 -0
  169. package/screenshots/truth/select/disabled.png +0 -0
  170. package/screenshots/truth/select/embedded.png +0 -0
  171. package/screenshots/truth/select/empty-options.png +0 -0
  172. package/screenshots/truth/select/expression-selected.png +0 -0
  173. package/screenshots/truth/select/expressions.png +0 -0
  174. package/screenshots/truth/select/functions.png +0 -0
  175. package/screenshots/truth/select/local-options.png +0 -0
  176. package/screenshots/truth/select/multi-reorder-final.png +0 -0
  177. package/screenshots/truth/select/multi-reorder-initial.png +0 -0
  178. package/screenshots/truth/select/multi-with-endpoint.png +0 -0
  179. package/screenshots/truth/select/multiple-initial-values.png +0 -0
  180. package/screenshots/truth/select/remote-options.png +0 -0
  181. package/screenshots/truth/select/search-enabled.png +0 -0
  182. package/screenshots/truth/select/search-multi-no-matches.png +0 -0
  183. package/screenshots/truth/select/search-selected-focus.png +0 -0
  184. package/screenshots/truth/select/search-selected.png +0 -0
  185. package/screenshots/truth/select/search-with-selected.png +0 -0
  186. package/screenshots/truth/select/searching.png +0 -0
  187. package/screenshots/truth/select/selected-multi-maxitems-reached.png +0 -0
  188. package/screenshots/truth/select/selected-multi.png +0 -0
  189. package/screenshots/truth/select/selected-single.png +0 -0
  190. package/screenshots/truth/select/selection-clearable.png +0 -0
  191. package/screenshots/truth/select/static-initial-value.png +0 -0
  192. package/screenshots/truth/select/static-initial-via-selected.png +0 -0
  193. package/screenshots/truth/select/truncated-selection.png +0 -0
  194. package/screenshots/truth/select/with-placeholder.png +0 -0
  195. package/screenshots/truth/select/without-placeholder.png +0 -0
  196. package/screenshots/truth/slider/custom-min-custom-max-valid-value.png +0 -0
  197. package/screenshots/truth/slider/custom-min-default-max-no-value.png +0 -0
  198. package/screenshots/truth/slider/default-min-custom-max-no-value.png +0 -0
  199. package/screenshots/truth/slider/default-min-default-max-invalid-value.png +0 -0
  200. package/screenshots/truth/slider/default-min-default-max-valid-value.png +0 -0
  201. package/screenshots/truth/slider/update-slider-on-value-change.png +0 -0
  202. package/screenshots/truth/templates/default.png +0 -0
  203. package/screenshots/truth/templates/unapproved.png +0 -0
  204. package/screenshots/truth/textinput/input-disabled.png +0 -0
  205. package/screenshots/truth/textinput/input-focused.png +0 -0
  206. package/screenshots/truth/textinput/input-form.png +0 -0
  207. package/screenshots/truth/textinput/input-inserted.png +0 -0
  208. package/screenshots/truth/textinput/input-placeholder.png +0 -0
  209. package/screenshots/truth/textinput/input-updated.png +0 -0
  210. package/screenshots/truth/textinput/input.png +0 -0
  211. package/screenshots/truth/textinput/textarea-focused.png +0 -0
  212. package/screenshots/truth/textinput/textarea.png +0 -0
  213. package/screenshots/truth/tip/bottom.png +0 -0
  214. package/screenshots/truth/tip/left.png +0 -0
  215. package/screenshots/truth/tip/right.png +0 -0
  216. package/screenshots/truth/tip/top.png +0 -0
  217. package/screenshots/truth/webchat/closed-widget.png +0 -0
  218. package/screenshots/truth/webchat/connected-state.png +0 -0
  219. package/screenshots/truth/webchat/connecting-state.png +0 -0
  220. package/screenshots/truth/webchat/disconnected-state.png +0 -0
  221. package/screenshots/truth/webchat/opened-widget.png +0 -0
  222. package/src/chart/TembaChart.ts +86 -15
  223. package/src/fields/FieldManager.ts +30 -38
  224. package/src/list/RunList.ts +11 -8
  225. package/src/list/SortableList.ts +291 -67
  226. package/src/locales/es.ts +1 -0
  227. package/src/locales/fr.ts +1 -0
  228. package/src/locales/pt.ts +1 -0
  229. package/src/omnibox/Omnibox.ts +1 -1
  230. package/src/options/Options.ts +38 -13
  231. package/src/select/Select.ts +245 -47
  232. package/src/store/AppState.ts +3 -3
  233. package/src/utils/index.ts +17 -5
  234. package/src/vectoricon/VectorIcon.ts +2 -1
  235. package/src/webchat/WebChat.ts +5 -2
  236. package/temba-modules.ts +0 -2
  237. package/test/temba-appstate-language.test.ts +218 -0
  238. package/test/temba-chart.test.ts +161 -1
  239. package/test/temba-dropdown.test.ts +444 -0
  240. package/test/temba-flow-editor-node.test.ts +344 -0
  241. package/test/temba-flow-editor.test.ts +301 -0
  242. package/test/temba-flow-plumber.test.ts +189 -0
  243. package/test/temba-flow-render.test.ts +220 -0
  244. package/test/temba-omnibox.test.ts +2 -3
  245. package/test/temba-run-list.test.ts +774 -0
  246. package/test/temba-select.test.ts +206 -78
  247. package/test/temba-sortable-list.test.ts +108 -15
  248. package/test/temba-toast.test.ts +386 -0
  249. package/test/temba-utils-index.test.ts +1547 -0
  250. package/test/temba-webchat-lightbox-fix.test.ts +57 -0
  251. package/test/temba-webchat.test.ts +1095 -0
  252. package/test/utils.test.ts +56 -2
  253. package/test-assets/list/flow-results.json +17 -0
  254. package/test-assets/list/runs.json +126 -0
  255. package/test-assets/style.css +23 -0
  256. package/web-test-runner.config.mjs +33 -7
  257. package/xliff/es.xlf +3 -0
  258. package/xliff/fr.xlf +3 -0
  259. package/xliff/pt.xlf +3 -0
  260. package/out-tsc/src/outboxmonitor/OutboxMonitor.js +0 -136
  261. package/out-tsc/src/outboxmonitor/OutboxMonitor.js.map +0 -1
  262. package/src/outboxmonitor/OutboxMonitor.ts +0 -148
@@ -0,0 +1,176 @@
1
+ import { assert } from '@open-wc/testing';
2
+ import { zustand } from '../src/store/AppState';
3
+ describe('AppState Language Reset', () => {
4
+ beforeEach(() => {
5
+ // Reset the store state before each test
6
+ const state = zustand.getState();
7
+ zustand.setState({
8
+ ...state,
9
+ languageCode: '',
10
+ isTranslating: false,
11
+ flowDefinition: null,
12
+ flowInfo: null
13
+ });
14
+ });
15
+ it('should reset language when loading a new flow', () => {
16
+ const state = zustand.getState();
17
+ // First, load an initial flow to establish state
18
+ const initialFlowContents = {
19
+ definition: {
20
+ language: 'en',
21
+ localization: {},
22
+ name: 'Initial Flow',
23
+ nodes: [],
24
+ uuid: 'initial-uuid',
25
+ type: 'messaging',
26
+ revision: 1,
27
+ spec_version: '14.3',
28
+ _ui: {
29
+ nodes: {},
30
+ languages: []
31
+ }
32
+ },
33
+ info: {
34
+ results: [],
35
+ dependencies: [],
36
+ counts: { nodes: 0, languages: 1 },
37
+ locals: []
38
+ }
39
+ };
40
+ state.setFlowContents(initialFlowContents);
41
+ // Simulate having a previous flow with localization
42
+ state.setLanguageCode('es'); // User selected Spanish for localization
43
+ assert.equal(zustand.getState().languageCode, 'es');
44
+ assert.equal(zustand.getState().isTranslating, true); // Now translating from English to Spanish
45
+ // Simulate loading a new flow with English as default
46
+ const mockFlowContents = {
47
+ definition: {
48
+ language: 'en',
49
+ localization: {},
50
+ name: 'Test Flow',
51
+ nodes: [],
52
+ uuid: 'test-uuid',
53
+ type: 'messaging',
54
+ revision: 1,
55
+ spec_version: '14.3',
56
+ _ui: {
57
+ nodes: {},
58
+ languages: []
59
+ }
60
+ },
61
+ info: {
62
+ results: [],
63
+ dependencies: [],
64
+ counts: { nodes: 0, languages: 1 },
65
+ locals: []
66
+ }
67
+ };
68
+ state.setFlowContents(mockFlowContents);
69
+ // The language should reset to the flow's default language
70
+ assert.equal(zustand.getState().languageCode, 'en', 'Language should reset to flow default');
71
+ assert.equal(zustand.getState().isTranslating, false, 'Should not be in translation mode');
72
+ });
73
+ it('should set isTranslating correctly when languages differ', () => {
74
+ const state = zustand.getState();
75
+ // Load a flow with Spanish as default
76
+ const mockFlowContents = {
77
+ definition: {
78
+ language: 'es',
79
+ localization: {},
80
+ name: 'Test Flow',
81
+ nodes: [],
82
+ uuid: 'test-uuid',
83
+ type: 'messaging',
84
+ revision: 1,
85
+ spec_version: '14.3',
86
+ _ui: {
87
+ nodes: {},
88
+ languages: []
89
+ }
90
+ },
91
+ info: {
92
+ results: [],
93
+ dependencies: [],
94
+ counts: { nodes: 0, languages: 1 },
95
+ locals: []
96
+ }
97
+ };
98
+ state.setFlowContents(mockFlowContents);
99
+ // Should be in Spanish and not translating
100
+ assert.equal(zustand.getState().languageCode, 'es');
101
+ assert.equal(zustand.getState().isTranslating, false);
102
+ // Now switch to English for localization
103
+ state.setLanguageCode('en');
104
+ assert.equal(zustand.getState().languageCode, 'en');
105
+ assert.equal(zustand.getState().isTranslating, true, 'Should be translating when language differs from flow default');
106
+ });
107
+ it('should preserve flow default language when no previous language is set', () => {
108
+ const state = zustand.getState();
109
+ // Load a flow with French as default, no previous language set
110
+ const mockFlowContents = {
111
+ definition: {
112
+ language: 'fr',
113
+ localization: {},
114
+ name: 'Test Flow',
115
+ nodes: [],
116
+ uuid: 'test-uuid',
117
+ type: 'messaging',
118
+ revision: 1,
119
+ spec_version: '14.3',
120
+ _ui: {
121
+ nodes: {},
122
+ languages: []
123
+ }
124
+ },
125
+ info: {
126
+ results: [],
127
+ dependencies: [],
128
+ counts: { nodes: 0, languages: 1 },
129
+ locals: []
130
+ }
131
+ };
132
+ state.setFlowContents(mockFlowContents);
133
+ // Should use the flow's default language
134
+ assert.equal(zustand.getState().languageCode, 'fr', 'Should use flow default language');
135
+ assert.equal(zustand.getState().isTranslating, false, 'Should not be translating');
136
+ });
137
+ it('should handle language switching after flow is loaded', () => {
138
+ const state = zustand.getState();
139
+ // Load a flow with English as default
140
+ const mockFlowContents = {
141
+ definition: {
142
+ language: 'en',
143
+ localization: {},
144
+ name: 'Test Flow',
145
+ nodes: [],
146
+ uuid: 'test-uuid',
147
+ type: 'messaging',
148
+ revision: 1,
149
+ spec_version: '14.3',
150
+ _ui: {
151
+ nodes: {},
152
+ languages: []
153
+ }
154
+ },
155
+ info: {
156
+ results: [],
157
+ dependencies: [],
158
+ counts: { nodes: 0, languages: 1 },
159
+ locals: []
160
+ }
161
+ };
162
+ state.setFlowContents(mockFlowContents);
163
+ // Should start in English, not translating
164
+ assert.equal(zustand.getState().languageCode, 'en');
165
+ assert.equal(zustand.getState().isTranslating, false);
166
+ // Switch to Spanish for localization
167
+ state.setLanguageCode('es');
168
+ assert.equal(zustand.getState().languageCode, 'es');
169
+ assert.equal(zustand.getState().isTranslating, true);
170
+ // Switch back to English
171
+ state.setLanguageCode('en');
172
+ assert.equal(zustand.getState().languageCode, 'en');
173
+ assert.equal(zustand.getState().isTranslating, false);
174
+ });
175
+ });
176
+ //# sourceMappingURL=temba-appstate-language.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temba-appstate-language.test.js","sourceRoot":"","sources":["../../test/temba-appstate-language.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from '@open-wc/testing';\nimport { zustand } from '../src/store/AppState';\n\ndescribe('AppState Language Reset', () => {\n beforeEach(() => {\n // Reset the store state before each test\n const state = zustand.getState();\n zustand.setState({\n ...state,\n languageCode: '',\n isTranslating: false,\n flowDefinition: null,\n flowInfo: null\n });\n });\n\n it('should reset language when loading a new flow', () => {\n const state = zustand.getState();\n\n // First, load an initial flow to establish state\n const initialFlowContents = {\n definition: {\n language: 'en',\n localization: {},\n name: 'Initial Flow',\n nodes: [],\n uuid: 'initial-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {},\n languages: []\n }\n },\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 0, languages: 1 },\n locals: []\n }\n };\n\n state.setFlowContents(initialFlowContents);\n\n // Simulate having a previous flow with localization\n state.setLanguageCode('es'); // User selected Spanish for localization\n assert.equal(zustand.getState().languageCode, 'es');\n assert.equal(zustand.getState().isTranslating, true); // Now translating from English to Spanish\n\n // Simulate loading a new flow with English as default\n const mockFlowContents = {\n definition: {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {},\n languages: []\n }\n },\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 0, languages: 1 },\n locals: []\n }\n };\n\n state.setFlowContents(mockFlowContents);\n\n // The language should reset to the flow's default language\n assert.equal(\n zustand.getState().languageCode,\n 'en',\n 'Language should reset to flow default'\n );\n assert.equal(\n zustand.getState().isTranslating,\n false,\n 'Should not be in translation mode'\n );\n });\n\n it('should set isTranslating correctly when languages differ', () => {\n const state = zustand.getState();\n\n // Load a flow with Spanish as default\n const mockFlowContents = {\n definition: {\n language: 'es',\n localization: {},\n name: 'Test Flow',\n nodes: [],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {},\n languages: []\n }\n },\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 0, languages: 1 },\n locals: []\n }\n };\n\n state.setFlowContents(mockFlowContents);\n\n // Should be in Spanish and not translating\n assert.equal(zustand.getState().languageCode, 'es');\n assert.equal(zustand.getState().isTranslating, false);\n\n // Now switch to English for localization\n state.setLanguageCode('en');\n assert.equal(zustand.getState().languageCode, 'en');\n assert.equal(\n zustand.getState().isTranslating,\n true,\n 'Should be translating when language differs from flow default'\n );\n });\n\n it('should preserve flow default language when no previous language is set', () => {\n const state = zustand.getState();\n\n // Load a flow with French as default, no previous language set\n const mockFlowContents = {\n definition: {\n language: 'fr',\n localization: {},\n name: 'Test Flow',\n nodes: [],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {},\n languages: []\n }\n },\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 0, languages: 1 },\n locals: []\n }\n };\n\n state.setFlowContents(mockFlowContents);\n\n // Should use the flow's default language\n assert.equal(\n zustand.getState().languageCode,\n 'fr',\n 'Should use flow default language'\n );\n assert.equal(\n zustand.getState().isTranslating,\n false,\n 'Should not be translating'\n );\n });\n\n it('should handle language switching after flow is loaded', () => {\n const state = zustand.getState();\n\n // Load a flow with English as default\n const mockFlowContents = {\n definition: {\n language: 'en',\n localization: {},\n name: 'Test Flow',\n nodes: [],\n uuid: 'test-uuid',\n type: 'messaging' as const,\n revision: 1,\n spec_version: '14.3',\n _ui: {\n nodes: {},\n languages: []\n }\n },\n info: {\n results: [],\n dependencies: [],\n counts: { nodes: 0, languages: 1 },\n locals: []\n }\n };\n\n state.setFlowContents(mockFlowContents);\n\n // Should start in English, not translating\n assert.equal(zustand.getState().languageCode, 'en');\n assert.equal(zustand.getState().isTranslating, false);\n\n // Switch to Spanish for localization\n state.setLanguageCode('es');\n assert.equal(zustand.getState().languageCode, 'es');\n assert.equal(zustand.getState().isTranslating, true);\n\n // Switch back to English\n state.setLanguageCode('en');\n assert.equal(zustand.getState().languageCode, 'en');\n assert.equal(zustand.getState().isTranslating, false);\n });\n});\n"]}
@@ -1,4 +1,5 @@
1
1
  import { expect } from '@open-wc/testing';
2
+ import { formatDurationFromSeconds } from '../src/chart/TembaChart';
2
3
  import { getComponent } from './utils.test';
3
4
  const sampleData = {
4
5
  labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
@@ -42,5 +43,129 @@ describe('temba-chart', () => {
42
43
  // now others should be everything but general and support
43
44
  expect(chart.datasets[2].data).to.deep.equal([58, 28, 10, 1, 0, 19, 20]);
44
45
  });
46
+ it('supports duration formatting', async () => {
47
+ const chart = await getChart();
48
+ // Test that formatDuration property exists and defaults to false
49
+ expect(chart.formatDuration).to.equal(false);
50
+ // Test that we can set formatDuration to true
51
+ chart.formatDuration = true;
52
+ expect(chart.formatDuration).to.equal(true);
53
+ });
54
+ it('formats duration values correctly', async () => {
55
+ const chart = await getChart();
56
+ // Access the formatDurationFromSeconds function through the chart's module
57
+ // We need to test the duration formatting logic
58
+ const durationData = {
59
+ labels: ['Day 1', 'Day 2', 'Day 3'],
60
+ datasets: [
61
+ {
62
+ label: 'Process Time',
63
+ data: [68787, 958000, 3661] // seconds that should be formatted as durations
64
+ }
65
+ ]
66
+ };
67
+ chart.formatDuration = true;
68
+ chart.data = durationData;
69
+ await chart.updateComplete;
70
+ // Wait for the chart to be created after data is set
71
+ await new Promise((resolve) => setTimeout(resolve, 100));
72
+ // Test that the chart was created and has the duration formatting enabled
73
+ expect(chart.formatDuration).to.equal(true);
74
+ expect(chart.chart).to.exist;
75
+ // Test that the chart configuration includes the duration formatting
76
+ const chartConfig = chart.chart.options;
77
+ expect(chartConfig.scales.y.ticks).to.exist;
78
+ expect(chartConfig.scales.y.ticks.callback).to.be.a('function');
79
+ // Test the tick callback function formatting
80
+ const tickCallback = chartConfig.scales.y.ticks.callback;
81
+ expect(tickCallback.call({}, 68787, 0, [])).to.equal('19h 6m');
82
+ expect(tickCallback.call({}, 958000, 1, [])).to.equal('11d 2h');
83
+ expect(tickCallback.call({}, 3661, 2, [])).to.equal('1h 1m');
84
+ expect(tickCallback.call({}, 120, 3, [])).to.equal('2m');
85
+ expect(tickCallback.call({}, 0, 4, [])).to.equal('0s');
86
+ // Test tooltip formatting
87
+ expect(chartConfig.plugins.tooltip.callbacks.label).to.be.a('function');
88
+ const tooltipCallback = chartConfig.plugins.tooltip.callbacks.label;
89
+ const mockContext = {
90
+ dataset: { label: 'Process Time' },
91
+ parsed: { y: 68787 }
92
+ };
93
+ expect(tooltipCallback.call({}, mockContext)).to.equal('Process Time: 19h 6m');
94
+ });
95
+ it('formats various duration edge cases correctly', async () => {
96
+ const chart = await getChart();
97
+ chart.formatDuration = true;
98
+ chart.data = sampleData;
99
+ await chart.updateComplete;
100
+ // Wait for the chart to be created after data is set
101
+ await new Promise((resolve) => setTimeout(resolve, 100));
102
+ expect(chart.chart).to.exist;
103
+ const tickCallback = chart.chart.options.scales.y.ticks.callback;
104
+ // Test edge cases for duration formatting
105
+ expect(tickCallback.call({}, 0, 0, [])).to.equal('0s');
106
+ expect(tickCallback.call({}, 1, 1, [])).to.equal('1s');
107
+ expect(tickCallback.call({}, 59, 2, [])).to.equal('59s');
108
+ expect(tickCallback.call({}, 60, 3, [])).to.equal('1m');
109
+ expect(tickCallback.call({}, 61, 4, [])).to.equal('1m 1s');
110
+ expect(tickCallback.call({}, 3600, 5, [])).to.equal('1h');
111
+ expect(tickCallback.call({}, 3661, 6, [])).to.equal('1h 1m');
112
+ expect(tickCallback.call({}, 86400, 7, [])).to.equal('1d');
113
+ expect(tickCallback.call({}, 90061, 8, [])).to.equal('1d 1h'); // 1 day, 1 hour, 1 minute, 1 second - should show only first two units
114
+ expect(tickCallback.call({}, 604800, 9, [])).to.equal('7d'); // 1 week in seconds
115
+ expect(tickCallback.call({}, 1209600, 10, [])).to.equal('14d'); // 2 weeks in seconds
116
+ });
117
+ it('respects formatDuration property state', async () => {
118
+ const chart = await getChart();
119
+ // Test default state
120
+ expect(chart.formatDuration).to.equal(false);
121
+ chart.data = sampleData;
122
+ await chart.updateComplete;
123
+ // Test that formatDuration property can be toggled
124
+ chart.formatDuration = true;
125
+ expect(chart.formatDuration).to.equal(true);
126
+ chart.formatDuration = false;
127
+ expect(chart.formatDuration).to.equal(false);
128
+ });
129
+ });
130
+ describe('formatDurationFromSeconds', () => {
131
+ it('formats zero correctly', () => {
132
+ expect(formatDurationFromSeconds(0)).to.equal('0s');
133
+ });
134
+ it('formats seconds only', () => {
135
+ expect(formatDurationFromSeconds(1)).to.equal('1s');
136
+ expect(formatDurationFromSeconds(30)).to.equal('30s');
137
+ expect(formatDurationFromSeconds(59)).to.equal('59s');
138
+ });
139
+ it('formats minutes and seconds', () => {
140
+ expect(formatDurationFromSeconds(60)).to.equal('1m');
141
+ expect(formatDurationFromSeconds(61)).to.equal('1m 1s');
142
+ expect(formatDurationFromSeconds(90)).to.equal('1m 30s');
143
+ expect(formatDurationFromSeconds(120)).to.equal('2m');
144
+ expect(formatDurationFromSeconds(3599)).to.equal('59m 59s');
145
+ });
146
+ it('formats hours and minutes', () => {
147
+ expect(formatDurationFromSeconds(3600)).to.equal('1h');
148
+ expect(formatDurationFromSeconds(3661)).to.equal('1h 1m');
149
+ expect(formatDurationFromSeconds(7200)).to.equal('2h');
150
+ expect(formatDurationFromSeconds(68787)).to.equal('19h 6m');
151
+ });
152
+ it('formats days and hours', () => {
153
+ expect(formatDurationFromSeconds(86400)).to.equal('1d');
154
+ expect(formatDurationFromSeconds(90000)).to.equal('1d 1h');
155
+ expect(formatDurationFromSeconds(958000)).to.equal('11d 2h');
156
+ });
157
+ it('shows only two most significant units', () => {
158
+ // 1 day, 1 hour, 1 minute, 1 second - should show only "1d 1h"
159
+ expect(formatDurationFromSeconds(90061)).to.equal('1d 1h');
160
+ // 2 hours, 30 minutes, 45 seconds - should show only "2h 30m"
161
+ expect(formatDurationFromSeconds(9045)).to.equal('2h 30m');
162
+ // 5 minutes, 30 seconds - should show "5m 30s"
163
+ expect(formatDurationFromSeconds(330)).to.equal('5m 30s');
164
+ });
165
+ it('handles large durations', () => {
166
+ expect(formatDurationFromSeconds(604800)).to.equal('7d'); // 1 week
167
+ expect(formatDurationFromSeconds(1209600)).to.equal('14d'); // 2 weeks
168
+ expect(formatDurationFromSeconds(2678400)).to.equal('31d'); // ~1 month
169
+ });
45
170
  });
46
171
  //# sourceMappingURL=temba-chart.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"temba-chart.test.js","sourceRoot":"","sources":["../../test/temba-chart.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,GAAmB;IACjC,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;IACxE,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;SACnC;QACD;YACE,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;SACnC;QACD;YACE,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;SACjC;KACF;CACF,CAAC;AAEF,MAAM,GAAG,GAAG,aAAa,CAAC;AAC1B,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE,EAAE;IACzC,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,CAAC,CAAe,CAAC;IACvE,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACjC,MAAM,KAAK,GAAe,MAAM,QAAQ,EAAE,CAAC;QAE3C,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;QACxB,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,qEAAqE;QACrE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YAC3C,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;SAClC,CAAC,CAAC;QAEH,cAAc;QACd,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3B,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,wCAAwC;QACxC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QAE5E,oBAAoB;QACpB,KAAK,CAAC,MAAM,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,0DAA0D;QAC1D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { RapidChartData, TembaChart } from '../src/chart/TembaChart';\nimport { getComponent } from './utils.test';\n\nconst sampleData: RapidChartData = {\n labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],\n datasets: [\n {\n label: 'General',\n data: [65, 59, 80, 81, 56, 55, 40]\n },\n {\n label: 'Support',\n data: [28, 48, 40, 19, 86, 27, 90]\n },\n {\n label: 'VIPs',\n data: [58, 28, 10, 1, 0, 19, 20]\n }\n ]\n};\n\nconst TAG = 'temba-chart';\nconst getChart = async (attrs: any = {}) => {\n const picker = (await getComponent(TAG, attrs, '', 400)) as TembaChart;\n return picker;\n};\n\ndescribe('temba-chart', () => {\n it('calculates others', async () => {\n const chart: TembaChart = await getChart();\n\n chart.data = sampleData;\n await chart.updateComplete;\n\n // if we haven't set any splits, everything should be summed as \"All\"\n expect(chart.datasets[0].data).to.deep.equal([\n 151, 135, 130, 101, 142, 101, 150\n ]);\n\n // add a split\n chart.splits = ['General'];\n await chart.updateComplete;\n\n // now we should get an \"Others\" dataset\n expect(chart.datasets[1].data).to.deep.equal([86, 76, 50, 20, 86, 46, 110]);\n\n // add another split\n chart.splits = ['General', 'Support'];\n await chart.updateComplete;\n\n // now others should be everything but general and support\n expect(chart.datasets[2].data).to.deep.equal([58, 28, 10, 1, 0, 19, 20]);\n });\n});\n"]}
1
+ {"version":3,"file":"temba-chart.test.js","sourceRoot":"","sources":["../../test/temba-chart.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport {\n RapidChartData,\n TembaChart,\n formatDurationFromSeconds\n} from '../src/chart/TembaChart';\nimport { getComponent } from './utils.test';\n\nconst sampleData: RapidChartData = {\n labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],\n datasets: [\n {\n label: 'General',\n data: [65, 59, 80, 81, 56, 55, 40]\n },\n {\n label: 'Support',\n data: [28, 48, 40, 19, 86, 27, 90]\n },\n {\n label: 'VIPs',\n data: [58, 28, 10, 1, 0, 19, 20]\n }\n ]\n};\n\nconst TAG = 'temba-chart';\nconst getChart = async (attrs: any = {}) => {\n const picker = (await getComponent(TAG, attrs, '', 400)) as TembaChart;\n return picker;\n};\n\ndescribe('temba-chart', () => {\n it('calculates others', async () => {\n const chart: TembaChart = await getChart();\n\n chart.data = sampleData;\n await chart.updateComplete;\n\n // if we haven't set any splits, everything should be summed as \"All\"\n expect(chart.datasets[0].data).to.deep.equal([\n 151, 135, 130, 101, 142, 101, 150\n ]);\n\n // add a split\n chart.splits = ['General'];\n await chart.updateComplete;\n\n // now we should get an \"Others\" dataset\n expect(chart.datasets[1].data).to.deep.equal([86, 76, 50, 20, 86, 46, 110]);\n\n // add another split\n chart.splits = ['General', 'Support'];\n await chart.updateComplete;\n\n // now others should be everything but general and support\n expect(chart.datasets[2].data).to.deep.equal([58, 28, 10, 1, 0, 19, 20]);\n });\n\n it('supports duration formatting', async () => {\n const chart: TembaChart = await getChart();\n\n // Test that formatDuration property exists and defaults to false\n expect(chart.formatDuration).to.equal(false);\n\n // Test that we can set formatDuration to true\n chart.formatDuration = true;\n expect(chart.formatDuration).to.equal(true);\n });\n\n it('formats duration values correctly', async () => {\n const chart: TembaChart = await getChart();\n\n // Access the formatDurationFromSeconds function through the chart's module\n // We need to test the duration formatting logic\n const durationData: RapidChartData = {\n labels: ['Day 1', 'Day 2', 'Day 3'],\n datasets: [\n {\n label: 'Process Time',\n data: [68787, 958000, 3661] // seconds that should be formatted as durations\n }\n ]\n };\n\n chart.formatDuration = true;\n chart.data = durationData;\n await chart.updateComplete;\n\n // Wait for the chart to be created after data is set\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n // Test that the chart was created and has the duration formatting enabled\n expect(chart.formatDuration).to.equal(true);\n expect(chart.chart).to.exist;\n\n // Test that the chart configuration includes the duration formatting\n const chartConfig = chart.chart.options;\n expect(chartConfig.scales.y.ticks).to.exist;\n expect(chartConfig.scales.y.ticks.callback).to.be.a('function');\n\n // Test the tick callback function formatting\n const tickCallback = chartConfig.scales.y.ticks.callback;\n expect(tickCallback.call({}, 68787, 0, [])).to.equal('19h 6m');\n expect(tickCallback.call({}, 958000, 1, [])).to.equal('11d 2h');\n expect(tickCallback.call({}, 3661, 2, [])).to.equal('1h 1m');\n expect(tickCallback.call({}, 120, 3, [])).to.equal('2m');\n expect(tickCallback.call({}, 0, 4, [])).to.equal('0s');\n\n // Test tooltip formatting\n expect(chartConfig.plugins.tooltip.callbacks.label).to.be.a('function');\n const tooltipCallback = chartConfig.plugins.tooltip.callbacks.label;\n\n const mockContext = {\n dataset: { label: 'Process Time' },\n parsed: { y: 68787 }\n };\n expect(tooltipCallback.call({}, mockContext)).to.equal(\n 'Process Time: 19h 6m'\n );\n });\n\n it('formats various duration edge cases correctly', async () => {\n const chart: TembaChart = await getChart();\n chart.formatDuration = true;\n chart.data = sampleData;\n await chart.updateComplete;\n\n // Wait for the chart to be created after data is set\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n expect(chart.chart).to.exist;\n const tickCallback = chart.chart.options.scales.y.ticks.callback;\n\n // Test edge cases for duration formatting\n expect(tickCallback.call({}, 0, 0, [])).to.equal('0s');\n expect(tickCallback.call({}, 1, 1, [])).to.equal('1s');\n expect(tickCallback.call({}, 59, 2, [])).to.equal('59s');\n expect(tickCallback.call({}, 60, 3, [])).to.equal('1m');\n expect(tickCallback.call({}, 61, 4, [])).to.equal('1m 1s');\n expect(tickCallback.call({}, 3600, 5, [])).to.equal('1h');\n expect(tickCallback.call({}, 3661, 6, [])).to.equal('1h 1m');\n expect(tickCallback.call({}, 86400, 7, [])).to.equal('1d');\n expect(tickCallback.call({}, 90061, 8, [])).to.equal('1d 1h'); // 1 day, 1 hour, 1 minute, 1 second - should show only first two units\n expect(tickCallback.call({}, 604800, 9, [])).to.equal('7d'); // 1 week in seconds\n expect(tickCallback.call({}, 1209600, 10, [])).to.equal('14d'); // 2 weeks in seconds\n });\n\n it('respects formatDuration property state', async () => {\n const chart: TembaChart = await getChart();\n\n // Test default state\n expect(chart.formatDuration).to.equal(false);\n\n chart.data = sampleData;\n await chart.updateComplete;\n\n // Test that formatDuration property can be toggled\n chart.formatDuration = true;\n expect(chart.formatDuration).to.equal(true);\n\n chart.formatDuration = false;\n expect(chart.formatDuration).to.equal(false);\n });\n});\n\ndescribe('formatDurationFromSeconds', () => {\n it('formats zero correctly', () => {\n expect(formatDurationFromSeconds(0)).to.equal('0s');\n });\n\n it('formats seconds only', () => {\n expect(formatDurationFromSeconds(1)).to.equal('1s');\n expect(formatDurationFromSeconds(30)).to.equal('30s');\n expect(formatDurationFromSeconds(59)).to.equal('59s');\n });\n\n it('formats minutes and seconds', () => {\n expect(formatDurationFromSeconds(60)).to.equal('1m');\n expect(formatDurationFromSeconds(61)).to.equal('1m 1s');\n expect(formatDurationFromSeconds(90)).to.equal('1m 30s');\n expect(formatDurationFromSeconds(120)).to.equal('2m');\n expect(formatDurationFromSeconds(3599)).to.equal('59m 59s');\n });\n\n it('formats hours and minutes', () => {\n expect(formatDurationFromSeconds(3600)).to.equal('1h');\n expect(formatDurationFromSeconds(3661)).to.equal('1h 1m');\n expect(formatDurationFromSeconds(7200)).to.equal('2h');\n expect(formatDurationFromSeconds(68787)).to.equal('19h 6m');\n });\n\n it('formats days and hours', () => {\n expect(formatDurationFromSeconds(86400)).to.equal('1d');\n expect(formatDurationFromSeconds(90000)).to.equal('1d 1h');\n expect(formatDurationFromSeconds(958000)).to.equal('11d 2h');\n });\n\n it('shows only two most significant units', () => {\n // 1 day, 1 hour, 1 minute, 1 second - should show only \"1d 1h\"\n expect(formatDurationFromSeconds(90061)).to.equal('1d 1h');\n\n // 2 hours, 30 minutes, 45 seconds - should show only \"2h 30m\"\n expect(formatDurationFromSeconds(9045)).to.equal('2h 30m');\n\n // 5 minutes, 30 seconds - should show \"5m 30s\"\n expect(formatDurationFromSeconds(330)).to.equal('5m 30s');\n });\n\n it('handles large durations', () => {\n expect(formatDurationFromSeconds(604800)).to.equal('7d'); // 1 week\n expect(formatDurationFromSeconds(1209600)).to.equal('14d'); // 2 weeks\n expect(formatDurationFromSeconds(2678400)).to.equal('31d'); // ~1 month\n });\n});\n"]}