@thoughtspot/ts-chart-sdk 0.0.2-alpha.9 → 1.1.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 (141) hide show
  1. package/README.md +126 -50
  2. package/dist/ts-chart-sdk.d.ts +330 -32
  3. package/lib/index.d.ts +3 -0
  4. package/lib/index.d.ts.map +1 -1
  5. package/lib/index.js +3 -0
  6. package/lib/index.js.map +1 -1
  7. package/lib/main/custom-chart-context.d.ts +17 -4
  8. package/lib/main/custom-chart-context.d.ts.map +1 -1
  9. package/lib/main/custom-chart-context.js +46 -16
  10. package/lib/main/custom-chart-context.js.map +1 -1
  11. package/lib/main/custom-chart-context.spec.js +302 -4
  12. package/lib/main/custom-chart-context.spec.js.map +1 -1
  13. package/lib/main/logger.d.ts +13 -0
  14. package/lib/main/logger.d.ts.map +1 -0
  15. package/lib/main/logger.js +64 -0
  16. package/lib/main/logger.js.map +1 -0
  17. package/lib/main/logger.spec.d.ts +2 -0
  18. package/lib/main/logger.spec.d.ts.map +1 -0
  19. package/lib/main/logger.spec.js +88 -0
  20. package/lib/main/logger.spec.js.map +1 -0
  21. package/lib/main/util.d.ts +2 -0
  22. package/lib/main/util.d.ts.map +1 -1
  23. package/lib/main/util.js +11 -0
  24. package/lib/main/util.js.map +1 -1
  25. package/lib/main/util.spec.d.ts +2 -0
  26. package/lib/main/util.spec.d.ts.map +1 -0
  27. package/lib/main/util.spec.js +73 -0
  28. package/lib/main/util.spec.js.map +1 -0
  29. package/lib/react/use-custom-chart-context.d.ts.map +1 -1
  30. package/lib/react/use-custom-chart-context.js +3 -1
  31. package/lib/react/use-custom-chart-context.js.map +1 -1
  32. package/lib/react/use-custom-chart-context.spec.js +0 -1
  33. package/lib/react/use-custom-chart-context.spec.js.map +1 -1
  34. package/lib/react/use-custom-chart-context.util.d.ts.map +1 -1
  35. package/lib/react/use-custom-chart-context.util.js +5 -3
  36. package/lib/react/use-custom-chart-context.util.js.map +1 -1
  37. package/lib/types/answer-column.types.d.ts +7 -4
  38. package/lib/types/answer-column.types.d.ts.map +1 -1
  39. package/lib/types/answer-column.types.js +3 -3
  40. package/lib/types/answer-column.types.js.map +1 -1
  41. package/lib/types/chart-to-ts-event.types.d.ts +2 -0
  42. package/lib/types/chart-to-ts-event.types.d.ts.map +1 -1
  43. package/lib/types/chart-to-ts-event.types.js +1 -0
  44. package/lib/types/chart-to-ts-event.types.js.map +1 -1
  45. package/lib/types/common.types.d.ts +65 -6
  46. package/lib/types/common.types.d.ts.map +1 -1
  47. package/lib/types/common.types.js.map +1 -1
  48. package/lib/types/conditional-formatting.types.d.ts +1 -16
  49. package/lib/types/conditional-formatting.types.d.ts.map +1 -1
  50. package/lib/types/conditional-formatting.types.js.map +1 -1
  51. package/lib/types/configurator.types.d.ts +1 -1
  52. package/lib/types/configurator.types.d.ts.map +1 -1
  53. package/lib/types/number-formatting.types.d.ts +55 -0
  54. package/lib/types/number-formatting.types.d.ts.map +1 -0
  55. package/lib/types/number-formatting.types.js +23 -0
  56. package/lib/types/number-formatting.types.js.map +1 -0
  57. package/lib/types/ts-to-chart-event.types.d.ts +20 -6
  58. package/lib/types/ts-to-chart-event.types.d.ts.map +1 -1
  59. package/lib/types/ts-to-chart-event.types.js +1 -0
  60. package/lib/types/ts-to-chart-event.types.js.map +1 -1
  61. package/lib/types/visual-prop.types.d.ts +71 -3
  62. package/lib/types/visual-prop.types.d.ts.map +1 -1
  63. package/lib/types/visual-prop.types.js +32 -1
  64. package/lib/types/visual-prop.types.js.map +1 -1
  65. package/lib/utils/date-formatting.d.ts +85 -1
  66. package/lib/utils/date-formatting.d.ts.map +1 -1
  67. package/lib/utils/date-formatting.js +344 -9
  68. package/lib/utils/date-formatting.js.map +1 -1
  69. package/lib/utils/date-formatting.spec.js +301 -31
  70. package/lib/utils/date-formatting.spec.js.map +1 -1
  71. package/lib/utils/date-utils.d.ts +6 -0
  72. package/lib/utils/date-utils.d.ts.map +1 -0
  73. package/lib/utils/date-utils.js +20 -0
  74. package/lib/utils/date-utils.js.map +1 -0
  75. package/lib/utils/date-utils.spec.d.ts +2 -0
  76. package/lib/utils/date-utils.spec.d.ts.map +1 -0
  77. package/lib/utils/date-utils.spec.js +63 -0
  78. package/lib/utils/date-utils.spec.js.map +1 -0
  79. package/lib/utils/formatting-util.d.ts +10 -0
  80. package/lib/utils/formatting-util.d.ts.map +1 -0
  81. package/lib/utils/formatting-util.js +78 -0
  82. package/lib/utils/formatting-util.js.map +1 -0
  83. package/lib/utils/formatting-util.spec.d.ts +2 -0
  84. package/lib/utils/formatting-util.spec.d.ts.map +1 -0
  85. package/lib/utils/formatting-util.spec.js +247 -0
  86. package/lib/utils/formatting-util.spec.js.map +1 -0
  87. package/lib/utils/globalize-Initializer/globalize-utils.d.ts +16 -0
  88. package/lib/utils/globalize-Initializer/globalize-utils.d.ts.map +1 -0
  89. package/lib/utils/globalize-Initializer/globalize-utils.js +101 -0
  90. package/lib/utils/globalize-Initializer/globalize-utils.js.map +1 -0
  91. package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts +2 -0
  92. package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts.map +1 -0
  93. package/lib/utils/globalize-Initializer/globalize-utils.spec.js +149 -0
  94. package/lib/utils/globalize-Initializer/globalize-utils.spec.js.map +1 -0
  95. package/lib/utils/number-formatting/number-formatting-utils.d.ts +20 -0
  96. package/lib/utils/number-formatting/number-formatting-utils.d.ts.map +1 -0
  97. package/lib/utils/number-formatting/number-formatting-utils.js +159 -0
  98. package/lib/utils/number-formatting/number-formatting-utils.js.map +1 -0
  99. package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts +2 -0
  100. package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts.map +1 -0
  101. package/lib/utils/number-formatting/number-formatting-utils.spec.js +221 -0
  102. package/lib/utils/number-formatting/number-formatting-utils.spec.js.map +1 -0
  103. package/lib/utils/number-formatting/number-formatting.d.ts +5 -0
  104. package/lib/utils/number-formatting/number-formatting.d.ts.map +1 -0
  105. package/lib/utils/number-formatting/number-formatting.js +128 -0
  106. package/lib/utils/number-formatting/number-formatting.js.map +1 -0
  107. package/lib/utils/number-formatting/number-formatting.spec.d.ts +2 -0
  108. package/lib/utils/number-formatting/number-formatting.spec.d.ts.map +1 -0
  109. package/lib/utils/number-formatting/number-formatting.spec.js +159 -0
  110. package/lib/utils/number-formatting/number-formatting.spec.js.map +1 -0
  111. package/package.json +4 -1
  112. package/src/index.ts +3 -0
  113. package/src/main/custom-chart-context.spec.ts +356 -6
  114. package/src/main/custom-chart-context.ts +205 -16
  115. package/src/main/logger.spec.ts +114 -0
  116. package/src/main/logger.ts +97 -0
  117. package/src/main/util.spec.ts +94 -0
  118. package/src/main/util.ts +20 -0
  119. package/src/react/use-custom-chart-context.spec.tsx +0 -1
  120. package/src/react/use-custom-chart-context.tsx +4 -1
  121. package/src/react/use-custom-chart-context.util.ts +6 -3
  122. package/src/types/answer-column.types.ts +9 -6
  123. package/src/types/chart-to-ts-event.types.ts +7 -0
  124. package/src/types/common.types.ts +100 -10
  125. package/src/types/conditional-formatting.types.ts +2 -17
  126. package/src/types/configurator.types.ts +1 -1
  127. package/src/types/number-formatting.types.ts +80 -0
  128. package/src/types/ts-to-chart-event.types.ts +63 -5
  129. package/src/types/visual-prop.types.ts +197 -3
  130. package/src/utils/date-formatting.spec.ts +375 -32
  131. package/src/utils/date-formatting.ts +587 -14
  132. package/src/utils/date-utils.spec.ts +93 -0
  133. package/src/utils/date-utils.ts +69 -0
  134. package/src/utils/formatting-util.spec.ts +312 -0
  135. package/src/utils/formatting-util.ts +234 -0
  136. package/src/utils/globalize-Initializer/globalize-utils.spec.ts +192 -0
  137. package/src/utils/globalize-Initializer/globalize-utils.ts +216 -0
  138. package/src/utils/number-formatting/number-formatting-utils.spec.ts +296 -0
  139. package/src/utils/number-formatting/number-formatting-utils.ts +260 -0
  140. package/src/utils/number-formatting/number-formatting.spec.ts +243 -0
  141. package/src/utils/number-formatting/number-formatting.ts +264 -0
@@ -0,0 +1,159 @@
1
+ import { create, LogLevel, logMethods } from '../../main/logger';
2
+ import { CurrencyFormatType, FormatType, } from '../../types/answer-column.types';
3
+ import { CategoryType, NegativeValueFormat, Unit, } from '../../types/number-formatting.types';
4
+ import { initGlobalize } from '../globalize-Initializer/globalize-utils';
5
+ import * as globalizeUtils from '../globalize-Initializer/globalize-utils';
6
+ import { formatCurrencyWithCustomPattern, getFormattedValue, } from './number-formatting';
7
+ jest.mock('../../main/util', () => ({
8
+ getQueryParam: jest.fn().mockReturnValue('true'),
9
+ }));
10
+ describe('formatCurrencyWithCustomPattern', () => {
11
+ beforeAll(() => {
12
+ initGlobalize('en-US');
13
+ });
14
+ test('formats value with a custom pattern and currency symbol', () => {
15
+ const value = 12345.678;
16
+ const currencyCode = 'USD';
17
+ const formatPattern = '#,##0.00';
18
+ const result = formatCurrencyWithCustomPattern(value, currencyCode, formatPattern);
19
+ expect(result).toBe('$12,345.68');
20
+ });
21
+ });
22
+ describe('getFormattedValue', () => {
23
+ beforeAll(() => {
24
+ initGlobalize('en-US');
25
+ });
26
+ const columnFormatConfig = {
27
+ type: FormatType.CURRENCY,
28
+ currencyFormat: {
29
+ type: CurrencyFormatType.ISO_CODE,
30
+ column: '',
31
+ isoCode: 'USD',
32
+ },
33
+ };
34
+ beforeEach(() => {
35
+ jest.clearAllMocks();
36
+ });
37
+ test('uses Number Fromatting as default configuration when formatConfigProp & columnFormatConfig are null', () => {
38
+ const result = getFormattedValue(12345, {}, {});
39
+ expect(result).toBe('12.35K');
40
+ });
41
+ test('use Custom Formatting as default configuration when only formatConfigProp is null', () => {
42
+ const result = getFormattedValue(12345, {}, columnFormatConfig);
43
+ expect(result).toBe('$12.35K');
44
+ });
45
+ test('formats special values (NaN, Infinity)', () => {
46
+ expect(getFormattedValue(NaN, {}, {})).toBe('NaN');
47
+ expect(getFormattedValue(Infinity, {}, {})).toBe('Infinity');
48
+ expect(getFormattedValue(-Infinity, {}, {})).toBe('-Infinity');
49
+ });
50
+ test('formats number category values with units and trailing zeroes', () => {
51
+ const formatConfig = {
52
+ category: CategoryType.Number,
53
+ numberFormatConfig: {
54
+ unit: Unit.Thousands,
55
+ decimals: 2,
56
+ toSeparateThousands: true,
57
+ negativeValueFormat: NegativeValueFormat.PrefixDash,
58
+ },
59
+ };
60
+ const result = getFormattedValue(-12345, formatConfig, {});
61
+ expect(result).toBe('-12.35K');
62
+ });
63
+ test('formats percentage values correctly', () => {
64
+ const formatConfig = {
65
+ category: CategoryType.Percentage,
66
+ percentageFormatConfig: { decimals: 2, removeTrailingZeroes: true },
67
+ };
68
+ const result = getFormattedValue(0.1234, formatConfig, {});
69
+ expect(result).toBe('12.34%');
70
+ });
71
+ test('formats currency values with compact units', () => {
72
+ const formatConfig = {
73
+ category: CategoryType.Currency,
74
+ currencyFormatConfig: {
75
+ locale: 'USD',
76
+ toSeparateThousands: true,
77
+ },
78
+ };
79
+ const result = getFormattedValue(12345.678, formatConfig, {});
80
+ expect(result).toMatch(/^\$\d+,\d+(\.\d+)?$/);
81
+ });
82
+ test('formats currency values with user Locale', () => {
83
+ jest.spyOn(globalizeUtils, 'getDefaultCurrencyCode').mockImplementationOnce(() => 'INR');
84
+ const formatConfig = {
85
+ category: CategoryType.Currency,
86
+ currencyFormatConfig: {
87
+ unit: Unit.Thousands,
88
+ decimals: 2,
89
+ locale: CurrencyFormatType.USER_LOCALE,
90
+ toSeparateThousands: true,
91
+ },
92
+ };
93
+ const result = getFormattedValue(12345.678, formatConfig, {});
94
+ expect(result).toMatch('₹12.35K');
95
+ });
96
+ test('should normalize category to CategoryType.Number when it is a number', () => {
97
+ const formatConfig = {
98
+ category: CategoryType.Number,
99
+ numberFormatConfig: {
100
+ unit: Unit.Thousands,
101
+ decimals: 2,
102
+ toSeparateThousands: true,
103
+ negativeValueFormat: NegativeValueFormat.PrefixDash,
104
+ },
105
+ };
106
+ const result = getFormattedValue(1000, formatConfig, {});
107
+ expect(result).toBe('1.00K');
108
+ });
109
+ test('falls back to default formatting for unsupported categories', () => {
110
+ const formatConfig = { category: 'Unknown' };
111
+ const result = getFormattedValue(12345.678, formatConfig, {});
112
+ expect(result).toBe('12,345.678');
113
+ });
114
+ test('formats custom pattern correctly', () => {
115
+ const formatConfig = {
116
+ category: CategoryType.Custom,
117
+ customFormatConfig: { format: '#,##0.00' },
118
+ };
119
+ const result = getFormattedValue(12345.678, formatConfig, {});
120
+ expect(result).toBe('12,345.68');
121
+ });
122
+ test('formats custom pattern with valid customColumn format', () => {
123
+ const formatConfig = {
124
+ category: CategoryType.Custom,
125
+ customFormatConfig: { format: '#,##0.00' },
126
+ };
127
+ const result = getFormattedValue(12345.678, formatConfig, columnFormatConfig);
128
+ expect(result).toBe('$12,345.68');
129
+ });
130
+ test('logs error for invalid custom format patterns', () => {
131
+ const formatConfig = {
132
+ category: CategoryType.Custom,
133
+ customFormatConfig: { format: 'invalid-format' },
134
+ };
135
+ const error = jest.fn();
136
+ logMethods[LogLevel.ERROR] = error;
137
+ const logger = create('TestLogger');
138
+ logger.error = error;
139
+ getFormattedValue(12345.678, formatConfig, {});
140
+ expect(logger.error).toHaveBeenCalled();
141
+ jest.restoreAllMocks();
142
+ });
143
+ test('handles currency formatting failure', () => {
144
+ const formatConfig = {
145
+ category: CategoryType.Currency,
146
+ };
147
+ jest.spyOn(globalizeUtils, 'globalizeCurrencyFormatter').mockImplementationOnce(() => {
148
+ throw new Error('Currency format error');
149
+ });
150
+ const error = jest.fn();
151
+ logMethods[LogLevel.ERROR] = error;
152
+ const logger = create('TestLogger');
153
+ logger.error = error;
154
+ getFormattedValue(12345.678, formatConfig, {});
155
+ expect(logger.error).toHaveBeenCalled();
156
+ jest.restoreAllMocks();
157
+ });
158
+ });
159
+ //# sourceMappingURL=number-formatting.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-formatting.spec.js","sourceRoot":"","sources":["../../../src/utils/number-formatting/number-formatting.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@thoughtspot/ts-chart-sdk",
3
3
  "private": false,
4
- "version": "0.0.2-alpha.9",
4
+ "version": "1.1.0",
5
5
  "module": "lib/index",
6
6
  "main": "lib/index",
7
7
  "types": "lib/index",
@@ -34,6 +34,7 @@
34
34
  "devDependencies": {
35
35
  "@testing-library/react": "12.1.5",
36
36
  "@testing-library/react-hooks": "^7.0.2",
37
+ "@types/globalize": "^1.5.5",
37
38
  "@types/jest": "^27.0.3",
38
39
  "@types/lodash": "4.14.175",
39
40
  "@types/luxon": "^3.4.2",
@@ -74,6 +75,8 @@
74
75
  "vite": "4.2.1"
75
76
  },
76
77
  "dependencies": {
78
+ "cldr-data": "^36.0.2",
79
+ "globalize": "^1.7.0",
77
80
  "lodash": "^4.17.21",
78
81
  "luxon": "^3.4.4",
79
82
  "promise-postmessage": "^3.5.0",
package/src/index.ts CHANGED
@@ -7,5 +7,8 @@ export * from './types/ts-to-chart-event.types';
7
7
  export * from './main/custom-chart-context';
8
8
  export * from './react/use-custom-chart-context';
9
9
  export * from './types/conditional-formatting.types';
10
+ export * from './types/number-formatting.types';
10
11
  export * from './utils/date-formatting';
11
12
  export * from './utils/conditional-formatting/conditional-formatting';
13
+ export * from './utils/number-formatting/number-formatting';
14
+ export * from './utils/globalize-Initializer/globalize-utils';
@@ -6,17 +6,25 @@
6
6
 
7
7
  import _ from 'lodash';
8
8
  import { mockInitializeContextPayload } from '../test/test-utils';
9
+ import { ColumnType } from '../types/answer-column.types';
9
10
  import { ChartToTSEvent, ErrorType } from '../types/chart-to-ts-event.types';
10
11
  import { TSToChartEvent } from '../types/ts-to-chart-event.types';
12
+ import { PropElement } from '../types/visual-prop.types';
11
13
  import { CustomChartContext, getChartContext } from './custom-chart-context';
12
14
  import * as PostMessageEventBridge from './post-message-event-bridge';
13
15
 
14
- // jest.mock('./post-message-event-bridge');
15
-
16
16
  jest.spyOn(console, 'log').mockImplementation(() => {
17
17
  // do nothing.
18
18
  });
19
19
 
20
+ const mockFormElements: PropElement = {
21
+ key: 'color',
22
+ type: 'radio',
23
+ defaultValue: 'red',
24
+ values: ['red', 'green', 'yellow'],
25
+ label: 'Colors',
26
+ };
27
+
20
28
  describe('CustomChartContext', () => {
21
29
  let eventProcessor: any;
22
30
 
@@ -107,10 +115,30 @@ describe('CustomChartContext', () => {
107
115
  allowedConfigurations: {
108
116
  allowColumnNumberFormatting: false,
109
117
  allowColumnConditionalFormatting: false,
118
+ allowGradientColoring: false,
110
119
  allowMeasureNamesAndValues: false,
111
120
  },
121
+ persistedVisualPropKeys: undefined,
122
+ chartConfigParameters: {
123
+ measureNameValueColumns: {
124
+ enableMeasureNameColumn: false,
125
+ enableMeasureValueColumn: false,
126
+ measureNameColumnAlias: 'Measure Name',
127
+ measureValueColumnAlias: 'Measure Values',
128
+ },
129
+ batchSizeLimit: 20000,
130
+ },
112
131
  });
113
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
132
+ });
133
+
134
+ test('should return responseMessage as empty instead of undefine', async () => {
135
+ expect(mockInitMessage).toHaveBeenCalled();
136
+
137
+ const initResp = await eventProcessor({
138
+ payload: {},
139
+ eventType: TSToChartEvent.InitializeComplete,
140
+ });
141
+ expect(initResp).toEqual({});
114
142
  });
115
143
 
116
144
  test('type check string for visualProps on initialize payload should not throw an error.', async () => {
@@ -141,7 +169,6 @@ describe('CustomChartContext', () => {
141
169
  const chartModel = customChartContext.getChartModel();
142
170
  expect(typeof chartModel.visualProps).toEqual('string');
143
171
  expect(chartModel.visualProps).toEqual('visualPropStringPayload');
144
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
145
172
  });
146
173
 
147
174
  test('type check object for visualProps on initialize payload should not throw an error.', async () => {
@@ -176,7 +203,6 @@ describe('CustomChartContext', () => {
176
203
  expect(chartModel.visualProps).toEqual({
177
204
  data: 'sample data',
178
205
  });
179
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
180
206
  });
181
207
 
182
208
  test('multiple intializations should throw an error', async () => {
@@ -213,6 +239,45 @@ describe('CustomChartContext', () => {
213
239
  }
214
240
  expect(error).toBe(ErrorType.MultipleContextsNotSupported);
215
241
  });
242
+ test('correct app options config should be set on initialize', async () => {
243
+ const mockAppConfigOptions = {
244
+ appOptions: {
245
+ isMobile: false,
246
+ isPrintMode: false,
247
+ isLiveboardContext: false,
248
+ isDebugMode: true,
249
+ },
250
+ };
251
+ expect(mockInitMessage).toHaveBeenCalled();
252
+
253
+ // Call the initialize function and wait for it to resolve
254
+ const promise = customChartContext.initialize();
255
+
256
+ // Check that the hasInitializedPromise has resolved
257
+
258
+ const mockInitializeContextPayloadWithVisualProps = {
259
+ ...mockInitializeContextPayload,
260
+ appConfig: mockAppConfigOptions,
261
+ chartModel: {
262
+ ...mockInitializeContextPayload.chartModel,
263
+ visualProps: {
264
+ data: 'sample data',
265
+ },
266
+ },
267
+ };
268
+
269
+ await eventProcessor({
270
+ payload: mockInitializeContextPayloadWithVisualProps,
271
+ eventType: TSToChartEvent.Initialize,
272
+ });
273
+ eventProcessor({
274
+ payload: {},
275
+ eventType: TSToChartEvent.InitializeComplete,
276
+ });
277
+ await expect(promise).resolves.toBeUndefined();
278
+ const appConfig = customChartContext.getAppConfig();
279
+ expect(appConfig).toStrictEqual(mockAppConfigOptions);
280
+ });
216
281
  });
217
282
 
218
283
  describe('on', () => {
@@ -289,6 +354,53 @@ describe('CustomChartContext', () => {
289
354
  ],
290
355
  });
291
356
  });
357
+ test('TSToChartEvent.ChartConfigValidate validation response for invalid config', async () => {
358
+ // Define initial context with object definitions
359
+ const mockChartConfigValidate = jest
360
+ .fn()
361
+ .mockReturnValue({ isValid: false });
362
+ customChartContext = new CustomChartContext({
363
+ getDefaultChartConfig,
364
+ getQueriesFromChartConfig,
365
+ renderChart,
366
+ visualPropEditorDefinition: { elements: [] },
367
+ chartConfigEditorDefinition: [],
368
+ validateConfig: mockChartConfigValidate,
369
+ });
370
+
371
+ // Trigger event processor with initial context
372
+ const responseWithInitialContext = await eventProcessor({
373
+ payload: mockInitializeContextPayload,
374
+ eventType: TSToChartEvent.ChartConfigValidate,
375
+ source: 'ts-host-app',
376
+ });
377
+ // Verify response with object definitions
378
+ expect(responseWithInitialContext).toStrictEqual({
379
+ isValid: false,
380
+ });
381
+ });
382
+ test('TSToChartEvent.ChartConfigValidate validation response return invalid without validate function', async () => {
383
+ // Define initial context with object definitions
384
+ customChartContext = new CustomChartContext({
385
+ getDefaultChartConfig,
386
+ getQueriesFromChartConfig,
387
+ renderChart,
388
+ visualPropEditorDefinition: { elements: [] },
389
+ chartConfigEditorDefinition: [],
390
+ validateConfig: undefined,
391
+ });
392
+
393
+ // Trigger event processor with initial context
394
+ const responseWithInitialContext = await eventProcessor({
395
+ payload: mockInitializeContextPayload,
396
+ eventType: TSToChartEvent.ChartConfigValidate,
397
+ source: 'ts-host-app',
398
+ });
399
+ // Verify response with object definitions
400
+ expect(responseWithInitialContext).toStrictEqual({
401
+ isValid: false,
402
+ });
403
+ });
292
404
 
293
405
  test('TSToChartEvent.validateVisualProps validation response testing', () => {
294
406
  // Define initial context with object definitions
@@ -348,6 +460,245 @@ describe('CustomChartContext', () => {
348
460
  });
349
461
  });
350
462
 
463
+ test('TSToChartEvent.validateVisualProps should work with activeColumnId', () => {
464
+ // Define initial context with object definitions
465
+ customChartContext = new CustomChartContext({
466
+ getDefaultChartConfig,
467
+ getQueriesFromChartConfig,
468
+ renderChart,
469
+ visualPropEditorDefinition: {
470
+ elements: [mockFormElements],
471
+ columnsVizPropDefinition: [
472
+ {
473
+ type: ColumnType.MEASURE,
474
+ columnSettingsDefinition: {
475
+ 'column-id': { elements: [mockFormElements] },
476
+ },
477
+ },
478
+ ],
479
+ },
480
+ chartConfigEditorDefinition: [],
481
+ });
482
+
483
+ // Trigger event processor with initial context
484
+ const responseWithInitialContext = eventProcessor({
485
+ payload: {
486
+ ...mockInitializeContextPayload,
487
+ activeColumnId: 'column-id',
488
+ },
489
+ eventType: TSToChartEvent.VisualPropsValidate,
490
+ source: 'ts-host-app',
491
+ });
492
+ // Verify response with object definitions
493
+ expect(responseWithInitialContext).toStrictEqual({
494
+ isValid: true,
495
+ visualPropEditorDefinition: {
496
+ elements: [mockFormElements],
497
+ columnsVizPropDefinition: [
498
+ {
499
+ type: ColumnType.MEASURE,
500
+ columnSettingsDefinition: {
501
+ 'column-id': { elements: [mockFormElements] },
502
+ },
503
+ },
504
+ ],
505
+ },
506
+ chartConfigEditorDefinition: [],
507
+ });
508
+ });
509
+
510
+ test('should handle GetColumnData event with valid columnId', async () => {
511
+ // Set up mock data in the chart model
512
+ const mockData = {
513
+ data: [
514
+ {
515
+ data: {
516
+ columns: ['col1', 'col2', 'col3'],
517
+ dataValue: [
518
+ [1, 2, 3],
519
+ [4, 5, 6],
520
+ [7, 8, 9],
521
+ ],
522
+ },
523
+ },
524
+ ],
525
+ };
526
+
527
+ (customChartContext as any).chartModel = mockData;
528
+
529
+ const response = await eventProcessor({
530
+ payload: {
531
+ columnId: 'col2',
532
+ },
533
+ eventType: TSToChartEvent.GetColumnData,
534
+ });
535
+
536
+ expect(response).toEqual({
537
+ data: [2, 5, 8],
538
+ });
539
+ });
540
+
541
+ test('should return empty array for non-existent columnId', async () => {
542
+ // Set up mock data in the chart model
543
+ const mockData = {
544
+ data: [
545
+ {
546
+ data: {
547
+ columns: ['col1', 'col2', 'col3'],
548
+ dataValue: [
549
+ [1, 2, 3],
550
+ [4, 5, 6],
551
+ ],
552
+ },
553
+ },
554
+ ],
555
+ };
556
+
557
+ (customChartContext as any).chartModel = mockData;
558
+
559
+ const response = await eventProcessor({
560
+ payload: {
561
+ columnId: 'non-existent-column',
562
+ },
563
+ eventType: TSToChartEvent.GetColumnData,
564
+ });
565
+
566
+ expect(response).toEqual({
567
+ data: [],
568
+ });
569
+ });
570
+
571
+ test('TSToChartEvent.validateVisualProps should be called with correct activeColumnId', () => {
572
+ // Define initial context with object definitions
573
+ const mockValidateVisualProps = jest
574
+ .fn()
575
+ .mockImplementation(
576
+ (_visualProps, _chartModel, activeColumnId) => {
577
+ if (activeColumnId === 'column-id')
578
+ return { isValid: true };
579
+ return { isValid: false };
580
+ },
581
+ );
582
+ customChartContext = new CustomChartContext({
583
+ getDefaultChartConfig,
584
+ getQueriesFromChartConfig,
585
+ renderChart,
586
+ visualPropEditorDefinition: {
587
+ elements: [mockFormElements],
588
+ columnsVizPropDefinition: [
589
+ {
590
+ type: ColumnType.MEASURE,
591
+ columnSettingsDefinition: {
592
+ 'column-id': { elements: [mockFormElements] },
593
+ },
594
+ },
595
+ ],
596
+ },
597
+ chartConfigEditorDefinition: [],
598
+ validateVisualProps: mockValidateVisualProps,
599
+ });
600
+
601
+ // Trigger event processor with initial context
602
+ const responseWithInitialContext = eventProcessor({
603
+ payload: {
604
+ ...mockInitializeContextPayload,
605
+ activeColumnId: 'column-id',
606
+ },
607
+ eventType: TSToChartEvent.VisualPropsValidate,
608
+ source: 'ts-host-app',
609
+ });
610
+ // we only want the correct active columnId to be passed
611
+ expect(mockValidateVisualProps).toHaveBeenCalledWith(
612
+ undefined,
613
+ {},
614
+ 'column-id',
615
+ );
616
+ const validationResponse = eventProcessor({
617
+ payload: {
618
+ ...mockInitializeContextPayload,
619
+ activeColumnId: 'column-id-1',
620
+ },
621
+ eventType: TSToChartEvent.VisualPropsValidate,
622
+ source: 'ts-host-app',
623
+ });
624
+ expect(validationResponse).toStrictEqual({ isValid: false });
625
+ });
626
+ test('TSToChartEvent.validateVisualProps returns invalid if no function is provided.', () => {
627
+ // Define initial context with object definitions
628
+ customChartContext = new CustomChartContext({
629
+ getDefaultChartConfig,
630
+ getQueriesFromChartConfig,
631
+ renderChart,
632
+ visualPropEditorDefinition: {
633
+ elements: [mockFormElements],
634
+ columnsVizPropDefinition: [
635
+ {
636
+ type: ColumnType.MEASURE,
637
+ columnSettingsDefinition: {
638
+ 'column-id': { elements: [mockFormElements] },
639
+ },
640
+ },
641
+ ],
642
+ },
643
+ chartConfigEditorDefinition: [],
644
+ validateVisualProps: undefined, // mocking undefined value
645
+ });
646
+
647
+ const validationResponse = eventProcessor({
648
+ payload: {
649
+ ...mockInitializeContextPayload,
650
+ },
651
+ eventType: TSToChartEvent.VisualPropsValidate,
652
+ source: 'ts-host-app',
653
+ });
654
+ expect(validationResponse).toStrictEqual({ isValid: false });
655
+ });
656
+ test('VisualPropEditorDefintion function should recieve columnId', () => {
657
+ // Define initial context with object definitions
658
+ const mockValidateVisualProps = jest
659
+ .fn()
660
+ .mockImplementation(
661
+ (_visualProps, _chartModel, activeColumnId) => {
662
+ if (activeColumnId === 'column-id')
663
+ return { isValid: true };
664
+ return { isValid: false };
665
+ },
666
+ );
667
+ const mockVisualPropEditorDefintion = jest.fn().mockReturnValue({
668
+ elements: [mockFormElements],
669
+ columnsVizPropDefinition: [
670
+ {
671
+ type: ColumnType.MEASURE,
672
+ columnSettingsDefinition: {
673
+ 'column-id': { elements: [mockFormElements] },
674
+ },
675
+ },
676
+ ],
677
+ });
678
+ customChartContext = new CustomChartContext({
679
+ getDefaultChartConfig,
680
+ getQueriesFromChartConfig,
681
+ renderChart,
682
+ visualPropEditorDefinition: mockVisualPropEditorDefintion,
683
+ chartConfigEditorDefinition: [],
684
+ validateVisualProps: mockValidateVisualProps,
685
+ });
686
+
687
+ // Trigger event processor with initial context
688
+ const responseWithInitialContext = eventProcessor({
689
+ payload: {
690
+ ...mockInitializeContextPayload,
691
+ activeColumnId: 'column-id',
692
+ },
693
+ eventType: TSToChartEvent.VisualPropsValidate,
694
+ source: 'ts-host-app',
695
+ });
696
+ // we only want the correct active columnId to be passed
697
+ expect(mockVisualPropEditorDefintion.mock.calls[0][2]).toBe(
698
+ 'column-id',
699
+ );
700
+ });
701
+
351
702
  test('should not trigger post message if host is not accurate', async () => {
352
703
  expect(mockInitMessage).toHaveBeenCalled();
353
704
 
@@ -668,7 +1019,6 @@ describe('CustomChartContext', () => {
668
1019
  );
669
1020
 
670
1021
  // Check that the result is defined
671
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
672
1022
  await expect(result).rejects.toBeDefined();
673
1023
  });
674
1024