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