@thoughtspot/visual-embed-sdk 1.44.1 → 1.44.2

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 (235) hide show
  1. package/cjs/package.json +6 -5
  2. package/cjs/src/api-intercept.d.ts.map +1 -1
  3. package/cjs/src/api-intercept.js +8 -3
  4. package/cjs/src/api-intercept.js.map +1 -1
  5. package/cjs/src/api-intercept.spec.js +19 -3
  6. package/cjs/src/api-intercept.spec.js.map +1 -1
  7. package/cjs/src/auth.spec.js +43 -42
  8. package/cjs/src/auth.spec.js.map +1 -1
  9. package/cjs/src/authToken.spec.js +3 -3
  10. package/cjs/src/authToken.spec.js.map +1 -1
  11. package/cjs/src/embed/app.d.ts +17 -0
  12. package/cjs/src/embed/app.d.ts.map +1 -1
  13. package/cjs/src/embed/app.js +9 -5
  14. package/cjs/src/embed/app.js.map +1 -1
  15. package/cjs/src/embed/app.spec.js +96 -6
  16. package/cjs/src/embed/app.spec.js.map +1 -1
  17. package/cjs/src/embed/base.spec.js +11 -15
  18. package/cjs/src/embed/base.spec.js.map +1 -1
  19. package/cjs/src/embed/bodyless-conversation.spec.js +2 -2
  20. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  21. package/cjs/src/embed/conversation.d.ts.map +1 -1
  22. package/cjs/src/embed/conversation.js +6 -1
  23. package/cjs/src/embed/conversation.js.map +1 -1
  24. package/cjs/src/embed/conversation.spec.js +8 -3
  25. package/cjs/src/embed/conversation.spec.js.map +1 -1
  26. package/cjs/src/embed/embed.spec.js +101 -2
  27. package/cjs/src/embed/embed.spec.js.map +1 -1
  28. package/cjs/src/embed/events.spec.js +2 -2
  29. package/cjs/src/embed/events.spec.js.map +1 -1
  30. package/cjs/src/embed/hostEventClient/host-event-client.spec.js +1 -1
  31. package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  32. package/cjs/src/embed/liveboard.d.ts +18 -0
  33. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  34. package/cjs/src/embed/liveboard.js +13 -6
  35. package/cjs/src/embed/liveboard.js.map +1 -1
  36. package/cjs/src/embed/liveboard.spec.js +114 -26
  37. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  38. package/cjs/src/embed/pinboard.spec.js +1 -1
  39. package/cjs/src/embed/pinboard.spec.js.map +1 -1
  40. package/cjs/src/embed/sage.spec.js +2 -2
  41. package/cjs/src/embed/sage.spec.js.map +1 -1
  42. package/cjs/src/embed/search.spec.js +118 -2
  43. package/cjs/src/embed/search.spec.js.map +1 -1
  44. package/cjs/src/embed/ts-embed-trigger.spec.js +2 -3
  45. package/cjs/src/embed/ts-embed-trigger.spec.js.map +1 -1
  46. package/cjs/src/embed/ts-embed.d.ts +3 -2
  47. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  48. package/cjs/src/embed/ts-embed.js +51 -17
  49. package/cjs/src/embed/ts-embed.js.map +1 -1
  50. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  51. package/cjs/src/embed/ts-embed.spec.js +335 -71
  52. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  53. package/cjs/src/errors.d.ts +7 -0
  54. package/cjs/src/errors.d.ts.map +1 -1
  55. package/cjs/src/errors.js +7 -0
  56. package/cjs/src/errors.js.map +1 -1
  57. package/cjs/src/mixpanel-service.spec.js +1 -1
  58. package/cjs/src/mixpanel-service.spec.js.map +1 -1
  59. package/cjs/src/react/index.spec.js +3 -4
  60. package/cjs/src/react/index.spec.js.map +1 -1
  61. package/cjs/src/test/test-utils.js +1 -1
  62. package/cjs/src/test/test-utils.js.map +1 -1
  63. package/cjs/src/types.d.ts +194 -1
  64. package/cjs/src/types.d.ts.map +1 -1
  65. package/cjs/src/types.js +94 -2
  66. package/cjs/src/types.js.map +1 -1
  67. package/cjs/src/utils/authService/authService.spec.js +8 -8
  68. package/cjs/src/utils/authService/authService.spec.js.map +1 -1
  69. package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  70. package/cjs/src/utils/graphql/answerService/answerService.spec.js +1 -1
  71. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  72. package/cjs/src/utils/graphql/graphql-request.spec.js +1 -1
  73. package/cjs/src/utils/graphql/graphql-request.spec.js.map +1 -1
  74. package/cjs/src/utils/graphql/sourceService.spec.js +1 -1
  75. package/cjs/src/utils/graphql/sourceService.spec.js.map +1 -1
  76. package/cjs/src/utils/logger.spec.d.ts +5 -20
  77. package/cjs/src/utils/logger.spec.d.ts.map +1 -1
  78. package/cjs/src/utils/processData.spec.js +17 -17
  79. package/cjs/src/utils/processData.spec.js.map +1 -1
  80. package/cjs/src/utils/processTrigger.spec.js +8 -8
  81. package/cjs/src/utils/processTrigger.spec.js.map +1 -1
  82. package/cjs/src/utils.d.ts +6 -0
  83. package/cjs/src/utils.d.ts.map +1 -1
  84. package/cjs/src/utils.js +32 -1
  85. package/cjs/src/utils.js.map +1 -1
  86. package/cjs/src/utils.spec.js +19 -10
  87. package/cjs/src/utils.spec.js.map +1 -1
  88. package/dist/{index-BE9gGzRX.js → index-CSFjfTVk.js} +1 -1
  89. package/dist/src/api-intercept.d.ts.map +1 -1
  90. package/dist/src/embed/app.d.ts +17 -0
  91. package/dist/src/embed/app.d.ts.map +1 -1
  92. package/dist/src/embed/conversation.d.ts.map +1 -1
  93. package/dist/src/embed/liveboard.d.ts +18 -0
  94. package/dist/src/embed/liveboard.d.ts.map +1 -1
  95. package/dist/src/embed/ts-embed.d.ts +3 -2
  96. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  97. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  98. package/dist/src/errors.d.ts +7 -0
  99. package/dist/src/errors.d.ts.map +1 -1
  100. package/dist/src/types.d.ts +194 -1
  101. package/dist/src/types.d.ts.map +1 -1
  102. package/dist/src/utils/logger.spec.d.ts +5 -20
  103. package/dist/src/utils/logger.spec.d.ts.map +1 -1
  104. package/dist/src/utils.d.ts +6 -0
  105. package/dist/src/utils.d.ts.map +1 -1
  106. package/dist/tsembed-react.es.js +219 -36
  107. package/dist/tsembed-react.js +218 -35
  108. package/dist/tsembed.es.js +219 -36
  109. package/dist/tsembed.js +218 -35
  110. package/dist/visual-embed-sdk-react-full.d.ts +184 -2
  111. package/dist/visual-embed-sdk-react.d.ts +184 -2
  112. package/dist/visual-embed-sdk.d.ts +184 -2
  113. package/lib/package.json +6 -5
  114. package/lib/src/api-intercept.d.ts.map +1 -1
  115. package/lib/src/api-intercept.js +9 -4
  116. package/lib/src/api-intercept.js.map +1 -1
  117. package/lib/src/api-intercept.spec.js +20 -4
  118. package/lib/src/api-intercept.spec.js.map +1 -1
  119. package/lib/src/auth.spec.js +43 -42
  120. package/lib/src/auth.spec.js.map +1 -1
  121. package/lib/src/authToken.spec.js +3 -3
  122. package/lib/src/authToken.spec.js.map +1 -1
  123. package/lib/src/embed/app.d.ts +17 -0
  124. package/lib/src/embed/app.d.ts.map +1 -1
  125. package/lib/src/embed/app.js +10 -6
  126. package/lib/src/embed/app.js.map +1 -1
  127. package/lib/src/embed/app.spec.js +96 -6
  128. package/lib/src/embed/app.spec.js.map +1 -1
  129. package/lib/src/embed/base.spec.js +11 -15
  130. package/lib/src/embed/base.spec.js.map +1 -1
  131. package/lib/src/embed/bodyless-conversation.spec.js +2 -2
  132. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  133. package/lib/src/embed/conversation.d.ts.map +1 -1
  134. package/lib/src/embed/conversation.js +7 -2
  135. package/lib/src/embed/conversation.js.map +1 -1
  136. package/lib/src/embed/conversation.spec.js +9 -4
  137. package/lib/src/embed/conversation.spec.js.map +1 -1
  138. package/lib/src/embed/embed.spec.js +103 -4
  139. package/lib/src/embed/embed.spec.js.map +1 -1
  140. package/lib/src/embed/events.spec.js +2 -2
  141. package/lib/src/embed/events.spec.js.map +1 -1
  142. package/lib/src/embed/hostEventClient/host-event-client.spec.js +2 -2
  143. package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  144. package/lib/src/embed/liveboard.d.ts +18 -0
  145. package/lib/src/embed/liveboard.d.ts.map +1 -1
  146. package/lib/src/embed/liveboard.js +15 -8
  147. package/lib/src/embed/liveboard.js.map +1 -1
  148. package/lib/src/embed/liveboard.spec.js +114 -26
  149. package/lib/src/embed/liveboard.spec.js.map +1 -1
  150. package/lib/src/embed/pinboard.spec.js +1 -1
  151. package/lib/src/embed/pinboard.spec.js.map +1 -1
  152. package/lib/src/embed/sage.spec.js +2 -2
  153. package/lib/src/embed/sage.spec.js.map +1 -1
  154. package/lib/src/embed/search.spec.js +118 -2
  155. package/lib/src/embed/search.spec.js.map +1 -1
  156. package/lib/src/embed/ts-embed-trigger.spec.js +2 -3
  157. package/lib/src/embed/ts-embed-trigger.spec.js.map +1 -1
  158. package/lib/src/embed/ts-embed.d.ts +3 -2
  159. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  160. package/lib/src/embed/ts-embed.js +52 -18
  161. package/lib/src/embed/ts-embed.js.map +1 -1
  162. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  163. package/lib/src/embed/ts-embed.spec.js +336 -72
  164. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  165. package/lib/src/errors.d.ts +7 -0
  166. package/lib/src/errors.d.ts.map +1 -1
  167. package/lib/src/errors.js +7 -0
  168. package/lib/src/errors.js.map +1 -1
  169. package/lib/src/mixpanel-service.spec.js +1 -1
  170. package/lib/src/mixpanel-service.spec.js.map +1 -1
  171. package/lib/src/react/index.spec.js +3 -4
  172. package/lib/src/react/index.spec.js.map +1 -1
  173. package/lib/src/test/test-utils.js +1 -1
  174. package/lib/src/test/test-utils.js.map +1 -1
  175. package/lib/src/types.d.ts +194 -1
  176. package/lib/src/types.d.ts.map +1 -1
  177. package/lib/src/types.js +93 -1
  178. package/lib/src/types.js.map +1 -1
  179. package/lib/src/utils/authService/authService.spec.js +8 -8
  180. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  181. package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  182. package/lib/src/utils/graphql/answerService/answerService.spec.js +1 -1
  183. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  184. package/lib/src/utils/graphql/graphql-request.spec.js +1 -1
  185. package/lib/src/utils/graphql/graphql-request.spec.js.map +1 -1
  186. package/lib/src/utils/graphql/sourceService.spec.js +1 -1
  187. package/lib/src/utils/graphql/sourceService.spec.js.map +1 -1
  188. package/lib/src/utils/logger.spec.d.ts +5 -20
  189. package/lib/src/utils/logger.spec.d.ts.map +1 -1
  190. package/lib/src/utils/processData.spec.js +17 -17
  191. package/lib/src/utils/processData.spec.js.map +1 -1
  192. package/lib/src/utils/processTrigger.spec.js +8 -8
  193. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  194. package/lib/src/utils.d.ts +6 -0
  195. package/lib/src/utils.d.ts.map +1 -1
  196. package/lib/src/utils.js +30 -0
  197. package/lib/src/utils.js.map +1 -1
  198. package/lib/src/utils.spec.js +20 -11
  199. package/lib/src/utils.spec.js.map +1 -1
  200. package/package.json +6 -5
  201. package/src/api-intercept.spec.ts +23 -10
  202. package/src/api-intercept.ts +9 -4
  203. package/src/auth.spec.ts +53 -51
  204. package/src/authToken.spec.ts +3 -3
  205. package/src/embed/app.spec.ts +128 -7
  206. package/src/embed/app.ts +30 -4
  207. package/src/embed/base.spec.ts +16 -20
  208. package/src/embed/bodyless-conversation.spec.ts +2 -2
  209. package/src/embed/conversation.spec.ts +9 -4
  210. package/src/embed/conversation.ts +7 -2
  211. package/src/embed/embed.spec.ts +122 -2
  212. package/src/embed/events.spec.ts +2 -2
  213. package/src/embed/hostEventClient/host-event-client.spec.ts +2 -2
  214. package/src/embed/liveboard.spec.ts +137 -29
  215. package/src/embed/liveboard.ts +36 -6
  216. package/src/embed/pinboard.spec.ts +1 -1
  217. package/src/embed/sage.spec.ts +2 -2
  218. package/src/embed/search.spec.ts +133 -2
  219. package/src/embed/ts-embed-trigger.spec.ts +2 -3
  220. package/src/embed/ts-embed.spec.ts +424 -91
  221. package/src/embed/ts-embed.ts +56 -19
  222. package/src/errors.ts +7 -0
  223. package/src/mixpanel-service.spec.ts +1 -1
  224. package/src/react/index.spec.tsx +4 -5
  225. package/src/test/test-utils.ts +2 -2
  226. package/src/types.ts +206 -1
  227. package/src/utils/authService/authService.spec.ts +17 -17
  228. package/src/utils/authService/tokenizedAuthService.spec.ts +4 -4
  229. package/src/utils/graphql/answerService/answerService.spec.ts +3 -3
  230. package/src/utils/graphql/graphql-request.spec.ts +2 -2
  231. package/src/utils/graphql/sourceService.spec.ts +1 -1
  232. package/src/utils/processData.spec.ts +26 -26
  233. package/src/utils/processTrigger.spec.ts +8 -8
  234. package/src/utils.spec.ts +22 -11
  235. package/src/utils.ts +34 -0
@@ -29,6 +29,8 @@ import {
29
29
  CustomActionTarget,
30
30
  CustomActionsPosition,
31
31
  DefaultAppInitData,
32
+ ErrorDetailsTypes,
33
+ EmbedErrorCodes,
32
34
  } from '../types';
33
35
  import {
34
36
  executeAfterWait,
@@ -87,7 +89,7 @@ const hideBydefault = `&hideAction=${fixedEncodeURI(
87
89
  const defaultParamsWithHiddenActions = defaultParamsWithoutHiddenActions + hideBydefault;
88
90
 
89
91
  beforeAll(() => {
90
- spyOn(window, 'alert');
92
+ jest.spyOn(window, 'alert').mockImplementation(() => {});
91
93
  });
92
94
 
93
95
  const customisations = {
@@ -150,7 +152,7 @@ describe('Unit test case for ts embed', () => {
150
152
  });
151
153
 
152
154
  beforeAll(() => {
153
- jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
155
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(undefined);
154
156
  });
155
157
 
156
158
  describe('Vaidate iframe properties', () => {
@@ -291,7 +293,7 @@ describe('Unit test case for ts embed', () => {
291
293
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
292
294
  });
293
295
  await executeAfterWait(() => {
294
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
296
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
295
297
  authInstance.AuthFailureType.EXPIRY,
296
298
  );
297
299
  expect(baseInstance.handleAuth).not.toHaveBeenCalled();
@@ -328,7 +330,7 @@ describe('Unit test case for ts embed', () => {
328
330
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
329
331
  });
330
332
  await executeAfterWait(() => {
331
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
333
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
332
334
  authInstance.AuthFailureType.EXPIRY,
333
335
  );
334
336
  expect(mockPort.postMessage).not.toHaveBeenCalledWith({
@@ -723,7 +725,7 @@ describe('Unit test case for ts embed', () => {
723
725
  }, 1000);
724
726
  });
725
727
 
726
- test('should remove event listener when called off method', async (done) => {
728
+ test('should remove event listener when called off method', async () => {
727
729
  const mockEmbedEventPayload = {
728
730
  type: EmbedEvent.Save,
729
731
  data: { answerId: '123' },
@@ -743,10 +745,7 @@ describe('Unit test case for ts embed', () => {
743
745
  const iframe = getIFrameEl();
744
746
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload);
745
747
  });
746
- await executeAfterWait(() => {
747
- expect(mockFn).toHaveBeenCalledTimes(1);
748
- done();
749
- }, 100);
748
+ expect(mockFn).toHaveBeenCalledTimes(1);
750
749
  });
751
750
  });
752
751
 
@@ -1011,7 +1010,7 @@ describe('Unit test case for ts embed', () => {
1011
1010
  authType: AuthType.TrustedAuthTokenCookieless,
1012
1011
  getAuthToken: () => Promise.reject(),
1013
1012
  });
1014
- jest.spyOn(logger, 'error').mockResolvedValue(true);
1013
+ jest.spyOn(logger, 'error').mockImplementation(() => {});
1015
1014
  });
1016
1015
 
1017
1016
  afterEach(() => {
@@ -1087,14 +1086,14 @@ describe('Unit test case for ts embed', () => {
1087
1086
  const mockPort: any = {
1088
1087
  postMessage: jest.fn(),
1089
1088
  };
1090
- const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
1089
+ const loggerSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
1091
1090
  await executeAfterWait(() => {
1092
1091
  const iframe = getIFrameEl();
1093
1092
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
1094
1093
  });
1095
1094
  await executeAfterWait(() => {
1096
1095
  expect(getRootEl().innerHTML).toContain('Not logged in');
1097
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
1096
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
1098
1097
  authInstance.AuthFailureType.EXPIRY,
1099
1098
  );
1100
1099
  expect(loggerSpy).toHaveBeenCalledTimes(1);
@@ -1116,7 +1115,7 @@ describe('Unit test case for ts embed', () => {
1116
1115
  const searchEmbed = new SearchEmbed(getRootEl(), { ...defaultViewConfig, preRenderId: 'test' });
1117
1116
  jest.spyOn(baseInstance, 'notifyAuthFailure');
1118
1117
  searchEmbed.preRender();
1119
- const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
1118
+ const loggerSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
1120
1119
  const mockPort: any = {
1121
1120
  postMessage: jest.fn(),
1122
1121
  };
@@ -1127,7 +1126,7 @@ describe('Unit test case for ts embed', () => {
1127
1126
  const preRenderWrapper = document.getElementById('tsEmbed-pre-render-wrapper-test');
1128
1127
  await executeAfterWait(() => {
1129
1128
  expect(preRenderWrapper.innerHTML).toContain('Not logged in');
1130
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
1129
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
1131
1130
  authInstance.AuthFailureType.EXPIRY,
1132
1131
  );
1133
1132
  expect(loggerSpy).toHaveBeenCalledTimes(1);
@@ -1161,7 +1160,7 @@ describe('Unit test case for ts embed', () => {
1161
1160
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload);
1162
1161
  });
1163
1162
  await executeAfterWait(() => {
1164
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
1163
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
1165
1164
  authInstance.AuthFailureType.EXPIRY,
1166
1165
  );
1167
1166
  expect(baseInstance.handleAuth).toHaveBeenCalled();
@@ -1188,7 +1187,7 @@ describe('Unit test case for ts embed', () => {
1188
1187
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload);
1189
1188
  });
1190
1189
  await executeAfterWait(() => {
1191
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
1190
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
1192
1191
  authInstance.AuthFailureType.EXPIRY,
1193
1192
  );
1194
1193
  expect(baseInstance.handleAuth).not.toHaveBeenCalled();
@@ -1208,13 +1207,11 @@ describe('Unit test case for ts embed', () => {
1208
1207
  const setup = async (isLoggedIn = false) => {
1209
1208
  jest.spyOn(window, 'addEventListener').mockImplementationOnce(
1210
1209
  (event, handler, options) => {
1211
- handler({
1212
- data: {
1213
- type: 'xyz',
1214
- },
1210
+ (handler as EventListener)({
1211
+ data: { type: 'xyz' },
1215
1212
  ports: [3000],
1216
1213
  source: null,
1217
- });
1214
+ } as any);
1218
1215
  },
1219
1216
  );
1220
1217
  const iFrame: any = document.createElement('div');
@@ -1224,7 +1221,7 @@ describe('Unit test case for ts embed', () => {
1224
1221
  tsEmbed.on(EmbedEvent.CustomAction, jest.fn());
1225
1222
  jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce(
1226
1223
  (event, handler, options) => {
1227
- handler({});
1224
+ (handler as EventListener)({} as Event);
1228
1225
  },
1229
1226
  );
1230
1227
  jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
@@ -1233,8 +1230,8 @@ describe('Unit test case for ts embed', () => {
1233
1230
 
1234
1231
  test('mixpanel should call with VISUAL_SDK_RENDER_COMPLETE', async () => {
1235
1232
  await setup(true);
1236
- expect(mockMixPanelEvent).toBeCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
1237
- expect(mockMixPanelEvent).toBeCalledWith(
1233
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
1234
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(
1238
1235
  MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE,
1239
1236
  expect.objectContaining({
1240
1237
  elWidth: 0,
@@ -1249,12 +1246,9 @@ describe('Unit test case for ts embed', () => {
1249
1246
  expect(prefetchIframe.length).toBe(0);
1250
1247
  });
1251
1248
 
1252
- test('Should render failure when login fails', async (done) => {
1253
- setup(false);
1254
- executeAfterWait(() => {
1255
- expect(getRootEl().innerHTML).toContain('Failed to Login');
1256
- done();
1257
- });
1249
+ test('Should render failure when login fails', async () => {
1250
+ await setup(false);
1251
+ expect(getRootEl().innerHTML).toContain('Failed to Login');
1258
1252
  });
1259
1253
  });
1260
1254
 
@@ -1271,13 +1265,11 @@ describe('Unit test case for ts embed', () => {
1271
1265
  const setup = async (isLoggedIn = false, overrideOrgId: number | undefined = undefined) => {
1272
1266
  jest.spyOn(window, 'addEventListener').mockImplementationOnce(
1273
1267
  (event, handler, options) => {
1274
- handler({
1275
- data: {
1276
- type: 'xyz',
1277
- },
1268
+ (handler as EventListener)({
1269
+ data: { type: 'xyz' },
1278
1270
  ports: [3000],
1279
1271
  source: null,
1280
- });
1272
+ } as any);
1281
1273
  },
1282
1274
  );
1283
1275
  mockProcessTrigger.mockResolvedValueOnce({ session: 'test' });
@@ -1313,7 +1305,7 @@ describe('Unit test case for ts embed', () => {
1313
1305
  tsEmbed.on(EmbedEvent.CustomAction, jest.fn());
1314
1306
  jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce(
1315
1307
  (event, handler, options) => {
1316
- handler({});
1308
+ (handler as EventListener)({} as Event);
1317
1309
  },
1318
1310
  );
1319
1311
  jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
@@ -1375,11 +1367,11 @@ describe('Unit test case for ts embed', () => {
1375
1367
  ) => {
1376
1368
  jest.spyOn(window, 'addEventListener').mockImplementationOnce(
1377
1369
  (event, handler, options) => {
1378
- handler({
1370
+ (handler as EventListener)({
1379
1371
  data: { type: 'xyz' },
1380
1372
  ports: [3000],
1381
1373
  source: null,
1382
- });
1374
+ } as any);
1383
1375
  },
1384
1376
  );
1385
1377
  mockProcessTrigger.mockResolvedValueOnce({ session: 'test' });
@@ -1396,7 +1388,7 @@ describe('Unit test case for ts embed', () => {
1396
1388
  .mockImplementation(jest.fn());
1397
1389
  } else {
1398
1390
  mockGetPreauthInfo = jest.spyOn(sessionInfoService, 'getPreauthInfo')
1399
- .mockResolvedValue({ info: { test: 'data' } });
1391
+ .mockResolvedValue({ info: { test: 'data' } } as any);
1400
1392
  }
1401
1393
 
1402
1394
  const mockPreauthInfoFetch = jest.spyOn(authService, 'fetchPreauthInfoService')
@@ -1441,7 +1433,7 @@ describe('Unit test case for ts embed', () => {
1441
1433
  };
1442
1434
  jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce(
1443
1435
  (event, handler, options) => {
1444
- handler({});
1436
+ (handler as EventListener)({} as Event);
1445
1437
  },
1446
1438
  );
1447
1439
  jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
@@ -1590,13 +1582,13 @@ describe('Unit test case for ts embed', () => {
1590
1582
  const iFrame: any = document.createElement('div');
1591
1583
  iFrame.contentWindow = null;
1592
1584
  jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
1593
- spyOn(logger, 'error');
1585
+ jest.spyOn(logger, 'error');
1594
1586
  await tsEmbed.render();
1595
1587
  });
1596
1588
 
1597
1589
  test('mixpanel should call with VISUAL_SDK_RENDER_FAILED', () => {
1598
- expect(mockMixPanelEvent).toBeCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
1599
- expect(mockMixPanelEvent).toBeCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_FAILED, {
1590
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
1591
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_FAILED, {
1600
1592
  error: 'false',
1601
1593
  });
1602
1594
  });
@@ -1604,7 +1596,7 @@ describe('Unit test case for ts embed', () => {
1604
1596
 
1605
1597
  describe('when visible actions are set', () => {
1606
1598
  test('should throw error when there are both visible and hidden actions - pinboard', async () => {
1607
- spyOn(logger, 'error');
1599
+ jest.spyOn(logger, 'error');
1608
1600
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
1609
1601
  hiddenActions: [Action.DownloadAsCsv],
1610
1602
  visibleActions: [Action.DownloadAsCsv],
@@ -1613,9 +1605,12 @@ describe('Unit test case for ts embed', () => {
1613
1605
  } as LiveboardViewConfig);
1614
1606
  await pinboardEmbed.render();
1615
1607
  expect(pinboardEmbed['isError']).toBe(true);
1616
- expect(logger.error).toHaveBeenCalledWith(
1617
- 'You cannot have both hidden actions and visible actions',
1618
- );
1608
+ expect(logger.error).toHaveBeenCalledWith({
1609
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1610
+ message: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1611
+ code: EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG,
1612
+ error: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1613
+ });
1619
1614
  });
1620
1615
  test('should not throw error when there are only visible or hidden actions - pinboard', async () => {
1621
1616
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
@@ -1636,7 +1631,7 @@ describe('Unit test case for ts embed', () => {
1636
1631
  hiddenActions: Array<Action>,
1637
1632
  visibleActions: Array<Action>,
1638
1633
  ) {
1639
- spyOn(logger, 'error');
1634
+ jest.spyOn(logger, 'error');
1640
1635
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1641
1636
  hiddenActions,
1642
1637
  visibleActions,
@@ -1645,9 +1640,12 @@ describe('Unit test case for ts embed', () => {
1645
1640
  } as LiveboardViewConfig);
1646
1641
  await liveboardEmbed.render();
1647
1642
  expect(liveboardEmbed['isError']).toBe(true);
1648
- expect(logger.error).toHaveBeenCalledWith(
1649
- 'You cannot have both hidden actions and visible actions',
1650
- );
1643
+ expect(logger.error).toHaveBeenCalledWith({
1644
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1645
+ message: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1646
+ code: EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG,
1647
+ error: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1648
+ });
1651
1649
  }
1652
1650
  test('should throw error when there are both visible and hidden action arrays', async () => {
1653
1651
  await testActionsForLiveboards([Action.DownloadAsCsv], [Action.DownloadAsCsv]);
@@ -1681,7 +1679,7 @@ describe('Unit test case for ts embed', () => {
1681
1679
 
1682
1680
  describe('when visible Tabs are set', () => {
1683
1681
  test('should throw error when there are both visible and hidden Tabs - pinboard', async () => {
1684
- spyOn(logger, 'error');
1682
+ jest.spyOn(logger, 'error');
1685
1683
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
1686
1684
  visibleTabs: [tabId1],
1687
1685
  hiddenTabs: [tabId2],
@@ -1690,9 +1688,12 @@ describe('Unit test case for ts embed', () => {
1690
1688
  } as LiveboardViewConfig);
1691
1689
  await pinboardEmbed.render();
1692
1690
  expect(pinboardEmbed['isError']).toBe(true);
1693
- expect(logger.error).toHaveBeenCalledWith(
1694
- 'You cannot have both hidden Tabs and visible Tabs',
1695
- );
1691
+ expect(logger.error).toHaveBeenCalledWith({
1692
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1693
+ message: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1694
+ code: EmbedErrorCodes.CONFLICTING_TABS_CONFIG,
1695
+ error: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1696
+ });
1696
1697
  });
1697
1698
  test('should not throw error when there are only visible or hidden Tabs - pinboard', async () => {
1698
1699
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
@@ -1713,7 +1714,7 @@ describe('Unit test case for ts embed', () => {
1713
1714
  hiddenTabs: Array<string>,
1714
1715
  visibleTabs: Array<string>,
1715
1716
  ) {
1716
- spyOn(logger, 'error');
1717
+ jest.spyOn(logger, 'error');
1717
1718
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1718
1719
  hiddenTabs,
1719
1720
  visibleTabs,
@@ -1722,9 +1723,12 @@ describe('Unit test case for ts embed', () => {
1722
1723
  } as LiveboardViewConfig);
1723
1724
  await liveboardEmbed.render();
1724
1725
  expect(liveboardEmbed['isError']).toBe(true);
1725
- expect(logger.error).toHaveBeenCalledWith(
1726
- 'You cannot have both hidden Tabs and visible Tabs',
1727
- );
1726
+ expect(logger.error).toHaveBeenCalledWith({
1727
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1728
+ message: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1729
+ code: EmbedErrorCodes.CONFLICTING_TABS_CONFIG,
1730
+ error: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1731
+ });
1728
1732
  }
1729
1733
  test('should throw error when there are both visible and hidden Tab arrays', async () => {
1730
1734
  await testTabsForLiveboards([tabId1], [tabId2]);
@@ -1766,13 +1770,16 @@ describe('Unit test case for ts embed', () => {
1766
1770
  });
1767
1771
 
1768
1772
  test('Error should be true', async () => {
1769
- spyOn(logger, 'error');
1773
+ jest.spyOn(logger, 'error');
1770
1774
  const tsEmbed = new SearchEmbed(getRootEl(), {});
1771
1775
  await tsEmbed.render();
1772
1776
  expect(tsEmbed['isError']).toBe(true);
1773
- expect(logger.error).toHaveBeenCalledWith(
1774
- 'You need to init the ThoughtSpot SDK module first',
1775
- );
1777
+ expect(logger.error).toHaveBeenCalledWith({
1778
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1779
+ message: ERROR_MESSAGE.INIT_SDK_REQUIRED,
1780
+ code: EmbedErrorCodes.INIT_ERROR,
1781
+ error: ERROR_MESSAGE.INIT_SDK_REQUIRED,
1782
+ });
1776
1783
  });
1777
1784
  });
1778
1785
 
@@ -1782,7 +1789,7 @@ describe('Unit test case for ts embed', () => {
1782
1789
  });
1783
1790
 
1784
1791
  test('when isRendered is true than isError will be true', async () => {
1785
- spyOn(logger, 'warn');
1792
+ jest.spyOn(logger, 'warn');
1786
1793
  const viEmbedIns = new tsEmbedInstance.V1Embed(getRootEl(), defaultViewConfig);
1787
1794
  expect(viEmbedIns['isError']).toBe(false);
1788
1795
  await viEmbedIns.render();
@@ -1840,7 +1847,7 @@ describe('Unit test case for ts embed', () => {
1840
1847
  });
1841
1848
 
1842
1849
  test('navigateToPage function use before render', async () => {
1843
- spyOn(logger, 'log');
1850
+ jest.spyOn(logger, 'log');
1844
1851
  const appEmbed = new AppEmbed(getRootEl(), {
1845
1852
  frameParams: {
1846
1853
  width: '100%',
@@ -2075,7 +2082,7 @@ describe('Unit test case for ts embed', () => {
2075
2082
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&additionalPendoKey=1234${defaultParamsPost}#/home`,
2076
2083
  );
2077
2084
  });
2078
- xit('Sets the forceSAMLAutoRedirect param', async (done) => {
2085
+ xit('Sets the forceSAMLAutoRedirect param', async () => {
2079
2086
  jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValue(true);
2080
2087
  init({
2081
2088
  thoughtSpotHost: 'tshost',
@@ -2089,11 +2096,8 @@ describe('Unit test case for ts embed', () => {
2089
2096
  },
2090
2097
  });
2091
2098
  appEmbed.render();
2092
- await waitFor(() => !!getIFrameEl()).then(() => {
2093
- expect(getIFrameSrc()).toContain('authType=EmbeddedSSO');
2094
- expect(getIFrameSrc()).toContain('forceSAMLAutoRedirect=true');
2095
- done();
2096
- });
2099
+ expect(getIFrameSrc()).toContain('authType=EmbeddedSSO');
2100
+ expect(getIFrameSrc()).toContain('forceSAMLAutoRedirect=true');
2097
2101
  });
2098
2102
 
2099
2103
  it('Should set the override locale for number/date and currency format', async () => {
@@ -2291,8 +2295,7 @@ describe('Unit test case for ts embed', () => {
2291
2295
  beforeAll(() => {
2292
2296
  delete window.location;
2293
2297
  (window as any).location = {
2294
- hash: '',
2295
- search: '',
2298
+ assign: jest.fn(),
2296
2299
  };
2297
2300
  });
2298
2301
 
@@ -2369,7 +2372,7 @@ describe('Unit test case for ts embed', () => {
2369
2372
 
2370
2373
  afterAll(() => {
2371
2374
  const rootEle = document.getElementById('myRoot');
2372
- rootEle.remove();
2375
+ rootEle?.remove();
2373
2376
  jest.clearAllMocks();
2374
2377
  });
2375
2378
 
@@ -2412,9 +2415,9 @@ describe('Unit test case for ts embed', () => {
2412
2415
  });
2413
2416
 
2414
2417
  // show preRender
2415
- const warnSpy = spyOn(logger, 'warn');
2418
+ const warnSpy = jest.spyOn(logger, 'warn');
2416
2419
  libEmbed.showPreRender();
2417
- expect(warnSpy).toHaveBeenCalledTimes(0);
2420
+ expect(warnSpy).toHaveBeenCalledTimes(1);
2418
2421
 
2419
2422
  resizeObserverCb([
2420
2423
  {
@@ -2442,7 +2445,7 @@ describe('Unit test case for ts embed', () => {
2442
2445
  it('preRender called without preRenderId should log error ', () => {
2443
2446
  createRootEleForEmbed();
2444
2447
 
2445
- spyOn(logger, 'error');
2448
+ jest.spyOn(logger, 'error');
2446
2449
  const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2447
2450
  liveboardId: 'myLiveboardId',
2448
2451
  });
@@ -2475,7 +2478,7 @@ describe('Unit test case for ts embed', () => {
2475
2478
  preRenderId: 'i-am-preRendered',
2476
2479
  liveboardId: 'myLiveboardId',
2477
2480
  });
2478
- spyOn(libEmbed, 'preRender');
2481
+ jest.spyOn(libEmbed, 'preRender');
2479
2482
  libEmbed.hidePreRender();
2480
2483
  expect(libEmbed.preRender).toHaveBeenCalledTimes(0);
2481
2484
  });
@@ -2514,8 +2517,8 @@ describe('Unit test case for ts embed', () => {
2514
2517
  const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2515
2518
  liveboardId: 'myLiveboardId',
2516
2519
  });
2517
- spyOn(libEmbed, 'preRender');
2518
- spyOn(logger, 'error');
2520
+ jest.spyOn(libEmbed, 'preRender');
2521
+ jest.spyOn(logger, 'error');
2519
2522
  libEmbed.showPreRender();
2520
2523
  expect(libEmbed.preRender).toHaveBeenCalledTimes(0);
2521
2524
  expect(logger.error).toHaveBeenCalledTimes(1);
@@ -2552,7 +2555,7 @@ describe('Unit test case for ts embed', () => {
2552
2555
  preRenderId: 'test',
2553
2556
  });
2554
2557
  await libEmbed.syncPreRenderStyle();
2555
- expect(logger.error).toBeCalledWith(
2558
+ expect(logger.error).toHaveBeenCalledWith(
2556
2559
  'PreRender should be called before using syncPreRenderStyle',
2557
2560
  );
2558
2561
  (logger.error as any).mockClear();
@@ -2590,7 +2593,7 @@ describe('Unit test case for ts embed', () => {
2590
2593
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2591
2594
  });
2592
2595
  await executeAfterWait(() => {
2593
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2596
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
2594
2597
  authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2595
2598
  );
2596
2599
  expect(baseInstance.handleAuth).toHaveBeenCalled();
@@ -2620,14 +2623,14 @@ describe('Unit test case for ts embed', () => {
2620
2623
  const mockPort: any = {
2621
2624
  postMessage: jest.fn(),
2622
2625
  };
2623
- const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
2626
+ const loggerSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
2624
2627
  await executeAfterWait(() => {
2625
2628
  const iframe = getIFrameEl();
2626
2629
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2627
2630
  });
2628
2631
  await executeAfterWait(() => {
2629
2632
  expect(getRootEl().innerHTML).toContain('Not logged in');
2630
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2633
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
2631
2634
  authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2632
2635
  );
2633
2636
  expect(loggerSpy).toHaveBeenCalledTimes(1);
@@ -2657,13 +2660,13 @@ describe('Unit test case for ts embed', () => {
2657
2660
  const mockPort: any = {
2658
2661
  postMessage: jest.fn(),
2659
2662
  };
2660
- const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
2663
+ const loggerSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
2661
2664
  await executeAfterWait(() => {
2662
2665
  const iframe = getIFrameEl();
2663
2666
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2664
2667
  });
2665
2668
  await executeAfterWait(() => {
2666
- expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2669
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
2667
2670
  authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2668
2671
  );
2669
2672
  expect(loggerSpy).toHaveBeenCalledTimes(0);
@@ -2675,7 +2678,7 @@ describe('Unit test case for ts embed', () => {
2675
2678
  });
2676
2679
 
2677
2680
  describe('Renders should wait for init to completed', () => {
2678
- const errorSpy = jest.spyOn(logger, 'error').mockResolvedValue(true);
2681
+ const errorSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
2679
2682
  beforeEach(() => {
2680
2683
  errorSpy.mockClear();
2681
2684
  resetValueFromWindow('initFlagKey');
@@ -3490,7 +3493,7 @@ describe('Unit test case for ts embed', () => {
3490
3493
 
3491
3494
  test('should execute callbacks through executeEvent function', async () => {
3492
3495
  let capturedExecuteEvent: any;
3493
- mockHandleInterceptEvent.mockImplementation((params) => {
3496
+ mockHandleInterceptEvent.mockImplementation(async (params) => {
3494
3497
  capturedExecuteEvent = params.executeEvent;
3495
3498
  });
3496
3499
 
@@ -3531,7 +3534,7 @@ describe('Unit test case for ts embed', () => {
3531
3534
 
3532
3535
  test('should call triggerUIPassThrough through getUnsavedAnswerTml function', async () => {
3533
3536
  let capturedGetUnsavedAnswerTml: any;
3534
- mockHandleInterceptEvent.mockImplementation((params) => {
3537
+ mockHandleInterceptEvent.mockImplementation(async (params) => {
3535
3538
  capturedGetUnsavedAnswerTml = params.getUnsavedAnswerTml;
3536
3539
  });
3537
3540
 
@@ -3715,7 +3718,7 @@ describe('Unit test case for ts embed', () => {
3715
3718
 
3716
3719
  test('should pass eventPort to executeCallbacks', async () => {
3717
3720
  let capturedExecuteEvent: any;
3718
- mockHandleInterceptEvent.mockImplementation((params) => {
3721
+ mockHandleInterceptEvent.mockImplementation(async (params) => {
3719
3722
  capturedExecuteEvent = params.executeEvent;
3720
3723
  });
3721
3724
 
@@ -3756,7 +3759,7 @@ describe('Unit test case for ts embed', () => {
3756
3759
 
3757
3760
  test('should handle getUnsavedAnswerTml with empty response', async () => {
3758
3761
  let capturedGetUnsavedAnswerTml: any;
3759
- mockHandleInterceptEvent.mockImplementation((params) => {
3762
+ mockHandleInterceptEvent.mockImplementation(async (params) => {
3760
3763
  capturedGetUnsavedAnswerTml = params.getUnsavedAnswerTml;
3761
3764
  });
3762
3765
 
@@ -3829,3 +3832,333 @@ describe('Unit test case for ts embed', () => {
3829
3832
  });
3830
3833
  });
3831
3834
  });
3835
+
3836
+
3837
+ describe('Additional Coverage Tests', () => {
3838
+ beforeAll(() => {
3839
+ init({
3840
+ thoughtSpotHost: 'tshost',
3841
+ authType: AuthType.None,
3842
+ });
3843
+ });
3844
+
3845
+ test('should handle getAuthTokenForCookielessInit with non-cookieless auth', async () => {
3846
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3847
+ const token = await searchEmbed['getAuthTokenForCookielessInit']();
3848
+ expect(token).toBe('');
3849
+ });
3850
+
3851
+ test('should call setIFrameHeight', async () => {
3852
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3853
+ await searchEmbed.render();
3854
+ await executeAfterWait(() => {
3855
+ searchEmbed['setIFrameHeight'](500);
3856
+ expect(getIFrameEl().style.height).toBe('500px');
3857
+ });
3858
+ });
3859
+
3860
+ test('should test getIframeCenter calculation', async () => {
3861
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3862
+ await searchEmbed.render();
3863
+ await executeAfterWait(() => {
3864
+ const center = searchEmbed['getIframeCenter']();
3865
+ expect(center).toHaveProperty('iframeCenter');
3866
+ expect(center).toHaveProperty('iframeHeight');
3867
+ expect(center).toHaveProperty('viewPortHeight');
3868
+ });
3869
+ });
3870
+
3871
+ test('should handle preRender with replaceExistingPreRender=true', async () => {
3872
+ createRootEleForEmbed();
3873
+ const embed1 = new LiveboardEmbed('#tsEmbedDiv', {
3874
+ preRenderId: 'test-replace',
3875
+ liveboardId: 'lb1',
3876
+ });
3877
+ await embed1.preRender();
3878
+ const embed2 = new LiveboardEmbed('#tsEmbedDiv', {
3879
+ preRenderId: 'test-replace',
3880
+ liveboardId: 'lb2',
3881
+ });
3882
+ await embed2.preRender(false, true);
3883
+ expect(document.getElementById('tsEmbed-pre-render-wrapper-test-replace')).toBeTruthy();
3884
+ });
3885
+
3886
+ test('should test getIframeSrc base implementation', () => {
3887
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3888
+ expect(searchEmbed.getIframeSrc()).toBe('');
3889
+ });
3890
+
3891
+ test('should handle createEmbedEventResponder with OnBeforeGetVizDataIntercept', async () => {
3892
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3893
+ const mockPort: any = { postMessage: jest.fn() };
3894
+ const responder = searchEmbed['createEmbedEventResponder'](
3895
+ mockPort,
3896
+ EmbedEvent.OnBeforeGetVizDataIntercept,
3897
+ );
3898
+ responder({ data: 'test' });
3899
+ expect(mockPort.postMessage).toHaveBeenCalled();
3900
+ });
3901
+
3902
+ test('should clean up message event listeners', async () => {
3903
+ const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
3904
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3905
+ await searchEmbed.render();
3906
+ searchEmbed['unsubscribeToMessageEvents']();
3907
+ expect(removeEventListenerSpy).toHaveBeenCalledWith('message', expect.any(Function));
3908
+ });
3909
+ });
3910
+
3911
+ describe('Trigger method edge cases', () => {
3912
+ beforeAll(() => {
3913
+ init({
3914
+ thoughtSpotHost: 'tshost',
3915
+ authType: AuthType.None,
3916
+ });
3917
+ });
3918
+
3919
+ beforeEach(() => {
3920
+ document.body.innerHTML = getDocumentBody();
3921
+ });
3922
+
3923
+ test('should handle error when trigger is called with undefined messageType', async () => {
3924
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3925
+ jest.spyOn(logger, 'error');
3926
+ await searchEmbed.render();
3927
+
3928
+ await executeAfterWait(async () => {
3929
+ const result = await searchEmbed.trigger(undefined as any);
3930
+ expect(result).toBeNull();
3931
+ expect(logger.error).toHaveBeenCalledWith(
3932
+ expect.objectContaining({
3933
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
3934
+ code: EmbedErrorCodes.HOST_EVENT_TYPE_UNDEFINED,
3935
+ }),
3936
+ );
3937
+ });
3938
+ });
3939
+
3940
+ test('should return null when trigger is called before iframe is ready', async () => {
3941
+ jest.spyOn(baseInstance, 'getAuthPromise').mockRejectedValueOnce(
3942
+ new Error('Auth failed'),
3943
+ );
3944
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3945
+ jest.spyOn(logger, 'debug');
3946
+ await searchEmbed.render();
3947
+
3948
+ await executeAfterWait(async () => {
3949
+ const result = await searchEmbed.trigger(HostEvent.Reload);
3950
+ expect(result).toBeNull();
3951
+ });
3952
+ });
3953
+ });
3954
+
3955
+ describe('PreRender replaceExistingPreRender scenarios', () => {
3956
+ beforeAll(() => {
3957
+ init({
3958
+ thoughtSpotHost: 'tshost',
3959
+ authType: AuthType.None,
3960
+ });
3961
+ });
3962
+
3963
+ afterEach(() => {
3964
+ const rootEle = document.getElementById('myRoot');
3965
+ rootEle?.remove();
3966
+ });
3967
+
3968
+ test('should skip re-rendering when preRender already exists and replaceExistingPreRender is false', async () => {
3969
+ createRootEleForEmbed();
3970
+ const embed1 = new LiveboardEmbed('#tsEmbedDiv', {
3971
+ preRenderId: 'no-replace-test',
3972
+ liveboardId: 'lb1',
3973
+ });
3974
+ await embed1.preRender();
3975
+ await waitFor(() => !!getIFrameEl());
3976
+
3977
+ const embed2 = new LiveboardEmbed('#tsEmbedDiv', {
3978
+ preRenderId: 'no-replace-test',
3979
+ liveboardId: 'lb2',
3980
+ });
3981
+
3982
+ const result = await embed2.preRender(false, false);
3983
+
3984
+ expect(result).toBe(embed2);
3985
+ // The original iframe should still have lb1
3986
+ const iframe = getIFrameEl();
3987
+ expect(iframe.src).toContain('lb1');
3988
+ });
3989
+ });
3990
+
3991
+ describe('Destroy error handling', () => {
3992
+ beforeAll(() => {
3993
+ init({
3994
+ thoughtSpotHost: 'tshost',
3995
+ authType: AuthType.None,
3996
+ });
3997
+ });
3998
+
3999
+ beforeEach(() => {
4000
+ document.body.innerHTML = getDocumentBody();
4001
+ });
4002
+
4003
+ test('should handle error gracefully when destroy fails', async () => {
4004
+ const appEmbed = new AppEmbed(getRootEl(), {
4005
+ frameParams: { width: '100%', height: '100%' },
4006
+ });
4007
+ await appEmbed.render();
4008
+
4009
+ const logSpy = jest.spyOn(logger, 'log').mockImplementation(() => {});
4010
+
4011
+ jest.spyOn(Node.prototype, 'removeChild').mockImplementationOnce(() => {
4012
+ throw new Error('Remove failed');
4013
+ });
4014
+
4015
+ expect(() => {
4016
+ appEmbed.destroy();
4017
+ }).not.toThrow();
4018
+
4019
+ expect(logSpy).toHaveBeenCalledWith('Error destroying TS Embed', expect.any(Error));
4020
+ logSpy.mockRestore();
4021
+ });
4022
+ });
4023
+
4024
+ describe('Fullscreen change handler behavior', () => {
4025
+ beforeAll(() => {
4026
+ init({
4027
+ thoughtSpotHost: 'tshost',
4028
+ authType: AuthType.None,
4029
+ disableFullscreenPresentation: false,
4030
+ });
4031
+ });
4032
+
4033
+ beforeEach(() => {
4034
+ document.body.innerHTML = getDocumentBody();
4035
+ });
4036
+
4037
+ test('should trigger ExitPresentMode when exiting fullscreen', async () => {
4038
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
4039
+ ...defaultViewConfig,
4040
+ liveboardId: 'test-lb',
4041
+ });
4042
+ await liveboardEmbed.render();
4043
+
4044
+ await executeAfterWait(() => {
4045
+ const iframe = getIFrameEl();
4046
+ expect(iframe).toBeTruthy();
4047
+ });
4048
+
4049
+ mockProcessTrigger.mockResolvedValue({});
4050
+
4051
+ liveboardEmbed['setupFullscreenChangeHandler']();
4052
+
4053
+ Object.defineProperty(document, 'fullscreenElement', {
4054
+ value: null,
4055
+ writable: true,
4056
+ configurable: true,
4057
+ });
4058
+
4059
+ const event = new Event('fullscreenchange');
4060
+ document.dispatchEvent(event);
4061
+
4062
+ await executeAfterWait(() => {
4063
+ expect(mockProcessTrigger).toHaveBeenCalledWith(
4064
+ expect.any(Object),
4065
+ HostEvent.ExitPresentMode,
4066
+ expect.any(String),
4067
+ expect.any(Object),
4068
+ );
4069
+ });
4070
+ });
4071
+
4072
+ test('should not trigger ExitPresentMode when entering fullscreen', async () => {
4073
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
4074
+ ...defaultViewConfig,
4075
+ liveboardId: 'test-lb-fullscreen',
4076
+ });
4077
+ await liveboardEmbed.render();
4078
+
4079
+ await executeAfterWait(() => {
4080
+ const iframe = getIFrameEl();
4081
+ expect(iframe).toBeTruthy();
4082
+ });
4083
+
4084
+ mockProcessTrigger.mockClear();
4085
+ mockProcessTrigger.mockResolvedValue({});
4086
+
4087
+ liveboardEmbed['setupFullscreenChangeHandler']();
4088
+
4089
+ Object.defineProperty(document, 'fullscreenElement', {
4090
+ value: getIFrameEl(),
4091
+ writable: true,
4092
+ configurable: true,
4093
+ });
4094
+
4095
+ const event = new Event('fullscreenchange');
4096
+ document.dispatchEvent(event);
4097
+
4098
+ await executeAfterWait(() => {
4099
+ expect(mockProcessTrigger).not.toHaveBeenCalledWith(
4100
+ expect.any(Object),
4101
+ HostEvent.ExitPresentMode,
4102
+ expect.any(String),
4103
+ expect.any(Object),
4104
+ );
4105
+ });
4106
+ });
4107
+ });
4108
+
4109
+ describe('ShowPreRender with UpdateEmbedParams', () => {
4110
+ beforeAll(() => {
4111
+ init({
4112
+ thoughtSpotHost: 'tshost',
4113
+ authType: AuthType.None,
4114
+ });
4115
+ });
4116
+
4117
+ afterEach(() => {
4118
+ const rootEle = document.getElementById('myRoot');
4119
+ rootEle?.remove();
4120
+ });
4121
+
4122
+ test('should trigger UpdateEmbedParams when showPreRender connects to existing prerendered component', async () => {
4123
+ createRootEleForEmbed();
4124
+ mockMessageChannel();
4125
+
4126
+ (window as any).ResizeObserver = window.ResizeObserver
4127
+ || jest.fn().mockImplementation(() => ({
4128
+ disconnect: jest.fn(),
4129
+ observe: jest.fn(),
4130
+ unobserve: jest.fn(),
4131
+ }));
4132
+
4133
+ const embed1 = new LiveboardEmbed('#tsEmbedDiv', {
4134
+ preRenderId: 'update-params-test',
4135
+ liveboardId: 'original-lb',
4136
+ });
4137
+
4138
+ await embed1.preRender();
4139
+ await waitFor(() => !!getIFrameEl());
4140
+
4141
+ embed1.isEmbedContainerLoaded = true;
4142
+
4143
+ mockProcessTrigger.mockClear();
4144
+ mockProcessTrigger.mockResolvedValue({});
4145
+
4146
+ const embed2 = new LiveboardEmbed('#tsEmbedDiv', {
4147
+ preRenderId: 'update-params-test',
4148
+ liveboardId: 'updated-lb',
4149
+ });
4150
+
4151
+ embed2.showPreRender();
4152
+
4153
+ await executeAfterWait(() => {
4154
+ expect(mockProcessTrigger).toHaveBeenCalledWith(
4155
+ expect.any(Object),
4156
+ HostEvent.UpdateEmbedParams,
4157
+ expect.any(String),
4158
+ expect.objectContaining({
4159
+ liveboardId: 'updated-lb',
4160
+ }),
4161
+ );
4162
+ });
4163
+ });
4164
+ });