@thoughtspot/visual-embed-sdk 1.42.3 → 1.43.1

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 (178) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/api-intercept.d.ts +51 -0
  3. package/cjs/src/api-intercept.d.ts.map +1 -0
  4. package/cjs/src/api-intercept.js +180 -0
  5. package/cjs/src/api-intercept.js.map +1 -0
  6. package/cjs/src/api-intercept.spec.d.ts +2 -0
  7. package/cjs/src/api-intercept.spec.d.ts.map +1 -0
  8. package/cjs/src/api-intercept.spec.js +672 -0
  9. package/cjs/src/api-intercept.spec.js.map +1 -0
  10. package/cjs/src/css-variables.d.ts +4 -0
  11. package/cjs/src/css-variables.d.ts.map +1 -1
  12. package/cjs/src/embed/app.d.ts +0 -5
  13. package/cjs/src/embed/app.d.ts.map +1 -1
  14. package/cjs/src/embed/app.js +4 -5
  15. package/cjs/src/embed/app.js.map +1 -1
  16. package/cjs/src/embed/app.spec.js +10 -0
  17. package/cjs/src/embed/app.spec.js.map +1 -1
  18. package/cjs/src/embed/conversation.d.ts +2 -2
  19. package/cjs/src/embed/conversation.js +1 -1
  20. package/cjs/src/embed/conversation.js.map +1 -1
  21. package/cjs/src/embed/conversation.spec.js +17 -0
  22. package/cjs/src/embed/conversation.spec.js.map +1 -1
  23. package/cjs/src/embed/hostEventClient/contracts.d.ts +11 -1
  24. package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  25. package/cjs/src/embed/hostEventClient/contracts.js +1 -0
  26. package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
  27. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  28. package/cjs/src/embed/liveboard.js +4 -2
  29. package/cjs/src/embed/liveboard.js.map +1 -1
  30. package/cjs/src/embed/liveboard.spec.js +11 -0
  31. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  32. package/cjs/src/embed/search.d.ts +0 -7
  33. package/cjs/src/embed/search.d.ts.map +1 -1
  34. package/cjs/src/embed/search.js +1 -4
  35. package/cjs/src/embed/search.js.map +1 -1
  36. package/cjs/src/embed/ts-embed.d.ts +10 -0
  37. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  38. package/cjs/src/embed/ts-embed.js +56 -15
  39. package/cjs/src/embed/ts-embed.js.map +1 -1
  40. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  41. package/cjs/src/embed/ts-embed.spec.js +412 -238
  42. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  43. package/cjs/src/index.d.ts +2 -2
  44. package/cjs/src/index.d.ts.map +1 -1
  45. package/cjs/src/index.js +2 -1
  46. package/cjs/src/index.js.map +1 -1
  47. package/cjs/src/react/all-types-export.d.ts +1 -1
  48. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  49. package/cjs/src/react/all-types-export.js +2 -1
  50. package/cjs/src/react/all-types-export.js.map +1 -1
  51. package/cjs/src/types.d.ts +328 -103
  52. package/cjs/src/types.d.ts.map +1 -1
  53. package/cjs/src/types.js +265 -85
  54. package/cjs/src/types.js.map +1 -1
  55. package/cjs/src/utils/logger.d.ts.map +1 -1
  56. package/cjs/src/utils/logger.js +1 -2
  57. package/cjs/src/utils/logger.js.map +1 -1
  58. package/cjs/src/utils/processData.d.ts +1 -1
  59. package/cjs/src/utils/processData.d.ts.map +1 -1
  60. package/cjs/src/utils/processData.js +8 -8
  61. package/cjs/src/utils/processData.js.map +1 -1
  62. package/cjs/src/utils/processData.spec.js.map +1 -1
  63. package/dist/{index-SVcLgSqi.js → index-CpkMygsc.js} +1 -1
  64. package/dist/src/api-intercept.d.ts +51 -0
  65. package/dist/src/api-intercept.d.ts.map +1 -0
  66. package/dist/src/api-intercept.spec.d.ts +2 -0
  67. package/dist/src/api-intercept.spec.d.ts.map +1 -0
  68. package/dist/src/css-variables.d.ts +4 -0
  69. package/dist/src/css-variables.d.ts.map +1 -1
  70. package/dist/src/embed/app.d.ts +0 -5
  71. package/dist/src/embed/app.d.ts.map +1 -1
  72. package/dist/src/embed/conversation.d.ts +2 -2
  73. package/dist/src/embed/hostEventClient/contracts.d.ts +11 -1
  74. package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  75. package/dist/src/embed/liveboard.d.ts.map +1 -1
  76. package/dist/src/embed/search.d.ts +0 -7
  77. package/dist/src/embed/search.d.ts.map +1 -1
  78. package/dist/src/embed/ts-embed.d.ts +10 -0
  79. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  80. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  81. package/dist/src/index.d.ts +2 -2
  82. package/dist/src/index.d.ts.map +1 -1
  83. package/dist/src/react/all-types-export.d.ts +1 -1
  84. package/dist/src/react/all-types-export.d.ts.map +1 -1
  85. package/dist/src/types.d.ts +328 -103
  86. package/dist/src/types.d.ts.map +1 -1
  87. package/dist/src/utils/logger.d.ts.map +1 -1
  88. package/dist/src/utils/processData.d.ts +1 -1
  89. package/dist/src/utils/processData.d.ts.map +1 -1
  90. package/dist/tsembed-react.es.js +519 -133
  91. package/dist/tsembed-react.js +518 -132
  92. package/dist/tsembed.es.js +2642 -2256
  93. package/dist/tsembed.js +2640 -2254
  94. package/dist/visual-embed-sdk-react-full.d.ts +355 -118
  95. package/dist/visual-embed-sdk-react.d.ts +352 -118
  96. package/dist/visual-embed-sdk.d.ts +355 -118
  97. package/lib/package.json +1 -1
  98. package/lib/src/api-intercept.d.ts +51 -0
  99. package/lib/src/api-intercept.d.ts.map +1 -0
  100. package/lib/src/api-intercept.js +173 -0
  101. package/lib/src/api-intercept.js.map +1 -0
  102. package/lib/src/api-intercept.spec.d.ts +2 -0
  103. package/lib/src/api-intercept.spec.d.ts.map +1 -0
  104. package/lib/src/api-intercept.spec.js +669 -0
  105. package/lib/src/api-intercept.spec.js.map +1 -0
  106. package/lib/src/css-variables.d.ts +4 -0
  107. package/lib/src/css-variables.d.ts.map +1 -1
  108. package/lib/src/embed/app.d.ts +0 -5
  109. package/lib/src/embed/app.d.ts.map +1 -1
  110. package/lib/src/embed/app.js +4 -5
  111. package/lib/src/embed/app.js.map +1 -1
  112. package/lib/src/embed/app.spec.js +10 -0
  113. package/lib/src/embed/app.spec.js.map +1 -1
  114. package/lib/src/embed/conversation.d.ts +2 -2
  115. package/lib/src/embed/conversation.js +1 -1
  116. package/lib/src/embed/conversation.js.map +1 -1
  117. package/lib/src/embed/conversation.spec.js +17 -0
  118. package/lib/src/embed/conversation.spec.js.map +1 -1
  119. package/lib/src/embed/hostEventClient/contracts.d.ts +11 -1
  120. package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  121. package/lib/src/embed/hostEventClient/contracts.js +1 -0
  122. package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
  123. package/lib/src/embed/liveboard.d.ts.map +1 -1
  124. package/lib/src/embed/liveboard.js +4 -2
  125. package/lib/src/embed/liveboard.js.map +1 -1
  126. package/lib/src/embed/liveboard.spec.js +11 -0
  127. package/lib/src/embed/liveboard.spec.js.map +1 -1
  128. package/lib/src/embed/search.d.ts +0 -7
  129. package/lib/src/embed/search.d.ts.map +1 -1
  130. package/lib/src/embed/search.js +1 -4
  131. package/lib/src/embed/search.js.map +1 -1
  132. package/lib/src/embed/ts-embed.d.ts +10 -0
  133. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  134. package/lib/src/embed/ts-embed.js +56 -15
  135. package/lib/src/embed/ts-embed.js.map +1 -1
  136. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  137. package/lib/src/embed/ts-embed.spec.js +412 -238
  138. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  139. package/lib/src/index.d.ts +2 -2
  140. package/lib/src/index.d.ts.map +1 -1
  141. package/lib/src/index.js +2 -2
  142. package/lib/src/index.js.map +1 -1
  143. package/lib/src/react/all-types-export.d.ts +1 -1
  144. package/lib/src/react/all-types-export.d.ts.map +1 -1
  145. package/lib/src/react/all-types-export.js +1 -1
  146. package/lib/src/react/all-types-export.js.map +1 -1
  147. package/lib/src/types.d.ts +328 -103
  148. package/lib/src/types.d.ts.map +1 -1
  149. package/lib/src/types.js +264 -84
  150. package/lib/src/types.js.map +1 -1
  151. package/lib/src/utils/logger.d.ts.map +1 -1
  152. package/lib/src/utils/logger.js +1 -2
  153. package/lib/src/utils/logger.js.map +1 -1
  154. package/lib/src/utils/processData.d.ts +1 -1
  155. package/lib/src/utils/processData.d.ts.map +1 -1
  156. package/lib/src/utils/processData.js +8 -8
  157. package/lib/src/utils/processData.js.map +1 -1
  158. package/lib/src/utils/processData.spec.js.map +1 -1
  159. package/package.json +1 -1
  160. package/src/api-intercept.spec.ts +856 -0
  161. package/src/api-intercept.ts +204 -0
  162. package/src/css-variables.ts +5 -0
  163. package/src/embed/app.spec.ts +11 -0
  164. package/src/embed/app.ts +5 -16
  165. package/src/embed/conversation.spec.ts +22 -0
  166. package/src/embed/conversation.ts +3 -3
  167. package/src/embed/hostEventClient/contracts.ts +10 -0
  168. package/src/embed/liveboard.spec.ts +12 -0
  169. package/src/embed/liveboard.ts +6 -2
  170. package/src/embed/search.ts +1 -14
  171. package/src/embed/ts-embed.spec.ts +498 -250
  172. package/src/embed/ts-embed.ts +80 -32
  173. package/src/index.ts +2 -0
  174. package/src/react/all-types-export.ts +1 -0
  175. package/src/types.ts +410 -179
  176. package/src/utils/logger.ts +1 -2
  177. package/src/utils/processData.spec.ts +0 -1
  178. package/src/utils/processData.ts +10 -11
@@ -0,0 +1,672 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const apiIntercept = tslib_1.__importStar(require("./api-intercept"));
5
+ const config = tslib_1.__importStar(require("./config"));
6
+ const embedConfig = tslib_1.__importStar(require("./embed/embedConfig"));
7
+ const types_1 = require("./types");
8
+ const utils_1 = require("./utils");
9
+ const logger_1 = require("./utils/logger");
10
+ jest.mock('./config');
11
+ jest.mock('./embed/embedConfig');
12
+ jest.mock('./utils/logger');
13
+ const mockGetThoughtSpotHost = config.getThoughtSpotHost;
14
+ const mockGetEmbedConfig = embedConfig.getEmbedConfig;
15
+ const mockLogger = logger_1.logger;
16
+ describe('api-intercept', () => {
17
+ const thoughtSpotHost = 'https://test.thoughtspot.com';
18
+ let originalJsonParse;
19
+ beforeAll(() => {
20
+ originalJsonParse = JSON.parse;
21
+ });
22
+ beforeEach(() => {
23
+ jest.clearAllMocks();
24
+ mockGetThoughtSpotHost.mockReturnValue(thoughtSpotHost);
25
+ mockGetEmbedConfig.mockReturnValue({});
26
+ // Restore JSON.parse before each test
27
+ JSON.parse = originalJsonParse;
28
+ });
29
+ afterEach(() => {
30
+ // Ensure JSON.parse is restored after each test
31
+ JSON.parse = originalJsonParse;
32
+ });
33
+ describe('getInterceptInitData', () => {
34
+ it('should return default intercept flags when no intercepts are configured', () => {
35
+ const viewConfig = {};
36
+ const result = apiIntercept.getInterceptInitData(viewConfig);
37
+ expect(result).toEqual({
38
+ interceptUrls: [],
39
+ interceptTimeout: undefined,
40
+ });
41
+ });
42
+ it('should expand InterceptedApiType.AnswerData to specific URLs', () => {
43
+ const viewConfig = {
44
+ interceptUrls: [types_1.InterceptedApiType.AnswerData]
45
+ };
46
+ const result = apiIntercept.getInterceptInitData(viewConfig);
47
+ expect(result.interceptUrls).toEqual([
48
+ `${thoughtSpotHost}/prism/?op=GetChartWithData`,
49
+ `${thoughtSpotHost}/prism/?op=GetTableWithHeadlineData`,
50
+ `${thoughtSpotHost}/prism/?op=GetTableWithData`,
51
+ ]);
52
+ });
53
+ it('should expand InterceptedApiType.LiveboardData to specific URLs', () => {
54
+ const viewConfig = {
55
+ interceptUrls: [types_1.InterceptedApiType.LiveboardData]
56
+ };
57
+ const result = apiIntercept.getInterceptInitData(viewConfig);
58
+ expect(result.interceptUrls).toEqual([
59
+ `${thoughtSpotHost}/prism/?op=LoadContextBook`
60
+ ]);
61
+ });
62
+ it('should handle multiple intercept types', () => {
63
+ const viewConfig = {
64
+ interceptUrls: [
65
+ types_1.InterceptedApiType.AnswerData,
66
+ types_1.InterceptedApiType.LiveboardData
67
+ ]
68
+ };
69
+ const result = apiIntercept.getInterceptInitData(viewConfig);
70
+ expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
71
+ expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=LoadContextBook`);
72
+ expect(result.interceptUrls.length).toBe(4);
73
+ });
74
+ it('should handle custom URL strings', () => {
75
+ const customUrl = '/api/custom-endpoint';
76
+ const viewConfig = {
77
+ interceptUrls: [customUrl]
78
+ };
79
+ const result = apiIntercept.getInterceptInitData(viewConfig);
80
+ expect(result.interceptUrls).toEqual([`${thoughtSpotHost}${customUrl}`]);
81
+ });
82
+ it('should handle full URL strings', () => {
83
+ const fullUrl = 'https://example.com/api/endpoint';
84
+ const viewConfig = {
85
+ interceptUrls: [fullUrl]
86
+ };
87
+ const result = apiIntercept.getInterceptInitData(viewConfig);
88
+ expect(result.interceptUrls).toEqual([fullUrl]);
89
+ });
90
+ it('should handle InterceptedApiType.ALL', () => {
91
+ const viewConfig = {
92
+ interceptUrls: [types_1.InterceptedApiType.ALL]
93
+ };
94
+ const result = apiIntercept.getInterceptInitData(viewConfig);
95
+ expect(result.interceptUrls).toEqual([types_1.InterceptedApiType.ALL]);
96
+ });
97
+ it('should prioritize ALL over other intercept types', () => {
98
+ const viewConfig = {
99
+ interceptUrls: [
100
+ types_1.InterceptedApiType.AnswerData,
101
+ types_1.InterceptedApiType.ALL,
102
+ '/api/custom'
103
+ ]
104
+ };
105
+ const result = apiIntercept.getInterceptInitData(viewConfig);
106
+ expect(result.interceptUrls).toEqual([types_1.InterceptedApiType.ALL]);
107
+ });
108
+ it('should handle legacy isOnBeforeGetVizDataInterceptEnabled flag', () => {
109
+ const viewConfig = {
110
+ isOnBeforeGetVizDataInterceptEnabled: true
111
+ };
112
+ const result = apiIntercept.getInterceptInitData(viewConfig);
113
+ expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
114
+ });
115
+ it('should combine legacy flag with interceptUrls', () => {
116
+ const viewConfig = {
117
+ isOnBeforeGetVizDataInterceptEnabled: true,
118
+ interceptUrls: [types_1.InterceptedApiType.LiveboardData]
119
+ };
120
+ const result = apiIntercept.getInterceptInitData(viewConfig);
121
+ expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
122
+ expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=LoadContextBook`);
123
+ });
124
+ it('should pass through interceptTimeout', () => {
125
+ const viewConfig = {
126
+ interceptUrls: [],
127
+ interceptTimeout: 5000
128
+ };
129
+ const result = apiIntercept.getInterceptInitData(viewConfig);
130
+ expect(result.interceptTimeout).toBe(5000);
131
+ });
132
+ it('should deduplicate URLs when same type is added multiple times', () => {
133
+ const viewConfig = {
134
+ interceptUrls: [
135
+ types_1.InterceptedApiType.AnswerData,
136
+ types_1.InterceptedApiType.AnswerData
137
+ ]
138
+ };
139
+ const result = apiIntercept.getInterceptInitData(viewConfig);
140
+ expect(result.interceptUrls.length).toBe(3); // 3 answer data URLs
141
+ });
142
+ });
143
+ describe('handleInterceptEvent', () => {
144
+ let executeEvent;
145
+ let getUnsavedAnswerTml;
146
+ let viewConfig;
147
+ beforeEach(() => {
148
+ executeEvent = jest.fn();
149
+ getUnsavedAnswerTml = jest.fn().mockResolvedValue({ answer: { tml: 'test-tml' } });
150
+ viewConfig = {};
151
+ });
152
+ it('should handle valid intercept data', async () => {
153
+ const eventData = {
154
+ data: JSON.stringify({
155
+ input: '/prism/?op=GetChartWithData',
156
+ init: {
157
+ method: 'POST',
158
+ body: JSON.stringify({
159
+ variables: {
160
+ session: { sessionId: 'session-123' },
161
+ contextBookId: 'viz-456'
162
+ }
163
+ })
164
+ }
165
+ })
166
+ };
167
+ await apiIntercept.handleInterceptEvent({
168
+ eventData,
169
+ executeEvent,
170
+ viewConfig,
171
+ getUnsavedAnswerTml
172
+ });
173
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.objectContaining({
174
+ input: '/prism/?op=GetChartWithData',
175
+ urlType: types_1.InterceptedApiType.AnswerData
176
+ }));
177
+ });
178
+ it('should trigger legacy OnBeforeGetVizDataIntercept for answer data URLs', async () => {
179
+ viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
180
+ const eventData = {
181
+ data: JSON.stringify({
182
+ input: '/prism/?op=GetChartWithData',
183
+ init: {
184
+ method: 'POST',
185
+ body: JSON.stringify({
186
+ variables: {
187
+ session: { sessionId: 'session-123' },
188
+ contextBookId: 'viz-456'
189
+ }
190
+ })
191
+ }
192
+ })
193
+ };
194
+ await apiIntercept.handleInterceptEvent({
195
+ eventData,
196
+ executeEvent,
197
+ viewConfig,
198
+ getUnsavedAnswerTml
199
+ });
200
+ expect(getUnsavedAnswerTml).toHaveBeenCalledWith({
201
+ sessionId: 'session-123',
202
+ vizId: 'viz-456'
203
+ });
204
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.OnBeforeGetVizDataIntercept, {
205
+ data: {
206
+ data: { answer: { tml: 'test-tml' } },
207
+ status: utils_1.embedEventStatus.END,
208
+ type: types_1.EmbedEvent.OnBeforeGetVizDataIntercept
209
+ }
210
+ });
211
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.any(Object));
212
+ });
213
+ it('should not trigger legacy intercept for non-answer data URLs', async () => {
214
+ viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
215
+ const eventData = {
216
+ data: JSON.stringify({
217
+ input: '/prism/?op=LoadContextBook',
218
+ init: {
219
+ method: 'POST',
220
+ body: '{}'
221
+ }
222
+ })
223
+ };
224
+ await apiIntercept.handleInterceptEvent({
225
+ eventData,
226
+ executeEvent,
227
+ viewConfig,
228
+ getUnsavedAnswerTml
229
+ });
230
+ expect(getUnsavedAnswerTml).not.toHaveBeenCalled();
231
+ expect(executeEvent).toHaveBeenCalledTimes(1);
232
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.any(Object));
233
+ });
234
+ it('should handle GetTableWithHeadlineData URL as answer data', async () => {
235
+ viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
236
+ const eventData = {
237
+ data: JSON.stringify({
238
+ input: '/prism/?op=GetTableWithHeadlineData',
239
+ init: {
240
+ body: JSON.stringify({
241
+ variables: { session: { sessionId: 'test' } }
242
+ })
243
+ }
244
+ })
245
+ };
246
+ await apiIntercept.handleInterceptEvent({
247
+ eventData,
248
+ executeEvent,
249
+ viewConfig,
250
+ getUnsavedAnswerTml
251
+ });
252
+ expect(getUnsavedAnswerTml).toHaveBeenCalled();
253
+ });
254
+ it('should handle GetTableWithData URL as answer data', async () => {
255
+ viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
256
+ const eventData = {
257
+ data: JSON.stringify({
258
+ input: '/prism/?op=GetTableWithData',
259
+ init: {
260
+ body: JSON.stringify({
261
+ variables: { session: { sessionId: 'test' } }
262
+ })
263
+ }
264
+ })
265
+ };
266
+ await apiIntercept.handleInterceptEvent({
267
+ eventData,
268
+ executeEvent,
269
+ viewConfig,
270
+ getUnsavedAnswerTml
271
+ });
272
+ expect(getUnsavedAnswerTml).toHaveBeenCalled();
273
+ });
274
+ it('should handle invalid JSON in event data', async () => {
275
+ const eventData = {
276
+ data: 'invalid-json'
277
+ };
278
+ await apiIntercept.handleInterceptEvent({
279
+ eventData,
280
+ executeEvent,
281
+ viewConfig,
282
+ getUnsavedAnswerTml
283
+ });
284
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.Error, { error: 'Error parsing api intercept body' });
285
+ expect(mockLogger.error).toHaveBeenCalled();
286
+ });
287
+ it('should handle init with non-JSON body', async () => {
288
+ const eventData = {
289
+ data: JSON.stringify({
290
+ input: '/api/test',
291
+ init: {
292
+ method: 'POST',
293
+ body: 'plain-text-body'
294
+ }
295
+ })
296
+ };
297
+ await apiIntercept.handleInterceptEvent({
298
+ eventData,
299
+ executeEvent,
300
+ viewConfig,
301
+ getUnsavedAnswerTml
302
+ });
303
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.objectContaining({
304
+ init: expect.objectContaining({
305
+ body: 'plain-text-body'
306
+ })
307
+ }));
308
+ });
309
+ it('should handle malformed event data structure with property access error', async () => {
310
+ // Create an object with a getter that throws when accessing 'input'
311
+ global.JSON.parse = jest.fn().mockImplementationOnce((str) => {
312
+ // Return an object with a getter that throws
313
+ return new Proxy({}, {
314
+ get(target, prop) {
315
+ if (prop === 'input') {
316
+ throw new Error('Property access error');
317
+ }
318
+ return undefined;
319
+ }
320
+ });
321
+ });
322
+ const eventData = {
323
+ data: JSON.stringify({ input: '/test', init: {} })
324
+ };
325
+ await apiIntercept.handleInterceptEvent({
326
+ eventData,
327
+ executeEvent,
328
+ viewConfig,
329
+ getUnsavedAnswerTml
330
+ });
331
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.Error, { error: 'Error parsing api intercept body' });
332
+ expect(mockLogger.error).toHaveBeenCalled();
333
+ // Explicitly restore for this test
334
+ global.JSON.parse = originalJsonParse;
335
+ });
336
+ it('should determine urlType as ALL for unknown URLs', async () => {
337
+ const eventData = {
338
+ data: JSON.stringify({
339
+ input: '/unknown/endpoint',
340
+ init: { method: 'GET' }
341
+ })
342
+ };
343
+ await apiIntercept.handleInterceptEvent({
344
+ eventData,
345
+ executeEvent,
346
+ viewConfig,
347
+ getUnsavedAnswerTml
348
+ });
349
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.objectContaining({
350
+ urlType: types_1.InterceptedApiType.ALL
351
+ }));
352
+ });
353
+ it('should determine urlType as LiveboardData for liveboard URLs', async () => {
354
+ const eventData = {
355
+ data: JSON.stringify({
356
+ input: '/prism/?op=LoadContextBook',
357
+ init: { method: 'POST' }
358
+ })
359
+ };
360
+ await apiIntercept.handleInterceptEvent({
361
+ eventData,
362
+ executeEvent,
363
+ viewConfig,
364
+ getUnsavedAnswerTml
365
+ });
366
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.objectContaining({
367
+ urlType: types_1.InterceptedApiType.LiveboardData
368
+ }));
369
+ });
370
+ it('should handle event data with missing init', async () => {
371
+ const eventData = {
372
+ data: JSON.stringify({
373
+ input: '/prism/?op=GetChartWithData'
374
+ })
375
+ };
376
+ await apiIntercept.handleInterceptEvent({
377
+ eventData,
378
+ executeEvent,
379
+ viewConfig,
380
+ getUnsavedAnswerTml
381
+ });
382
+ // When init is missing, accessing init.body throws an error
383
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.Error, { error: 'Error parsing api intercept body' });
384
+ });
385
+ it('should handle event data with missing body', async () => {
386
+ const eventData = {
387
+ data: JSON.stringify({
388
+ input: '/prism/?op=GetChartWithData',
389
+ init: {}
390
+ })
391
+ };
392
+ await apiIntercept.handleInterceptEvent({
393
+ eventData,
394
+ executeEvent,
395
+ viewConfig,
396
+ getUnsavedAnswerTml
397
+ });
398
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.any(Object));
399
+ });
400
+ it('should handle event data with missing variables in body', async () => {
401
+ const eventData = {
402
+ data: JSON.stringify({
403
+ input: '/prism/?op=GetChartWithData',
404
+ init: {
405
+ body: JSON.stringify({})
406
+ }
407
+ })
408
+ };
409
+ await apiIntercept.handleInterceptEvent({
410
+ eventData,
411
+ executeEvent,
412
+ viewConfig,
413
+ getUnsavedAnswerTml
414
+ });
415
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.any(Object));
416
+ });
417
+ it('should handle event data with missing session in variables', async () => {
418
+ const eventData = {
419
+ data: JSON.stringify({
420
+ input: '/prism/?op=GetChartWithData',
421
+ init: {
422
+ body: JSON.stringify({
423
+ variables: {}
424
+ })
425
+ }
426
+ })
427
+ };
428
+ await apiIntercept.handleInterceptEvent({
429
+ eventData,
430
+ executeEvent,
431
+ viewConfig,
432
+ getUnsavedAnswerTml
433
+ });
434
+ expect(executeEvent).toHaveBeenCalledWith(types_1.EmbedEvent.ApiIntercept, expect.any(Object));
435
+ });
436
+ });
437
+ describe('processApiInterceptResponse', () => {
438
+ it('should process legacy format with error', () => {
439
+ const legacyPayload = {
440
+ data: {
441
+ error: {
442
+ errorText: 'Test Error',
443
+ errorDescription: 'Test Description'
444
+ },
445
+ execute: false
446
+ }
447
+ };
448
+ const result = apiIntercept.processApiInterceptResponse(legacyPayload);
449
+ expect(result).toEqual({
450
+ data: {
451
+ execute: false,
452
+ response: {
453
+ body: {
454
+ errors: [
455
+ {
456
+ title: 'Test Error',
457
+ description: 'Test Description',
458
+ isUserError: true,
459
+ },
460
+ ],
461
+ data: {},
462
+ },
463
+ },
464
+ }
465
+ });
466
+ });
467
+ it('should pass through new format unchanged', () => {
468
+ const newPayload = {
469
+ execute: true,
470
+ response: {
471
+ body: { data: 'test' }
472
+ }
473
+ };
474
+ const result = apiIntercept.processApiInterceptResponse(newPayload);
475
+ expect(result).toEqual(newPayload);
476
+ });
477
+ it('should handle payload without data property', () => {
478
+ const payload = {
479
+ execute: true
480
+ };
481
+ const result = apiIntercept.processApiInterceptResponse(payload);
482
+ expect(result).toEqual(payload);
483
+ });
484
+ it('should handle payload with data but no error', () => {
485
+ const payload = {
486
+ data: {
487
+ execute: true,
488
+ someOtherProperty: 'value'
489
+ }
490
+ };
491
+ const result = apiIntercept.processApiInterceptResponse(payload);
492
+ expect(result).toEqual(payload);
493
+ });
494
+ it('should handle null payload', () => {
495
+ const result = apiIntercept.processApiInterceptResponse(null);
496
+ expect(result).toBeNull();
497
+ });
498
+ it('should handle undefined payload', () => {
499
+ const result = apiIntercept.processApiInterceptResponse(undefined);
500
+ expect(result).toBeUndefined();
501
+ });
502
+ it('should handle payload with null data', () => {
503
+ const payload = {
504
+ data: null
505
+ };
506
+ const result = apiIntercept.processApiInterceptResponse(payload);
507
+ expect(result).toEqual(payload);
508
+ });
509
+ it('should handle payload with data.error set to null', () => {
510
+ const payload = {
511
+ data: {
512
+ error: null,
513
+ execute: true
514
+ }
515
+ };
516
+ const result = apiIntercept.processApiInterceptResponse(payload);
517
+ expect(result).toEqual(payload);
518
+ });
519
+ it('should handle payload with data.error set to undefined', () => {
520
+ const payload = {
521
+ data: {
522
+ error: undefined,
523
+ execute: true
524
+ }
525
+ };
526
+ const result = apiIntercept.processApiInterceptResponse(payload);
527
+ expect(result).toEqual(payload);
528
+ });
529
+ it('should handle payload with data.error set to false', () => {
530
+ const payload = {
531
+ data: {
532
+ error: false,
533
+ execute: true
534
+ }
535
+ };
536
+ const result = apiIntercept.processApiInterceptResponse(payload);
537
+ expect(result).toEqual(payload);
538
+ });
539
+ it('should handle payload with data.error set to 0', () => {
540
+ const payload = {
541
+ data: {
542
+ error: 0,
543
+ execute: true
544
+ }
545
+ };
546
+ const result = apiIntercept.processApiInterceptResponse(payload);
547
+ expect(result).toEqual(payload);
548
+ });
549
+ it('should handle payload with data.error set to empty string', () => {
550
+ const payload = {
551
+ data: {
552
+ error: '',
553
+ execute: true
554
+ }
555
+ };
556
+ const result = apiIntercept.processApiInterceptResponse(payload);
557
+ expect(result).toEqual(payload);
558
+ });
559
+ });
560
+ describe('processLegacyInterceptResponse', () => {
561
+ it('should convert legacy error format to new format', () => {
562
+ const legacyPayload = {
563
+ data: {
564
+ error: {
565
+ errorText: 'Custom Error',
566
+ errorDescription: 'Custom Description'
567
+ },
568
+ execute: false
569
+ }
570
+ };
571
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
572
+ expect(result).toEqual({
573
+ data: {
574
+ execute: false,
575
+ response: {
576
+ body: {
577
+ errors: [
578
+ {
579
+ title: 'Custom Error',
580
+ description: 'Custom Description',
581
+ isUserError: true,
582
+ },
583
+ ],
584
+ data: {},
585
+ },
586
+ },
587
+ }
588
+ });
589
+ });
590
+ it('should handle missing error properties', () => {
591
+ const legacyPayload = {
592
+ data: {
593
+ error: {},
594
+ execute: true
595
+ }
596
+ };
597
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
598
+ expect(result.data.response.body.errors[0]).toEqual({
599
+ title: undefined,
600
+ description: undefined,
601
+ isUserError: true,
602
+ });
603
+ });
604
+ it('should handle missing execute property', () => {
605
+ const legacyPayload = {
606
+ data: {
607
+ error: {
608
+ errorText: 'Error',
609
+ errorDescription: 'Description'
610
+ }
611
+ }
612
+ };
613
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
614
+ expect(result.data.execute).toBeUndefined();
615
+ });
616
+ it('should always include empty data object', () => {
617
+ const legacyPayload = {
618
+ data: {
619
+ error: {
620
+ errorText: 'Error',
621
+ errorDescription: 'Description'
622
+ },
623
+ execute: false
624
+ }
625
+ };
626
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
627
+ expect(result.data.response.body.data).toEqual({});
628
+ });
629
+ it('should always set isUserError to true', () => {
630
+ const legacyPayload = {
631
+ data: {
632
+ error: {
633
+ errorText: 'Error',
634
+ errorDescription: 'Description'
635
+ },
636
+ execute: false
637
+ }
638
+ };
639
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
640
+ expect(result.data.response.body.errors[0].isUserError).toBe(true);
641
+ });
642
+ it('should handle payload with null data', () => {
643
+ const legacyPayload = {
644
+ data: null
645
+ };
646
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
647
+ expect(result.data.execute).toBeUndefined();
648
+ expect(result.data.response.body.errors[0].title).toBeUndefined();
649
+ expect(result.data.response.body.errors[0].description).toBeUndefined();
650
+ });
651
+ it('should handle payload with null error', () => {
652
+ const legacyPayload = {
653
+ data: {
654
+ error: null,
655
+ execute: true
656
+ }
657
+ };
658
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
659
+ expect(result.data.execute).toBe(true);
660
+ expect(result.data.response.body.errors[0].title).toBeUndefined();
661
+ expect(result.data.response.body.errors[0].description).toBeUndefined();
662
+ });
663
+ it('should handle payload with undefined properties', () => {
664
+ const legacyPayload = {};
665
+ const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
666
+ expect(result.data.execute).toBeUndefined();
667
+ expect(result.data.response.body.errors[0].title).toBeUndefined();
668
+ expect(result.data.response.body.errors[0].description).toBeUndefined();
669
+ });
670
+ });
671
+ });
672
+ //# sourceMappingURL=api-intercept.spec.js.map