@thoughtspot/ts-chart-sdk 0.0.2-alpha.8 → 1.0.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 (144) hide show
  1. package/README.md +126 -50
  2. package/dist/ts-chart-sdk.d.ts +337 -31
  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 +15 -3
  8. package/lib/main/custom-chart-context.d.ts.map +1 -1
  9. package/lib/main/custom-chart-context.js +45 -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 +15 -5
  38. package/lib/types/answer-column.types.d.ts.map +1 -1
  39. package/lib/types/answer-column.types.js +10 -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 -5
  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 +3 -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 +19 -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/conditional-formatting/conditional-formatting.spec.js +2 -1
  66. package/lib/utils/conditional-formatting/conditional-formatting.spec.js.map +1 -1
  67. package/lib/utils/date-formatting.d.ts +85 -1
  68. package/lib/utils/date-formatting.d.ts.map +1 -1
  69. package/lib/utils/date-formatting.js +344 -9
  70. package/lib/utils/date-formatting.js.map +1 -1
  71. package/lib/utils/date-formatting.spec.js +303 -32
  72. package/lib/utils/date-formatting.spec.js.map +1 -1
  73. package/lib/utils/date-utils.d.ts +6 -0
  74. package/lib/utils/date-utils.d.ts.map +1 -0
  75. package/lib/utils/date-utils.js +20 -0
  76. package/lib/utils/date-utils.js.map +1 -0
  77. package/lib/utils/date-utils.spec.d.ts +2 -0
  78. package/lib/utils/date-utils.spec.d.ts.map +1 -0
  79. package/lib/utils/date-utils.spec.js +63 -0
  80. package/lib/utils/date-utils.spec.js.map +1 -0
  81. package/lib/utils/formatting-util.d.ts +10 -0
  82. package/lib/utils/formatting-util.d.ts.map +1 -0
  83. package/lib/utils/formatting-util.js +78 -0
  84. package/lib/utils/formatting-util.js.map +1 -0
  85. package/lib/utils/formatting-util.spec.d.ts +2 -0
  86. package/lib/utils/formatting-util.spec.d.ts.map +1 -0
  87. package/lib/utils/formatting-util.spec.js +247 -0
  88. package/lib/utils/formatting-util.spec.js.map +1 -0
  89. package/lib/utils/globalize-Initializer/globalize-utils.d.ts +16 -0
  90. package/lib/utils/globalize-Initializer/globalize-utils.d.ts.map +1 -0
  91. package/lib/utils/globalize-Initializer/globalize-utils.js +101 -0
  92. package/lib/utils/globalize-Initializer/globalize-utils.js.map +1 -0
  93. package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts +2 -0
  94. package/lib/utils/globalize-Initializer/globalize-utils.spec.d.ts.map +1 -0
  95. package/lib/utils/globalize-Initializer/globalize-utils.spec.js +149 -0
  96. package/lib/utils/globalize-Initializer/globalize-utils.spec.js.map +1 -0
  97. package/lib/utils/number-formatting/number-formatting-utils.d.ts +20 -0
  98. package/lib/utils/number-formatting/number-formatting-utils.d.ts.map +1 -0
  99. package/lib/utils/number-formatting/number-formatting-utils.js +159 -0
  100. package/lib/utils/number-formatting/number-formatting-utils.js.map +1 -0
  101. package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts +2 -0
  102. package/lib/utils/number-formatting/number-formatting-utils.spec.d.ts.map +1 -0
  103. package/lib/utils/number-formatting/number-formatting-utils.spec.js +221 -0
  104. package/lib/utils/number-formatting/number-formatting-utils.spec.js.map +1 -0
  105. package/lib/utils/number-formatting/number-formatting.d.ts +5 -0
  106. package/lib/utils/number-formatting/number-formatting.d.ts.map +1 -0
  107. package/lib/utils/number-formatting/number-formatting.js +128 -0
  108. package/lib/utils/number-formatting/number-formatting.js.map +1 -0
  109. package/lib/utils/number-formatting/number-formatting.spec.d.ts +2 -0
  110. package/lib/utils/number-formatting/number-formatting.spec.d.ts.map +1 -0
  111. package/lib/utils/number-formatting/number-formatting.spec.js +159 -0
  112. package/lib/utils/number-formatting/number-formatting.spec.js.map +1 -0
  113. package/package.json +5 -2
  114. package/src/index.ts +3 -0
  115. package/src/main/custom-chart-context.spec.ts +356 -6
  116. package/src/main/custom-chart-context.ts +182 -15
  117. package/src/main/logger.spec.ts +114 -0
  118. package/src/main/logger.ts +97 -0
  119. package/src/main/util.spec.ts +94 -0
  120. package/src/main/util.ts +20 -0
  121. package/src/react/use-custom-chart-context.spec.tsx +0 -1
  122. package/src/react/use-custom-chart-context.tsx +4 -1
  123. package/src/react/use-custom-chart-context.util.ts +6 -3
  124. package/src/types/answer-column.types.ts +29 -6
  125. package/src/types/chart-to-ts-event.types.ts +7 -0
  126. package/src/types/common.types.ts +103 -8
  127. package/src/types/conditional-formatting.types.ts +2 -17
  128. package/src/types/configurator.types.ts +15 -1
  129. package/src/types/number-formatting.types.ts +80 -0
  130. package/src/types/ts-to-chart-event.types.ts +54 -5
  131. package/src/types/visual-prop.types.ts +197 -3
  132. package/src/utils/conditional-formatting/conditional-formatting.spec.ts +2 -0
  133. package/src/utils/date-formatting.spec.ts +377 -32
  134. package/src/utils/date-formatting.ts +587 -14
  135. package/src/utils/date-utils.spec.ts +93 -0
  136. package/src/utils/date-utils.ts +69 -0
  137. package/src/utils/formatting-util.spec.ts +312 -0
  138. package/src/utils/formatting-util.ts +234 -0
  139. package/src/utils/globalize-Initializer/globalize-utils.spec.ts +192 -0
  140. package/src/utils/globalize-Initializer/globalize-utils.ts +216 -0
  141. package/src/utils/number-formatting/number-formatting-utils.spec.ts +296 -0
  142. package/src/utils/number-formatting/number-formatting-utils.ts +260 -0
  143. package/src/utils/number-formatting/number-formatting.spec.ts +243 -0
  144. 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.8",
4
+ "version": "1.0.0",
5
5
  "module": "lib/index",
6
6
  "main": "lib/index",
7
7
  "types": "lib/index",
@@ -29,11 +29,12 @@
29
29
  "publish-dev": "npm publish --tag dev --access public",
30
30
  "about:publish-prod": "echo '===== patch prod workflow ====='",
31
31
  "patch-prod": "npm version prepatch --no-git-tag-version",
32
- "publish-prod": "npm publish --access public"
32
+ "publish-prod": "npm publish --tag latest --access public"
33
33
  },
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,9 +115,29 @@ describe('CustomChartContext', () => {
107
115
  allowedConfigurations: {
108
116
  allowColumnNumberFormatting: false,
109
117
  allowColumnConditionalFormatting: false,
118
+ allowGradientColoring: false,
119
+ allowMeasureNamesAndValues: false,
120
+ },
121
+ chartConfigParameters: {
122
+ measureNameValueColumns: {
123
+ enableMeasureNameColumn: false,
124
+ enableMeasureValueColumn: false,
125
+ measureNameColumnAlias: 'Measure Name',
126
+ measureValueColumnAlias: 'Measure Values',
127
+ },
128
+ batchSizeLimit: 20000,
110
129
  },
111
130
  });
112
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
131
+ });
132
+
133
+ test('should return responseMessage as empty instead of undefine', async () => {
134
+ expect(mockInitMessage).toHaveBeenCalled();
135
+
136
+ const initResp = await eventProcessor({
137
+ payload: {},
138
+ eventType: TSToChartEvent.InitializeComplete,
139
+ });
140
+ expect(initResp).toEqual({});
113
141
  });
114
142
 
115
143
  test('type check string for visualProps on initialize payload should not throw an error.', async () => {
@@ -140,7 +168,6 @@ describe('CustomChartContext', () => {
140
168
  const chartModel = customChartContext.getChartModel();
141
169
  expect(typeof chartModel.visualProps).toEqual('string');
142
170
  expect(chartModel.visualProps).toEqual('visualPropStringPayload');
143
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
144
171
  });
145
172
 
146
173
  test('type check object for visualProps on initialize payload should not throw an error.', async () => {
@@ -175,7 +202,6 @@ describe('CustomChartContext', () => {
175
202
  expect(chartModel.visualProps).toEqual({
176
203
  data: 'sample data',
177
204
  });
178
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
179
205
  });
180
206
 
181
207
  test('multiple intializations should throw an error', async () => {
@@ -212,6 +238,45 @@ describe('CustomChartContext', () => {
212
238
  }
213
239
  expect(error).toBe(ErrorType.MultipleContextsNotSupported);
214
240
  });
241
+ test('correct app options config should be set on initialize', async () => {
242
+ const mockAppConfigOptions = {
243
+ appOptions: {
244
+ isMobile: false,
245
+ isPrintMode: false,
246
+ isLiveboardContext: false,
247
+ isDebugMode: true,
248
+ },
249
+ };
250
+ expect(mockInitMessage).toHaveBeenCalled();
251
+
252
+ // Call the initialize function and wait for it to resolve
253
+ const promise = customChartContext.initialize();
254
+
255
+ // Check that the hasInitializedPromise has resolved
256
+
257
+ const mockInitializeContextPayloadWithVisualProps = {
258
+ ...mockInitializeContextPayload,
259
+ appConfig: mockAppConfigOptions,
260
+ chartModel: {
261
+ ...mockInitializeContextPayload.chartModel,
262
+ visualProps: {
263
+ data: 'sample data',
264
+ },
265
+ },
266
+ };
267
+
268
+ await eventProcessor({
269
+ payload: mockInitializeContextPayloadWithVisualProps,
270
+ eventType: TSToChartEvent.Initialize,
271
+ });
272
+ eventProcessor({
273
+ payload: {},
274
+ eventType: TSToChartEvent.InitializeComplete,
275
+ });
276
+ await expect(promise).resolves.toBeUndefined();
277
+ const appConfig = customChartContext.getAppConfig();
278
+ expect(appConfig).toStrictEqual(mockAppConfigOptions);
279
+ });
215
280
  });
216
281
 
217
282
  describe('on', () => {
@@ -288,6 +353,53 @@ describe('CustomChartContext', () => {
288
353
  ],
289
354
  });
290
355
  });
356
+ test('TSToChartEvent.ChartConfigValidate validation response for invalid config', async () => {
357
+ // Define initial context with object definitions
358
+ const mockChartConfigValidate = jest
359
+ .fn()
360
+ .mockReturnValue({ isValid: false });
361
+ customChartContext = new CustomChartContext({
362
+ getDefaultChartConfig,
363
+ getQueriesFromChartConfig,
364
+ renderChart,
365
+ visualPropEditorDefinition: { elements: [] },
366
+ chartConfigEditorDefinition: [],
367
+ validateConfig: mockChartConfigValidate,
368
+ });
369
+
370
+ // Trigger event processor with initial context
371
+ const responseWithInitialContext = await eventProcessor({
372
+ payload: mockInitializeContextPayload,
373
+ eventType: TSToChartEvent.ChartConfigValidate,
374
+ source: 'ts-host-app',
375
+ });
376
+ // Verify response with object definitions
377
+ expect(responseWithInitialContext).toStrictEqual({
378
+ isValid: false,
379
+ });
380
+ });
381
+ test('TSToChartEvent.ChartConfigValidate validation response return invalid without validate function', async () => {
382
+ // Define initial context with object definitions
383
+ customChartContext = new CustomChartContext({
384
+ getDefaultChartConfig,
385
+ getQueriesFromChartConfig,
386
+ renderChart,
387
+ visualPropEditorDefinition: { elements: [] },
388
+ chartConfigEditorDefinition: [],
389
+ validateConfig: undefined,
390
+ });
391
+
392
+ // Trigger event processor with initial context
393
+ const responseWithInitialContext = await eventProcessor({
394
+ payload: mockInitializeContextPayload,
395
+ eventType: TSToChartEvent.ChartConfigValidate,
396
+ source: 'ts-host-app',
397
+ });
398
+ // Verify response with object definitions
399
+ expect(responseWithInitialContext).toStrictEqual({
400
+ isValid: false,
401
+ });
402
+ });
291
403
 
292
404
  test('TSToChartEvent.validateVisualProps validation response testing', () => {
293
405
  // Define initial context with object definitions
@@ -347,6 +459,245 @@ describe('CustomChartContext', () => {
347
459
  });
348
460
  });
349
461
 
462
+ test('TSToChartEvent.validateVisualProps should work with activeColumnId', () => {
463
+ // Define initial context with object definitions
464
+ customChartContext = new CustomChartContext({
465
+ getDefaultChartConfig,
466
+ getQueriesFromChartConfig,
467
+ renderChart,
468
+ visualPropEditorDefinition: {
469
+ elements: [mockFormElements],
470
+ columnsVizPropDefinition: [
471
+ {
472
+ type: ColumnType.MEASURE,
473
+ columnSettingsDefinition: {
474
+ 'column-id': { elements: [mockFormElements] },
475
+ },
476
+ },
477
+ ],
478
+ },
479
+ chartConfigEditorDefinition: [],
480
+ });
481
+
482
+ // Trigger event processor with initial context
483
+ const responseWithInitialContext = eventProcessor({
484
+ payload: {
485
+ ...mockInitializeContextPayload,
486
+ activeColumnId: 'column-id',
487
+ },
488
+ eventType: TSToChartEvent.VisualPropsValidate,
489
+ source: 'ts-host-app',
490
+ });
491
+ // Verify response with object definitions
492
+ expect(responseWithInitialContext).toStrictEqual({
493
+ isValid: true,
494
+ visualPropEditorDefinition: {
495
+ elements: [mockFormElements],
496
+ columnsVizPropDefinition: [
497
+ {
498
+ type: ColumnType.MEASURE,
499
+ columnSettingsDefinition: {
500
+ 'column-id': { elements: [mockFormElements] },
501
+ },
502
+ },
503
+ ],
504
+ },
505
+ chartConfigEditorDefinition: [],
506
+ });
507
+ });
508
+
509
+ test('should handle GetColumnData event with valid columnId', async () => {
510
+ // Set up mock data in the chart model
511
+ const mockData = {
512
+ data: [
513
+ {
514
+ data: {
515
+ columns: ['col1', 'col2', 'col3'],
516
+ dataValue: [
517
+ [1, 2, 3],
518
+ [4, 5, 6],
519
+ [7, 8, 9],
520
+ ],
521
+ },
522
+ },
523
+ ],
524
+ };
525
+
526
+ (customChartContext as any).chartModel = mockData;
527
+
528
+ const response = await eventProcessor({
529
+ payload: {
530
+ columnId: 'col2',
531
+ },
532
+ eventType: TSToChartEvent.GetColumnData,
533
+ });
534
+
535
+ expect(response).toEqual({
536
+ data: [2, 5, 8],
537
+ });
538
+ });
539
+
540
+ test('should return empty array for non-existent columnId', async () => {
541
+ // Set up mock data in the chart model
542
+ const mockData = {
543
+ data: [
544
+ {
545
+ data: {
546
+ columns: ['col1', 'col2', 'col3'],
547
+ dataValue: [
548
+ [1, 2, 3],
549
+ [4, 5, 6],
550
+ ],
551
+ },
552
+ },
553
+ ],
554
+ };
555
+
556
+ (customChartContext as any).chartModel = mockData;
557
+
558
+ const response = await eventProcessor({
559
+ payload: {
560
+ columnId: 'non-existent-column',
561
+ },
562
+ eventType: TSToChartEvent.GetColumnData,
563
+ });
564
+
565
+ expect(response).toEqual({
566
+ data: [],
567
+ });
568
+ });
569
+
570
+ test('TSToChartEvent.validateVisualProps should be called with correct activeColumnId', () => {
571
+ // Define initial context with object definitions
572
+ const mockValidateVisualProps = jest
573
+ .fn()
574
+ .mockImplementation(
575
+ (_visualProps, _chartModel, activeColumnId) => {
576
+ if (activeColumnId === 'column-id')
577
+ return { isValid: true };
578
+ return { isValid: false };
579
+ },
580
+ );
581
+ customChartContext = new CustomChartContext({
582
+ getDefaultChartConfig,
583
+ getQueriesFromChartConfig,
584
+ renderChart,
585
+ visualPropEditorDefinition: {
586
+ elements: [mockFormElements],
587
+ columnsVizPropDefinition: [
588
+ {
589
+ type: ColumnType.MEASURE,
590
+ columnSettingsDefinition: {
591
+ 'column-id': { elements: [mockFormElements] },
592
+ },
593
+ },
594
+ ],
595
+ },
596
+ chartConfigEditorDefinition: [],
597
+ validateVisualProps: mockValidateVisualProps,
598
+ });
599
+
600
+ // Trigger event processor with initial context
601
+ const responseWithInitialContext = eventProcessor({
602
+ payload: {
603
+ ...mockInitializeContextPayload,
604
+ activeColumnId: 'column-id',
605
+ },
606
+ eventType: TSToChartEvent.VisualPropsValidate,
607
+ source: 'ts-host-app',
608
+ });
609
+ // we only want the correct active columnId to be passed
610
+ expect(mockValidateVisualProps).toHaveBeenCalledWith(
611
+ undefined,
612
+ {},
613
+ 'column-id',
614
+ );
615
+ const validationResponse = eventProcessor({
616
+ payload: {
617
+ ...mockInitializeContextPayload,
618
+ activeColumnId: 'column-id-1',
619
+ },
620
+ eventType: TSToChartEvent.VisualPropsValidate,
621
+ source: 'ts-host-app',
622
+ });
623
+ expect(validationResponse).toStrictEqual({ isValid: false });
624
+ });
625
+ test('TSToChartEvent.validateVisualProps returns invalid if no function is provided.', () => {
626
+ // Define initial context with object definitions
627
+ customChartContext = new CustomChartContext({
628
+ getDefaultChartConfig,
629
+ getQueriesFromChartConfig,
630
+ renderChart,
631
+ visualPropEditorDefinition: {
632
+ elements: [mockFormElements],
633
+ columnsVizPropDefinition: [
634
+ {
635
+ type: ColumnType.MEASURE,
636
+ columnSettingsDefinition: {
637
+ 'column-id': { elements: [mockFormElements] },
638
+ },
639
+ },
640
+ ],
641
+ },
642
+ chartConfigEditorDefinition: [],
643
+ validateVisualProps: undefined, // mocking undefined value
644
+ });
645
+
646
+ const validationResponse = eventProcessor({
647
+ payload: {
648
+ ...mockInitializeContextPayload,
649
+ },
650
+ eventType: TSToChartEvent.VisualPropsValidate,
651
+ source: 'ts-host-app',
652
+ });
653
+ expect(validationResponse).toStrictEqual({ isValid: false });
654
+ });
655
+ test('VisualPropEditorDefintion function should recieve columnId', () => {
656
+ // Define initial context with object definitions
657
+ const mockValidateVisualProps = jest
658
+ .fn()
659
+ .mockImplementation(
660
+ (_visualProps, _chartModel, activeColumnId) => {
661
+ if (activeColumnId === 'column-id')
662
+ return { isValid: true };
663
+ return { isValid: false };
664
+ },
665
+ );
666
+ const mockVisualPropEditorDefintion = jest.fn().mockReturnValue({
667
+ elements: [mockFormElements],
668
+ columnsVizPropDefinition: [
669
+ {
670
+ type: ColumnType.MEASURE,
671
+ columnSettingsDefinition: {
672
+ 'column-id': { elements: [mockFormElements] },
673
+ },
674
+ },
675
+ ],
676
+ });
677
+ customChartContext = new CustomChartContext({
678
+ getDefaultChartConfig,
679
+ getQueriesFromChartConfig,
680
+ renderChart,
681
+ visualPropEditorDefinition: mockVisualPropEditorDefintion,
682
+ chartConfigEditorDefinition: [],
683
+ validateVisualProps: mockValidateVisualProps,
684
+ });
685
+
686
+ // Trigger event processor with initial context
687
+ const responseWithInitialContext = eventProcessor({
688
+ payload: {
689
+ ...mockInitializeContextPayload,
690
+ activeColumnId: 'column-id',
691
+ },
692
+ eventType: TSToChartEvent.VisualPropsValidate,
693
+ source: 'ts-host-app',
694
+ });
695
+ // we only want the correct active columnId to be passed
696
+ expect(mockVisualPropEditorDefintion.mock.calls[0][2]).toBe(
697
+ 'column-id',
698
+ );
699
+ });
700
+
350
701
  test('should not trigger post message if host is not accurate', async () => {
351
702
  expect(mockInitMessage).toHaveBeenCalled();
352
703
 
@@ -667,7 +1018,6 @@ describe('CustomChartContext', () => {
667
1018
  );
668
1019
 
669
1020
  // Check that the result is defined
670
- expect(mockPostMessageToHost).not.toHaveBeenCalled();
671
1021
  await expect(result).rejects.toBeDefined();
672
1022
  });
673
1023