@thoughtspot/visual-embed-sdk 1.48.0 → 1.49.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 (217) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +140 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +62 -1
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +57 -6
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +191 -1
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/auto-frame-renderer.js +7 -2
  11. package/cjs/src/embed/auto-frame-renderer.js.map +1 -1
  12. package/cjs/src/embed/auto-frame-renderer.spec.js +385 -6
  13. package/cjs/src/embed/auto-frame-renderer.spec.js.map +1 -1
  14. package/cjs/src/embed/base.d.ts +1 -0
  15. package/cjs/src/embed/base.d.ts.map +1 -1
  16. package/cjs/src/embed/base.js +13 -1
  17. package/cjs/src/embed/base.js.map +1 -1
  18. package/cjs/src/embed/base.spec.js +21 -0
  19. package/cjs/src/embed/base.spec.js.map +1 -1
  20. package/cjs/src/embed/bodyless-conversation.spec.js +86 -0
  21. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  22. package/cjs/src/embed/conversation.d.ts +16 -1
  23. package/cjs/src/embed/conversation.d.ts.map +1 -1
  24. package/cjs/src/embed/conversation.js +5 -1
  25. package/cjs/src/embed/conversation.js.map +1 -1
  26. package/cjs/src/embed/conversation.spec.js +26 -0
  27. package/cjs/src/embed/conversation.spec.js.map +1 -1
  28. package/cjs/src/embed/liveboard.d.ts +47 -1
  29. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  30. package/cjs/src/embed/liveboard.js +47 -6
  31. package/cjs/src/embed/liveboard.js.map +1 -1
  32. package/cjs/src/embed/liveboard.spec.js +129 -1
  33. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  34. package/cjs/src/embed/spotter-viz-utils.d.ts +85 -0
  35. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -0
  36. package/cjs/src/embed/spotter-viz-utils.js +17 -0
  37. package/cjs/src/embed/spotter-viz-utils.js.map +1 -0
  38. package/cjs/src/embed/spotter-viz-utils.spec.d.ts +2 -0
  39. package/cjs/src/embed/spotter-viz-utils.spec.d.ts.map +1 -0
  40. package/cjs/src/embed/spotter-viz-utils.spec.js +31 -0
  41. package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -0
  42. package/cjs/src/embed/ts-embed.d.ts +58 -38
  43. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  44. package/cjs/src/embed/ts-embed.js +247 -151
  45. package/cjs/src/embed/ts-embed.js.map +1 -1
  46. package/cjs/src/embed/ts-embed.spec.js +369 -123
  47. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  48. package/cjs/src/index.d.ts +2 -1
  49. package/cjs/src/index.d.ts.map +1 -1
  50. package/cjs/src/index.js.map +1 -1
  51. package/cjs/src/mixpanel-service.js +2 -2
  52. package/cjs/src/mixpanel-service.js.map +1 -1
  53. package/cjs/src/react/index.d.ts.map +1 -1
  54. package/cjs/src/react/index.js +3 -0
  55. package/cjs/src/react/index.js.map +1 -1
  56. package/cjs/src/types.d.ts +267 -27
  57. package/cjs/src/types.d.ts.map +1 -1
  58. package/cjs/src/types.js +223 -19
  59. package/cjs/src/types.js.map +1 -1
  60. package/cjs/src/utils/authService/tokenizedAuthService.spec.js +6 -7
  61. package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  62. package/cjs/src/utils/logger.js +2 -1
  63. package/cjs/src/utils/logger.js.map +1 -1
  64. package/cjs/src/utils/logger.spec.d.ts +1 -0
  65. package/cjs/src/utils/logger.spec.d.ts.map +1 -1
  66. package/cjs/src/utils/logger.spec.js +10 -9
  67. package/cjs/src/utils/logger.spec.js.map +1 -1
  68. package/cjs/src/utils/sdk-version.d.ts +2 -0
  69. package/cjs/src/utils/sdk-version.d.ts.map +1 -0
  70. package/cjs/src/utils/sdk-version.js +7 -0
  71. package/cjs/src/utils/sdk-version.js.map +1 -0
  72. package/cjs/src/utils.d.ts +4 -1
  73. package/cjs/src/utils.d.ts.map +1 -1
  74. package/cjs/src/utils.js +107 -10
  75. package/cjs/src/utils.js.map +1 -1
  76. package/cjs/src/utils.spec.js +163 -4
  77. package/cjs/src/utils.spec.js.map +1 -1
  78. package/dist/{index-Ck-r09gt.js → index-B6Rn561t.js} +1 -1
  79. package/dist/src/css-variables.d.ts +140 -0
  80. package/dist/src/css-variables.d.ts.map +1 -1
  81. package/dist/src/embed/app.d.ts +62 -1
  82. package/dist/src/embed/app.d.ts.map +1 -1
  83. package/dist/src/embed/base.d.ts +1 -0
  84. package/dist/src/embed/base.d.ts.map +1 -1
  85. package/dist/src/embed/conversation.d.ts +16 -1
  86. package/dist/src/embed/conversation.d.ts.map +1 -1
  87. package/dist/src/embed/liveboard.d.ts +47 -1
  88. package/dist/src/embed/liveboard.d.ts.map +1 -1
  89. package/dist/src/embed/spotter-viz-utils.d.ts +85 -0
  90. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -0
  91. package/dist/src/embed/spotter-viz-utils.spec.d.ts +2 -0
  92. package/dist/src/embed/spotter-viz-utils.spec.d.ts.map +1 -0
  93. package/dist/src/embed/ts-embed.d.ts +58 -38
  94. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  95. package/dist/src/index.d.ts +2 -1
  96. package/dist/src/index.d.ts.map +1 -1
  97. package/dist/src/react/index.d.ts.map +1 -1
  98. package/dist/src/types.d.ts +267 -27
  99. package/dist/src/types.d.ts.map +1 -1
  100. package/dist/src/utils/logger.spec.d.ts +1 -0
  101. package/dist/src/utils/logger.spec.d.ts.map +1 -1
  102. package/dist/src/utils/sdk-version.d.ts +2 -0
  103. package/dist/src/utils/sdk-version.d.ts.map +1 -0
  104. package/dist/src/utils.d.ts +4 -1
  105. package/dist/src/utils.d.ts.map +1 -1
  106. package/dist/tsembed-react.es.js +3710 -3226
  107. package/dist/tsembed-react.js +3360 -2876
  108. package/dist/tsembed.es.js +3715 -3229
  109. package/dist/tsembed.js +3710 -3224
  110. package/dist/visual-embed-sdk-react-full.d.ts +643 -63
  111. package/dist/visual-embed-sdk-react.d.ts +643 -63
  112. package/dist/visual-embed-sdk.d.ts +658 -65
  113. package/lib/package.json +1 -1
  114. package/lib/src/css-variables.d.ts +140 -0
  115. package/lib/src/css-variables.d.ts.map +1 -1
  116. package/lib/src/embed/app.d.ts +62 -1
  117. package/lib/src/embed/app.d.ts.map +1 -1
  118. package/lib/src/embed/app.js +58 -7
  119. package/lib/src/embed/app.js.map +1 -1
  120. package/lib/src/embed/app.spec.js +192 -2
  121. package/lib/src/embed/app.spec.js.map +1 -1
  122. package/lib/src/embed/auto-frame-renderer.js +7 -2
  123. package/lib/src/embed/auto-frame-renderer.js.map +1 -1
  124. package/lib/src/embed/auto-frame-renderer.spec.js +387 -8
  125. package/lib/src/embed/auto-frame-renderer.spec.js.map +1 -1
  126. package/lib/src/embed/base.d.ts +1 -0
  127. package/lib/src/embed/base.d.ts.map +1 -1
  128. package/lib/src/embed/base.js +11 -0
  129. package/lib/src/embed/base.js.map +1 -1
  130. package/lib/src/embed/base.spec.js +22 -1
  131. package/lib/src/embed/base.spec.js.map +1 -1
  132. package/lib/src/embed/bodyless-conversation.spec.js +86 -0
  133. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  134. package/lib/src/embed/conversation.d.ts +16 -1
  135. package/lib/src/embed/conversation.d.ts.map +1 -1
  136. package/lib/src/embed/conversation.js +5 -1
  137. package/lib/src/embed/conversation.js.map +1 -1
  138. package/lib/src/embed/conversation.spec.js +27 -1
  139. package/lib/src/embed/conversation.spec.js.map +1 -1
  140. package/lib/src/embed/liveboard.d.ts +47 -1
  141. package/lib/src/embed/liveboard.d.ts.map +1 -1
  142. package/lib/src/embed/liveboard.js +48 -7
  143. package/lib/src/embed/liveboard.js.map +1 -1
  144. package/lib/src/embed/liveboard.spec.js +129 -1
  145. package/lib/src/embed/liveboard.spec.js.map +1 -1
  146. package/lib/src/embed/spotter-viz-utils.d.ts +85 -0
  147. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -0
  148. package/lib/src/embed/spotter-viz-utils.js +13 -0
  149. package/lib/src/embed/spotter-viz-utils.js.map +1 -0
  150. package/lib/src/embed/spotter-viz-utils.spec.d.ts +2 -0
  151. package/lib/src/embed/spotter-viz-utils.spec.d.ts.map +1 -0
  152. package/lib/src/embed/spotter-viz-utils.spec.js +29 -0
  153. package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -0
  154. package/lib/src/embed/ts-embed.d.ts +58 -38
  155. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  156. package/lib/src/embed/ts-embed.js +249 -153
  157. package/lib/src/embed/ts-embed.js.map +1 -1
  158. package/lib/src/embed/ts-embed.spec.js +369 -123
  159. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  160. package/lib/src/index.d.ts +2 -1
  161. package/lib/src/index.d.ts.map +1 -1
  162. package/lib/src/index.js.map +1 -1
  163. package/lib/src/mixpanel-service.js +1 -1
  164. package/lib/src/mixpanel-service.js.map +1 -1
  165. package/lib/src/react/index.d.ts.map +1 -1
  166. package/lib/src/react/index.js +3 -0
  167. package/lib/src/react/index.js.map +1 -1
  168. package/lib/src/types.d.ts +267 -27
  169. package/lib/src/types.d.ts.map +1 -1
  170. package/lib/src/types.js +223 -19
  171. package/lib/src/types.js.map +1 -1
  172. package/lib/src/utils/authService/tokenizedAuthService.spec.js +6 -7
  173. package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  174. package/lib/src/utils/logger.js +2 -1
  175. package/lib/src/utils/logger.js.map +1 -1
  176. package/lib/src/utils/logger.spec.d.ts +1 -0
  177. package/lib/src/utils/logger.spec.d.ts.map +1 -1
  178. package/lib/src/utils/logger.spec.js +10 -9
  179. package/lib/src/utils/logger.spec.js.map +1 -1
  180. package/lib/src/utils/sdk-version.d.ts +2 -0
  181. package/lib/src/utils/sdk-version.d.ts.map +1 -0
  182. package/lib/src/utils/sdk-version.js +3 -0
  183. package/lib/src/utils/sdk-version.js.map +1 -0
  184. package/lib/src/utils.d.ts +4 -1
  185. package/lib/src/utils.d.ts.map +1 -1
  186. package/lib/src/utils.js +103 -9
  187. package/lib/src/utils.js.map +1 -1
  188. package/lib/src/utils.spec.js +164 -5
  189. package/lib/src/utils.spec.js.map +1 -1
  190. package/lib/src/visual-embed-sdk.d.ts +658 -65
  191. package/package.json +1 -1
  192. package/src/css-variables.ts +175 -1
  193. package/src/embed/app.spec.ts +247 -3
  194. package/src/embed/app.ts +125 -5
  195. package/src/embed/auto-frame-renderer.spec.ts +457 -58
  196. package/src/embed/auto-frame-renderer.ts +7 -2
  197. package/src/embed/base.spec.ts +25 -1
  198. package/src/embed/base.ts +19 -5
  199. package/src/embed/bodyless-conversation.spec.ts +93 -0
  200. package/src/embed/conversation.spec.ts +34 -0
  201. package/src/embed/conversation.ts +22 -1
  202. package/src/embed/liveboard.spec.ts +149 -1
  203. package/src/embed/liveboard.ts +102 -6
  204. package/src/embed/spotter-viz-utils.spec.ts +30 -0
  205. package/src/embed/spotter-viz-utils.ts +94 -0
  206. package/src/embed/ts-embed.spec.ts +532 -234
  207. package/src/embed/ts-embed.ts +384 -258
  208. package/src/index.ts +3 -0
  209. package/src/mixpanel-service.ts +1 -1
  210. package/src/react/index.tsx +3 -0
  211. package/src/types.ts +284 -23
  212. package/src/utils/authService/tokenizedAuthService.spec.ts +6 -6
  213. package/src/utils/logger.spec.ts +11 -9
  214. package/src/utils/logger.ts +2 -2
  215. package/src/utils/sdk-version.ts +3 -0
  216. package/src/utils.spec.ts +200 -4
  217. package/src/utils.ts +128 -9
@@ -81,7 +81,7 @@ const getMockAppInitPayload = (data) => {
81
81
  interceptUrls: [],
82
82
  shouldBypassPayloadValidation: undefined,
83
83
  useHostEventsV2: undefined,
84
- embedExpiryInAuthToken: true
84
+ embedExpiryInAuthToken: true,
85
85
  };
86
86
  return {
87
87
  type: EmbedEvent.APP_INIT,
@@ -370,7 +370,10 @@ describe('Unit test case for ts embed', () => {
370
370
  });
371
371
  await executeAfterWait(() => {
372
372
  expect(mockPort.postMessage).toHaveBeenCalledWith(getMockAppInitPayload({
373
- reorderedHomepageModules: [HomepageModule.MyLibrary, HomepageModule.Watchlist],
373
+ reorderedHomepageModules: [
374
+ HomepageModule.MyLibrary,
375
+ HomepageModule.Watchlist,
376
+ ],
374
377
  }));
375
378
  });
376
379
  });
@@ -516,7 +519,10 @@ describe('Unit test case for ts embed', () => {
516
519
  });
517
520
  await executeAfterWait(() => {
518
521
  expect(mockPort.postMessage).toHaveBeenCalledWith(getMockAppInitPayload({
519
- hiddenHomeLeftNavItems: [HomeLeftNavItem.Home, HomeLeftNavItem.MonitorSubscription],
522
+ hiddenHomeLeftNavItems: [
523
+ HomeLeftNavItem.Home,
524
+ HomeLeftNavItem.MonitorSubscription,
525
+ ],
520
526
  }));
521
527
  });
522
528
  });
@@ -744,10 +750,8 @@ describe('Unit test case for ts embed', () => {
744
750
  customVariablesForThirdPartyTools: {},
745
751
  }));
746
752
  const customisationContent = mockPort.postMessage.mock.calls[0][0].data.customisations.content;
747
- expect(customisationContent.stringIDsUrl)
748
- .toBe('https://sample-string-ids-url.com');
749
- expect(customisationContent.stringIDs)
750
- .toEqual({
753
+ expect(customisationContent.stringIDsUrl).toBe('https://sample-string-ids-url.com');
754
+ expect(customisationContent.stringIDs).toEqual({
751
755
  'liveboard.header.title': 'Dashboard name',
752
756
  });
753
757
  });
@@ -757,7 +761,10 @@ describe('Unit test case for ts embed', () => {
757
761
  type: EmbedEvent.APP_INIT,
758
762
  data: {},
759
763
  };
760
- const searchEmbed = new SearchEmbed(getRootEl(), { ...defaultViewConfig, exposeTranslationIDs: true });
764
+ const searchEmbed = new SearchEmbed(getRootEl(), {
765
+ ...defaultViewConfig,
766
+ exposeTranslationIDs: true,
767
+ });
761
768
  searchEmbed.render();
762
769
  const mockPort = {
763
770
  postMessage: jest.fn(),
@@ -798,16 +805,16 @@ describe('Unit test case for ts embed', () => {
798
805
  name: 'Valid Action',
799
806
  target: CustomActionTarget.LIVEBOARD,
800
807
  position: CustomActionsPosition.PRIMARY,
801
- metadataIds: { liveboardIds: ['lb123'] }
808
+ metadataIds: { liveboardIds: ['lb123'] },
802
809
  },
803
810
  {
804
811
  id: 'action2',
805
812
  name: 'Another Valid Action',
806
813
  target: CustomActionTarget.VIZ,
807
814
  position: CustomActionsPosition.MENU,
808
- metadataIds: { vizIds: ['viz456'] }
809
- }
810
- ]
815
+ metadataIds: { vizIds: ['viz456'] },
816
+ },
817
+ ],
811
818
  });
812
819
  searchEmbed.render();
813
820
  const mockPort = {
@@ -833,15 +840,15 @@ describe('Unit test case for ts embed', () => {
833
840
  name: 'Another Valid Action',
834
841
  target: CustomActionTarget.VIZ,
835
842
  position: CustomActionsPosition.MENU,
836
- metadataIds: { vizIds: ['viz456'] }
843
+ metadataIds: { vizIds: ['viz456'] },
837
844
  },
838
845
  {
839
846
  id: 'action1',
840
847
  name: 'Valid Action',
841
848
  target: CustomActionTarget.LIVEBOARD,
842
849
  position: CustomActionsPosition.PRIMARY,
843
- metadataIds: { liveboardIds: ['lb123'] }
844
- }
850
+ metadataIds: { liveboardIds: ['lb123'] },
851
+ },
845
852
  ],
846
853
  customVariablesForThirdPartyTools: {},
847
854
  }));
@@ -854,14 +861,14 @@ describe('Unit test case for ts embed', () => {
854
861
  id: 'action1',
855
862
  name: 'Valid Action',
856
863
  target: CustomActionTarget.LIVEBOARD,
857
- position: CustomActionsPosition.PRIMARY
864
+ position: CustomActionsPosition.PRIMARY,
858
865
  }),
859
866
  expect.objectContaining({
860
867
  id: 'action2',
861
868
  name: 'Another Valid Action',
862
869
  target: CustomActionTarget.VIZ,
863
- position: CustomActionsPosition.MENU
864
- })
870
+ position: CustomActionsPosition.MENU,
871
+ }),
865
872
  ]));
866
873
  // Verify actions are sorted by name (alphabetically)
867
874
  expect(appInitData.customActions[0].name).toBe('Another Valid Action');
@@ -915,7 +922,10 @@ describe('Unit test case for ts embed', () => {
915
922
  type: EmbedEvent.APP_INIT,
916
923
  data: {},
917
924
  };
918
- const searchEmbed = new SearchEmbed(getRootEl(), { ...defaultViewConfig, preRenderId: 'test' });
925
+ const searchEmbed = new SearchEmbed(getRootEl(), {
926
+ ...defaultViewConfig,
927
+ preRenderId: 'test',
928
+ });
919
929
  searchEmbed.preRender();
920
930
  const mockPort = {
921
931
  postMessage: jest.fn(),
@@ -966,7 +976,10 @@ describe('Unit test case for ts embed', () => {
966
976
  type: EmbedEvent.AuthExpire,
967
977
  data: {},
968
978
  };
969
- const searchEmbed = new SearchEmbed(getRootEl(), { ...defaultViewConfig, preRenderId: 'test' });
979
+ const searchEmbed = new SearchEmbed(getRootEl(), {
980
+ ...defaultViewConfig,
981
+ preRenderId: 'test',
982
+ });
970
983
  jest.spyOn(baseInstance, 'notifyAuthFailure');
971
984
  searchEmbed.preRender();
972
985
  const loggerSpy = jest.spyOn(logger, 'error').mockImplementation(() => { });
@@ -1106,9 +1119,13 @@ describe('Unit test case for ts embed', () => {
1106
1119
  // resetCachedPreauthInfo();
1107
1120
  let mockGetPreauthInfo = null;
1108
1121
  if (overrideOrgId) {
1109
- mockGetPreauthInfo = jest.spyOn(sessionInfoService, 'getPreauthInfo').mockImplementation(jest.fn());
1122
+ mockGetPreauthInfo = jest
1123
+ .spyOn(sessionInfoService, 'getPreauthInfo')
1124
+ .mockImplementation(jest.fn());
1110
1125
  }
1111
- const mockPreauthInfoFetch = jest.spyOn(authService, 'fetchPreauthInfoService').mockResolvedValueOnce({
1126
+ const mockPreauthInfoFetch = jest
1127
+ .spyOn(authService, 'fetchPreauthInfoService')
1128
+ .mockResolvedValueOnce({
1112
1129
  ok: true,
1113
1130
  headers: new Headers({ 'content-type': 'application/json' }),
1114
1131
  json: async () => ({
@@ -1143,14 +1160,14 @@ describe('Unit test case for ts embed', () => {
1143
1160
  };
1144
1161
  };
1145
1162
  test('should call InfoSuccess Event on preauth call success', async () => {
1146
- const { mockPreauthInfoFetch, iFrame, } = await setup(true);
1163
+ const { mockPreauthInfoFetch, iFrame } = await setup(true);
1147
1164
  expect(mockPreauthInfoFetch).toHaveBeenCalledTimes(1);
1148
1165
  await executeAfterWait(() => {
1149
1166
  expect(mockProcessTrigger).toHaveBeenCalledWith(iFrame, HostEvent.InfoSuccess, 'http://tshost', expect.objectContaining({ info: expect.any(Object) }), undefined);
1150
1167
  });
1151
1168
  });
1152
1169
  test('should not call InfoSuccess Event if overrideOrgId is true', async () => {
1153
- const { mockGetPreauthInfo, } = await setup(true, 123);
1170
+ const { mockGetPreauthInfo } = await setup(true, 123);
1154
1171
  expect(mockGetPreauthInfo).toHaveBeenCalledTimes(0);
1155
1172
  });
1156
1173
  });
@@ -1183,14 +1200,17 @@ describe('Unit test case for ts embed', () => {
1183
1200
  const isAppEmbedWithPrimaryNavbar = embedType === 'AppEmbed' && showPrimaryNavbar === true;
1184
1201
  const shouldDisableCache = overrideOrgId || disablePreauthCache || isAppEmbedWithPrimaryNavbar;
1185
1202
  if (shouldDisableCache) {
1186
- mockGetPreauthInfo = jest.spyOn(sessionInfoService, 'getPreauthInfo')
1203
+ mockGetPreauthInfo = jest
1204
+ .spyOn(sessionInfoService, 'getPreauthInfo')
1187
1205
  .mockImplementation(jest.fn());
1188
1206
  }
1189
1207
  else {
1190
- mockGetPreauthInfo = jest.spyOn(sessionInfoService, 'getPreauthInfo')
1208
+ mockGetPreauthInfo = jest
1209
+ .spyOn(sessionInfoService, 'getPreauthInfo')
1191
1210
  .mockResolvedValue({ info: { test: 'data' } });
1192
1211
  }
1193
- const mockPreauthInfoFetch = jest.spyOn(authService, 'fetchPreauthInfoService')
1212
+ const mockPreauthInfoFetch = jest
1213
+ .spyOn(authService, 'fetchPreauthInfoService')
1194
1214
  .mockResolvedValueOnce({
1195
1215
  ok: true,
1196
1216
  headers: new Headers({ 'content-type': 'application/json' }),
@@ -1662,8 +1682,8 @@ describe('Unit test case for ts embed', () => {
1662
1682
  },
1663
1683
  });
1664
1684
  await appEmbed.render();
1665
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1666
- + `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`);
1685
+ expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
1686
+ `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`);
1667
1687
  });
1668
1688
  it('should set the additional flags correctly on the iframe src from init and view config', async () => {
1669
1689
  init({
@@ -1687,8 +1707,8 @@ describe('Unit test case for ts embed', () => {
1687
1707
  },
1688
1708
  });
1689
1709
  await appEmbed.render();
1690
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1691
- + `&foo=bar&foo2=bar2&foo3=false&baz=1&bool=true${defaultParamsPost}#/home`);
1710
+ expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
1711
+ `&foo=bar&foo2=bar2&foo3=false&baz=1&bool=true${defaultParamsPost}#/home`);
1692
1712
  });
1693
1713
  it('Sets the showAlerts param', async () => {
1694
1714
  const appEmbed = new AppEmbed(getRootEl(), {
@@ -1699,8 +1719,8 @@ describe('Unit test case for ts embed', () => {
1699
1719
  showAlerts: true,
1700
1720
  });
1701
1721
  await appEmbed.render();
1702
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1703
- + `&showAlerts=true${defaultParamsPost}#/home`);
1722
+ expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
1723
+ `&showAlerts=true${defaultParamsPost}#/home`);
1704
1724
  });
1705
1725
  it('Sets the locale param', async () => {
1706
1726
  const appEmbed = new AppEmbed(getRootEl(), {
@@ -1711,8 +1731,8 @@ describe('Unit test case for ts embed', () => {
1711
1731
  locale: 'ja-JP',
1712
1732
  });
1713
1733
  await appEmbed.render();
1714
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1715
- + `&locale=ja-JP${defaultParamsPost}#/home`);
1734
+ expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
1735
+ `&locale=ja-JP${defaultParamsPost}#/home`);
1716
1736
  });
1717
1737
  it('Sets both params when enableLinkOverridesV2 is set', async () => {
1718
1738
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
@@ -1726,7 +1746,7 @@ describe('Unit test case for ts embed', () => {
1726
1746
  await liveboardEmbed.render();
1727
1747
  expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&${defaultParamsForPinboardEmbed}&enableLinkOverridesV2=true&linkOverride=true${defaultParamsPost}#/embed/viz/test-lb`);
1728
1748
  });
1729
- it('Sets only linkOverride when enableLinkOverridesV2 is not set', async () => {
1749
+ it('Auto-upgrades V1 linkOverride to V2 (sends both flags)', async () => {
1730
1750
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1731
1751
  frameParams: {
1732
1752
  width: '100%',
@@ -1736,7 +1756,40 @@ describe('Unit test case for ts embed', () => {
1736
1756
  linkOverride: true,
1737
1757
  });
1738
1758
  await liveboardEmbed.render();
1739
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&${defaultParamsForPinboardEmbed}&linkOverride=true${defaultParamsPost}#/embed/viz/test-lb`);
1759
+ const src = getIFrameSrc();
1760
+ expect(src).toContain('linkOverride=true');
1761
+ expect(src).toContain('enableLinkOverridesV2=true');
1762
+ });
1763
+ it('Auto-disables V2 link overrides when disableRedirectionLinksInNewTab is true', async () => {
1764
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1765
+ frameParams: {
1766
+ width: '100%',
1767
+ height: '100%',
1768
+ },
1769
+ liveboardId: 'test-lb',
1770
+ enableLinkOverridesV2: true,
1771
+ disableRedirectionLinksInNewTab: true,
1772
+ });
1773
+ await liveboardEmbed.render();
1774
+ const src = getIFrameSrc();
1775
+ expect(src).not.toContain('enableLinkOverridesV2=true');
1776
+ expect(src).not.toContain('linkOverride=true');
1777
+ expect(src).toContain('disableRedirectionLinksInNewTab=true');
1778
+ });
1779
+ it('Auto-disables V1 link override when disableRedirectionLinksInNewTab is true', async () => {
1780
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1781
+ frameParams: {
1782
+ width: '100%',
1783
+ height: '100%',
1784
+ },
1785
+ liveboardId: 'test-lb',
1786
+ linkOverride: true,
1787
+ disableRedirectionLinksInNewTab: true,
1788
+ });
1789
+ await liveboardEmbed.render();
1790
+ const src = getIFrameSrc();
1791
+ expect(src).not.toContain('linkOverride=true');
1792
+ expect(src).toContain('disableRedirectionLinksInNewTab=true');
1740
1793
  });
1741
1794
  it('Sets the iconSprite url', async () => {
1742
1795
  const appEmbed = new AppEmbed(getRootEl(), {
@@ -1749,8 +1802,8 @@ describe('Unit test case for ts embed', () => {
1749
1802
  },
1750
1803
  });
1751
1804
  await appEmbed.render();
1752
- expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1753
- + `&iconSprite=iconSprite.com${defaultParamsPost}#/home`);
1805
+ expectUrlMatchesWithParams(getIFrameSrc(), `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
1806
+ `&iconSprite=iconSprite.com${defaultParamsPost}#/home`);
1754
1807
  });
1755
1808
  it('inserts as sibling of root node if configured', async () => {
1756
1809
  const appEmbed = new AppEmbed(getRootEl(), {
@@ -1983,22 +2036,26 @@ describe('Unit test case for ts embed', () => {
1983
2036
  tsEmbedDiv.style.width = '100px';
1984
2037
  tsEmbedDiv.style.height = '100px';
1985
2038
  let resizeObserverCb;
1986
- window.ResizeObserver = window.ResizeObserver
1987
- || jest.fn().mockImplementation((resizeObserverCbParam) => {
1988
- resizeObserverCb = resizeObserverCbParam;
1989
- return {
1990
- disconnect: jest.fn(),
1991
- observe: jest.fn(),
1992
- unobserve: jest.fn(),
1993
- };
1994
- });
2039
+ window.ResizeObserver =
2040
+ window.ResizeObserver ||
2041
+ jest.fn().mockImplementation((resizeObserverCbParam) => {
2042
+ resizeObserverCb = resizeObserverCbParam;
2043
+ return {
2044
+ disconnect: jest.fn(),
2045
+ observe: jest.fn(),
2046
+ unobserve: jest.fn(),
2047
+ };
2048
+ });
1995
2049
  // show preRender
1996
2050
  const warnSpy = jest.spyOn(logger, 'warn');
1997
2051
  libEmbed.showPreRender();
1998
2052
  expect(warnSpy).toHaveBeenCalledTimes(1);
2053
+ // The ResizeObserver now tracks the placeholder inside this.el,
2054
+ // not this.el itself, so pass it as the target.
2055
+ const preRenderPlaceholder = tsEmbedDiv.firstElementChild;
1999
2056
  resizeObserverCb([
2000
2057
  {
2001
- target: tsEmbedDiv,
2058
+ target: preRenderPlaceholder,
2002
2059
  contentRect: { height: 297, width: 987 },
2003
2060
  },
2004
2061
  ]);
@@ -2049,12 +2106,13 @@ describe('Unit test case for ts embed', () => {
2049
2106
  });
2050
2107
  it('should set overflow:hidden when hidePreRender and remove when showPreRender', async () => {
2051
2108
  createRootEleForEmbed();
2052
- window.ResizeObserver = window.ResizeObserver
2053
- || jest.fn().mockImplementation(() => ({
2054
- disconnect: jest.fn(),
2055
- observe: jest.fn(),
2056
- unobserve: jest.fn(),
2057
- }));
2109
+ window.ResizeObserver =
2110
+ window.ResizeObserver ||
2111
+ jest.fn().mockImplementation(() => ({
2112
+ disconnect: jest.fn(),
2113
+ observe: jest.fn(),
2114
+ unobserve: jest.fn(),
2115
+ }));
2058
2116
  const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2059
2117
  preRenderId: 'overflow-test',
2060
2118
  liveboardId: 'myLiveboardId',
@@ -2080,27 +2138,28 @@ describe('Unit test case for ts embed', () => {
2080
2138
  it('it should connect with another object', async () => {
2081
2139
  createRootEleForEmbed();
2082
2140
  mockMessageChannel();
2083
- window.ResizeObserver = window.ResizeObserver
2084
- || jest.fn().mockImplementation(() => ({
2085
- disconnect: jest.fn(),
2086
- observe: jest.fn(),
2087
- unobserve: jest.fn(),
2088
- }));
2141
+ window.ResizeObserver =
2142
+ window.ResizeObserver ||
2143
+ jest.fn().mockImplementation(() => ({
2144
+ disconnect: jest.fn(),
2145
+ observe: jest.fn(),
2146
+ unobserve: jest.fn(),
2147
+ }));
2089
2148
  const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2090
2149
  preRenderId: 'i-am-preRendered',
2091
2150
  liveboardId: 'myLiveboardId',
2092
2151
  });
2093
2152
  libEmbed.preRender();
2094
2153
  await waitFor(() => !!getIFrameEl());
2095
- const warnSpy = jest.spyOn(logger, 'warn');
2096
2154
  const newEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2097
2155
  preRenderId: 'i-am-preRendered',
2098
2156
  liveboardId: 'awdawda',
2099
2157
  hiddenActions: [Action.AddFilter],
2100
2158
  frameParams: { height: 90 },
2101
2159
  });
2102
- newEmbed.showPreRender();
2103
- expect(warnSpy).toHaveBeenCalledTimes(2);
2160
+ await newEmbed.showPreRender();
2161
+ // Verify newEmbed successfully connected to the existing preRender
2162
+ expect(newEmbed.isPreRenderConnected()).toBe(true);
2104
2163
  });
2105
2164
  it('showPreRender should not preRender if not available', async () => {
2106
2165
  createRootEleForEmbed();
@@ -2251,7 +2310,10 @@ describe('Unit test case for ts embed', () => {
2251
2310
  document.body.innerHTML = getDocumentBody();
2252
2311
  });
2253
2312
  test('Pre-render should wait for init to complete', async () => {
2254
- const lib = new LiveboardEmbed(getRootEl(), { preRenderId: 'test', liveboardId: 'test' });
2313
+ const lib = new LiveboardEmbed(getRootEl(), {
2314
+ preRenderId: 'test',
2315
+ liveboardId: 'test',
2316
+ });
2255
2317
  lib.preRender();
2256
2318
  await executeAfterWait(() => {
2257
2319
  expect(errorSpy).toHaveBeenCalledWith(ERROR_MESSAGE.RENDER_CALLED_BEFORE_INIT);
@@ -2481,7 +2543,11 @@ describe('Unit test case for ts embed', () => {
2481
2543
  expect(authToken.getAuthenticationToken).toHaveBeenCalledWith(expect.any(Object), true);
2482
2544
  // Check that logger.error was called with the token refresh
2483
2545
  // error
2484
- const errorCalls = logger.error.mock.calls.filter((call) => { var _a, _b; return ((_a = call[0]) === null || _a === void 0 ? void 0 : _a.includes(ERROR_MESSAGE.INVALID_TOKEN_ERROR)) && ((_b = call[0]) === null || _b === void 0 ? void 0 : _b.includes('Token fetch failed')); });
2546
+ const errorCalls = logger.error.mock.calls.filter((call) => {
2547
+ var _a, _b;
2548
+ return ((_a = call[0]) === null || _a === void 0 ? void 0 : _a.includes(ERROR_MESSAGE.INVALID_TOKEN_ERROR)) &&
2549
+ ((_b = call[0]) === null || _b === void 0 ? void 0 : _b.includes('Token fetch failed'));
2550
+ });
2485
2551
  expect(errorCalls.length).toBeGreaterThan(0);
2486
2552
  expect(processData.processAuthFailure).toHaveBeenCalledWith(error, expect.any(Element));
2487
2553
  expect(mockPort.postMessage).not.toHaveBeenCalled();
@@ -2643,8 +2709,8 @@ describe('Unit test case for ts embed', () => {
2643
2709
  test('should return getPreRenderObj and log if same object', () => {
2644
2710
  const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2645
2711
  const loggerSpy = jest.spyOn(logger, 'info');
2646
- // Mock insertedDomEl to have the embed object
2647
- searchEmbed.insertedDomEl = {
2712
+ // getPreRenderObj reads the embed reference from preRenderWrapper
2713
+ searchEmbed.preRenderWrapper = {
2648
2714
  [searchEmbed['embedNodeKey']]: searchEmbed,
2649
2715
  };
2650
2716
  const result = searchEmbed['getPreRenderObj']();
@@ -2693,7 +2759,8 @@ describe('Unit test case for ts embed', () => {
2693
2759
  test('should return context when embed container is already loaded', async () => {
2694
2760
  const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2695
2761
  searchEmbed.isEmbedContainerLoaded = true;
2696
- const triggerSpy = jest.spyOn(searchEmbed, 'trigger')
2762
+ const triggerSpy = jest
2763
+ .spyOn(searchEmbed, 'trigger')
2697
2764
  .mockResolvedValue(mockContext);
2698
2765
  const context = await searchEmbed.getCurrentContext();
2699
2766
  expect(context).toEqual(mockContext);
@@ -2702,7 +2769,8 @@ describe('Unit test case for ts embed', () => {
2702
2769
  test('should wait for embed container to load before returning context', async () => {
2703
2770
  const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2704
2771
  searchEmbed.isEmbedContainerLoaded = false;
2705
- const triggerSpy = jest.spyOn(searchEmbed, 'trigger')
2772
+ const triggerSpy = jest
2773
+ .spyOn(searchEmbed, 'trigger')
2706
2774
  .mockResolvedValue(mockContext);
2707
2775
  const contextPromise = searchEmbed.getCurrentContext();
2708
2776
  // Context should not be resolved yet
@@ -2888,9 +2956,11 @@ describe('Unit test case for ts embed', () => {
2888
2956
  });
2889
2957
  await appEmbed.render();
2890
2958
  jest.spyOn(appEmbed, 'trigger').mockRejectedValue(new Error('trigger failed'));
2891
- const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
2959
+ const removeChildSpy = jest
2960
+ .spyOn(Node.prototype, 'removeChild')
2961
+ .mockImplementation(() => getRootEl());
2892
2962
  appEmbed.destroy();
2893
- await new Promise(resolve => setTimeout(resolve, 50));
2963
+ await new Promise((resolve) => setTimeout(resolve, 50));
2894
2964
  expect(removeChildSpy).toHaveBeenCalled();
2895
2965
  embedConfig.setEmbedConfig(originalEmbedConfig);
2896
2966
  });
@@ -2915,7 +2985,9 @@ describe('Unit test case for ts embed', () => {
2915
2985
  });
2916
2986
  await appEmbed.render();
2917
2987
  const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockResolvedValue(null);
2918
- const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
2988
+ const removeChildSpy = jest
2989
+ .spyOn(Node.prototype, 'removeChild')
2990
+ .mockImplementation(() => getRootEl());
2919
2991
  appEmbed.destroy();
2920
2992
  expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
2921
2993
  expect(removeChildSpy).toHaveBeenCalled();
@@ -2934,12 +3006,14 @@ describe('Unit test case for ts embed', () => {
2934
3006
  });
2935
3007
  await appEmbed.render();
2936
3008
  const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockResolvedValue(null);
2937
- const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
3009
+ const removeChildSpy = jest
3010
+ .spyOn(Node.prototype, 'removeChild')
3011
+ .mockImplementation(() => getRootEl());
2938
3012
  appEmbed.destroy();
2939
3013
  // Should be called immediately when config is enabled
2940
3014
  expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
2941
3015
  // Wait for the timeout to complete
2942
- await new Promise(resolve => setTimeout(resolve, 1100));
3016
+ await new Promise((resolve) => setTimeout(resolve, 1100));
2943
3017
  expect(removeChildSpy).toHaveBeenCalled();
2944
3018
  });
2945
3019
  it('should handle Promise.race with successful cleanup completion', async () => {
@@ -2956,11 +3030,15 @@ describe('Unit test case for ts embed', () => {
2956
3030
  });
2957
3031
  await appEmbed.render();
2958
3032
  // Mock trigger to resolve quickly (before timeout)
2959
- const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockImplementation(() => new Promise(resolve => setTimeout(() => resolve(null), 100)));
2960
- const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
3033
+ const triggerSpy = jest
3034
+ .spyOn(appEmbed, 'trigger')
3035
+ .mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve(null), 100)));
3036
+ const removeChildSpy = jest
3037
+ .spyOn(Node.prototype, 'removeChild')
3038
+ .mockImplementation(() => getRootEl());
2961
3039
  appEmbed.destroy();
2962
3040
  // Wait for the trigger to complete
2963
- await new Promise(resolve => setTimeout(resolve, 200));
3041
+ await new Promise((resolve) => setTimeout(resolve, 200));
2964
3042
  expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
2965
3043
  expect(removeChildSpy).toHaveBeenCalled();
2966
3044
  });
@@ -2978,11 +3056,15 @@ describe('Unit test case for ts embed', () => {
2978
3056
  });
2979
3057
  await appEmbed.render();
2980
3058
  // Mock trigger to take longer than timeout
2981
- const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockImplementation(() => new Promise(resolve => setTimeout(() => resolve(null), 500)));
2982
- const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
3059
+ const triggerSpy = jest
3060
+ .spyOn(appEmbed, 'trigger')
3061
+ .mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve(null), 500)));
3062
+ const removeChildSpy = jest
3063
+ .spyOn(Node.prototype, 'removeChild')
3064
+ .mockImplementation(() => getRootEl());
2983
3065
  appEmbed.destroy();
2984
3066
  // Wait for the timeout to complete
2985
- await new Promise(resolve => setTimeout(resolve, 200));
3067
+ await new Promise((resolve) => setTimeout(resolve, 200));
2986
3068
  expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
2987
3069
  expect(removeChildSpy).toHaveBeenCalled();
2988
3070
  });
@@ -3010,11 +3092,11 @@ describe('Unit test case for ts embed', () => {
3010
3092
  body: JSON.stringify({
3011
3093
  variables: {
3012
3094
  session: { sessionId: 'session-123' },
3013
- contextBookId: 'viz-456'
3014
- }
3015
- })
3016
- }
3017
- })
3095
+ contextBookId: 'viz-456',
3096
+ },
3097
+ }),
3098
+ },
3099
+ }),
3018
3100
  };
3019
3101
  const mockPort = {
3020
3102
  postMessage: jest.fn(),
@@ -3045,8 +3127,8 @@ describe('Unit test case for ts embed', () => {
3045
3127
  type: EmbedEvent.ApiIntercept,
3046
3128
  data: JSON.stringify({
3047
3129
  input: '/prism/?op=GetChartWithData',
3048
- init: {}
3049
- })
3130
+ init: {},
3131
+ }),
3050
3132
  };
3051
3133
  const mockPort = {
3052
3134
  postMessage: jest.fn(),
@@ -3078,8 +3160,8 @@ describe('Unit test case for ts embed', () => {
3078
3160
  type: EmbedEvent.ApiIntercept,
3079
3161
  data: JSON.stringify({
3080
3162
  input: '/prism/?op=GetChartWithData',
3081
- init: {}
3082
- })
3163
+ init: {},
3164
+ }),
3083
3165
  };
3084
3166
  const mockPort = {
3085
3167
  postMessage: jest.fn(),
@@ -3096,7 +3178,7 @@ describe('Unit test case for ts embed', () => {
3096
3178
  // handleInterceptEvent
3097
3179
  const result = await capturedGetUnsavedAnswerTml({
3098
3180
  sessionId: 'session-123',
3099
- vizId: 'viz-456'
3181
+ vizId: 'viz-456',
3100
3182
  });
3101
3183
  expect(mockProcessTrigger).toHaveBeenCalled();
3102
3184
  const callArgs = mockProcessTrigger.mock.calls[0];
@@ -3106,8 +3188,8 @@ describe('Unit test case for ts embed', () => {
3106
3188
  type: 'getUnsavedAnswerTML',
3107
3189
  parameters: {
3108
3190
  sessionId: 'session-123',
3109
- vizId: 'viz-456'
3110
- }
3191
+ vizId: 'viz-456',
3192
+ },
3111
3193
  });
3112
3194
  expect(result).toEqual(mockTmlResponse);
3113
3195
  });
@@ -3124,8 +3206,8 @@ describe('Unit test case for ts embed', () => {
3124
3206
  type: EmbedEvent.ApiIntercept,
3125
3207
  data: JSON.stringify({
3126
3208
  input: '/api/test',
3127
- init: {}
3128
- })
3209
+ init: {},
3210
+ }),
3129
3211
  };
3130
3212
  const mockPort = {
3131
3213
  postMessage: jest.fn(),
@@ -3149,8 +3231,8 @@ describe('Unit test case for ts embed', () => {
3149
3231
  type: EmbedEvent.ApiIntercept,
3150
3232
  data: JSON.stringify({
3151
3233
  input: '/prism/?op=GetChartWithData',
3152
- init: {}
3153
- })
3234
+ init: {},
3235
+ }),
3154
3236
  };
3155
3237
  const mockPort = {
3156
3238
  postMessage: jest.fn(),
@@ -3191,15 +3273,15 @@ describe('Unit test case for ts embed', () => {
3191
3273
  type: EmbedEvent.ApiIntercept,
3192
3274
  data: JSON.stringify({
3193
3275
  input: '/prism/?op=GetChartWithData',
3194
- init: {}
3195
- })
3276
+ init: {},
3277
+ }),
3196
3278
  };
3197
3279
  const mockEventData2 = {
3198
3280
  type: EmbedEvent.ApiIntercept,
3199
3281
  data: JSON.stringify({
3200
3282
  input: '/prism/?op=LoadContextBook',
3201
- init: {}
3202
- })
3283
+ init: {},
3284
+ }),
3203
3285
  };
3204
3286
  const mockPort = {
3205
3287
  postMessage: jest.fn(),
@@ -3228,8 +3310,8 @@ describe('Unit test case for ts embed', () => {
3228
3310
  type: EmbedEvent.ApiIntercept,
3229
3311
  data: JSON.stringify({
3230
3312
  input: '/prism/?op=GetChartWithData',
3231
- init: {}
3232
- })
3313
+ init: {},
3314
+ }),
3233
3315
  };
3234
3316
  const mockPort = {
3235
3317
  postMessage: jest.fn(),
@@ -3260,8 +3342,8 @@ describe('Unit test case for ts embed', () => {
3260
3342
  type: EmbedEvent.ApiIntercept,
3261
3343
  data: JSON.stringify({
3262
3344
  input: '/prism/?op=GetChartWithData',
3263
- init: {}
3264
- })
3345
+ init: {},
3346
+ }),
3265
3347
  };
3266
3348
  const mockPort = {
3267
3349
  postMessage: jest.fn(),
@@ -3274,7 +3356,7 @@ describe('Unit test case for ts embed', () => {
3274
3356
  expect(capturedGetUnsavedAnswerTml).toBeDefined();
3275
3357
  const result = await capturedGetUnsavedAnswerTml({
3276
3358
  sessionId: 'session-123',
3277
- vizId: 'viz-456'
3359
+ vizId: 'viz-456',
3278
3360
  });
3279
3361
  expect(result).toBeUndefined();
3280
3362
  });
@@ -3289,8 +3371,8 @@ describe('Unit test case for ts embed', () => {
3289
3371
  type: EmbedEvent.ApiIntercept,
3290
3372
  data: JSON.stringify({
3291
3373
  input: '/prism/?op=LoadContextBook',
3292
- init: {}
3293
- })
3374
+ init: {},
3375
+ }),
3294
3376
  };
3295
3377
  const mockPort = {
3296
3378
  postMessage: jest.fn(),
@@ -3524,12 +3606,13 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3524
3606
  const setupPreRenderTest = async (preRenderId, initialConfig) => {
3525
3607
  createRootEleForEmbed();
3526
3608
  mockMessageChannel();
3527
- window.ResizeObserver = window.ResizeObserver
3528
- || jest.fn().mockImplementation(() => ({
3529
- disconnect: jest.fn(),
3530
- observe: jest.fn(),
3531
- unobserve: jest.fn(),
3532
- }));
3609
+ window.ResizeObserver =
3610
+ window.ResizeObserver ||
3611
+ jest.fn().mockImplementation(() => ({
3612
+ disconnect: jest.fn(),
3613
+ observe: jest.fn(),
3614
+ unobserve: jest.fn(),
3615
+ }));
3533
3616
  const embed1 = new LiveboardEmbed('#tsEmbedDiv', {
3534
3617
  preRenderId,
3535
3618
  ...initialConfig,
@@ -3680,7 +3763,8 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3680
3763
  authType: AuthType.None,
3681
3764
  });
3682
3765
  });
3683
- // Matches the structure produced by createValidationError / embedErrorDetails
3766
+ // Matches the structure produced by createValidationError /
3767
+ // embedErrorDetails
3684
3768
  const makeNestedValidationData = (message = 'invalid payload') => ({
3685
3769
  type: EmbedEvent.Error,
3686
3770
  data: {
@@ -3690,7 +3774,8 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3690
3774
  error: message,
3691
3775
  },
3692
3776
  });
3693
- // Matches the flat structure where errorType sits at the top level of data
3777
+ // Matches the flat structure where errorType sits at the top level of
3778
+ // data
3694
3779
  const makeFlatValidationData = (message = 'invalid payload') => ({
3695
3780
  errorType: EmbedErrorCodes.HOST_EVENT_VALIDATION,
3696
3781
  message,
@@ -3731,14 +3816,20 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3731
3816
  });
3732
3817
  test('delivers Error event to handler when useHostEventsV2 is true and shouldBypassPayloadValidation is undefined', () => {
3733
3818
  const errorHandler = jest.fn();
3734
- const embed = makeEmbed({ useHostEventsV2: true, shouldBypassPayloadValidation: undefined });
3819
+ const embed = makeEmbed({
3820
+ useHostEventsV2: true,
3821
+ shouldBypassPayloadValidation: undefined,
3822
+ });
3735
3823
  embed.on(EmbedEvent.Error, errorHandler);
3736
3824
  embed.executeCallbacks(EmbedEvent.Error, makeNestedValidationData());
3737
3825
  expect(errorHandler).toHaveBeenCalled();
3738
3826
  });
3739
3827
  test('delivers Error event to handler when useHostEventsV2 is true and shouldBypassPayloadValidation is false', () => {
3740
3828
  const errorHandler = jest.fn();
3741
- const embed = makeEmbed({ useHostEventsV2: true, shouldBypassPayloadValidation: false });
3829
+ const embed = makeEmbed({
3830
+ useHostEventsV2: true,
3831
+ shouldBypassPayloadValidation: false,
3832
+ });
3742
3833
  embed.on(EmbedEvent.Error, errorHandler);
3743
3834
  embed.executeCallbacks(EmbedEvent.Error, makeNestedValidationData());
3744
3835
  expect(errorHandler).toHaveBeenCalled();
@@ -3746,7 +3837,10 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3746
3837
  test('skips Error event when useHostEventsV2 is false regardless of shouldBypassPayloadValidation', () => {
3747
3838
  jest.spyOn(logger, 'warn');
3748
3839
  const errorHandler = jest.fn();
3749
- const embed = makeEmbed({ useHostEventsV2: false, shouldBypassPayloadValidation: undefined });
3840
+ const embed = makeEmbed({
3841
+ useHostEventsV2: false,
3842
+ shouldBypassPayloadValidation: undefined,
3843
+ });
3750
3844
  embed.on(EmbedEvent.Error, errorHandler);
3751
3845
  embed.executeCallbacks(EmbedEvent.Error, makeNestedValidationData());
3752
3846
  expect(errorHandler).not.toHaveBeenCalled();
@@ -3762,7 +3856,10 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3762
3856
  test('skips Error event when useHostEventsV2 is false and shouldBypassPayloadValidation is true', () => {
3763
3857
  jest.spyOn(logger, 'warn');
3764
3858
  const errorHandler = jest.fn();
3765
- const embed = makeEmbed({ useHostEventsV2: false, shouldBypassPayloadValidation: true });
3859
+ const embed = makeEmbed({
3860
+ useHostEventsV2: false,
3861
+ shouldBypassPayloadValidation: true,
3862
+ });
3766
3863
  embed.on(EmbedEvent.Error, errorHandler);
3767
3864
  embed.executeCallbacks(EmbedEvent.Error, makeNestedValidationData());
3768
3865
  expect(errorHandler).not.toHaveBeenCalled();
@@ -3787,14 +3884,20 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3787
3884
  });
3788
3885
  test('delivers Error event to EmbedEvent.ALL handler when not skipped', () => {
3789
3886
  const allHandler = jest.fn();
3790
- const embed = makeEmbed({ useHostEventsV2: true, shouldBypassPayloadValidation: false });
3887
+ const embed = makeEmbed({
3888
+ useHostEventsV2: true,
3889
+ shouldBypassPayloadValidation: false,
3890
+ });
3791
3891
  embed.on(EmbedEvent.ALL, allHandler);
3792
3892
  embed.executeCallbacks(EmbedEvent.Error, makeNestedValidationData());
3793
3893
  expect(allHandler).toHaveBeenCalled();
3794
3894
  });
3795
3895
  test('does not skip non-Error events even with HOST_EVENT_VALIDATION error code', () => {
3796
3896
  const customActionHandler = jest.fn();
3797
- const embed = makeEmbed({ useHostEventsV2: true, shouldBypassPayloadValidation: false });
3897
+ const embed = makeEmbed({
3898
+ useHostEventsV2: true,
3899
+ shouldBypassPayloadValidation: false,
3900
+ });
3798
3901
  embed.on(EmbedEvent.CustomAction, customActionHandler);
3799
3902
  embed.executeCallbacks(EmbedEvent.CustomAction, {
3800
3903
  data: { code: EmbedErrorCodes.HOST_EVENT_VALIDATION },
@@ -3803,7 +3906,10 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3803
3906
  });
3804
3907
  test('does not skip Error events with unrelated error codes', () => {
3805
3908
  const errorHandler = jest.fn();
3806
- const embed = makeEmbed({ useHostEventsV2: true, shouldBypassPayloadValidation: false });
3909
+ const embed = makeEmbed({
3910
+ useHostEventsV2: true,
3911
+ shouldBypassPayloadValidation: false,
3912
+ });
3807
3913
  embed.on(EmbedEvent.Error, errorHandler);
3808
3914
  embed.executeCallbacks(EmbedEvent.Error, {
3809
3915
  errorType: 'SOME_OTHER_ERROR',
@@ -3812,5 +3918,145 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
3812
3918
  expect(errorHandler).toHaveBeenCalled();
3813
3919
  });
3814
3920
  });
3921
+ describe('constructor init-path branching (SCAL-315058)', () => {
3922
+ beforeEach(() => {
3923
+ init({
3924
+ thoughtSpotHost: 'tshost',
3925
+ authType: AuthType.None,
3926
+ });
3927
+ });
3928
+ it('sets hostElement from domSelector', () => {
3929
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3930
+ expect(embed.hostElement).toBe(getRootEl());
3931
+ });
3932
+ it('skips isReadyForRenderPromise when init already completed', () => {
3933
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(true);
3934
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3935
+ expect(embed.shouldWaitForRenderPromise).toBe(false);
3936
+ expect(embed.isReadyForRenderPromise).toBeUndefined();
3937
+ });
3938
+ it('sets isReadyForRenderPromise when init not yet completed', () => {
3939
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(false);
3940
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3941
+ expect(embed.shouldWaitForRenderPromise).toBe(true);
3942
+ expect(embed.isReadyForRenderPromise).toBeInstanceOf(Promise);
3943
+ });
3944
+ it('afterInit runs synchronously when init already completed', () => {
3945
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(true);
3946
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3947
+ // thoughtSpotHost is set by afterInit;
3948
+ // must be non-empty after constructor
3949
+ expect(embed.thoughtSpotHost).toBeTruthy();
3950
+ });
3951
+ it('does not set isReadyForRenderPromise when shouldWaitForRenderPromise is false', () => {
3952
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(true);
3953
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3954
+ expect(embed.shouldWaitForRenderPromise).toBe(false);
3955
+ // isReadyForRenderPromise must be undefined
3956
+ // so no unnecessary await occurs
3957
+ expect(embed.isReadyForRenderPromise).toBeUndefined();
3958
+ });
3959
+ it('shouldWaitForRenderPromise flips to false after promise settles', async () => {
3960
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(false);
3961
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3962
+ expect(embed.shouldWaitForRenderPromise).toBe(true);
3963
+ await embed.isReadyForRenderPromise;
3964
+ expect(embed.shouldWaitForRenderPromise).toBe(false);
3965
+ });
3966
+ it('calls throwInitError when getInitPromise rejects', async () => {
3967
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(false);
3968
+ jest.spyOn(baseInstance, 'getInitPromise').mockReturnValue(Promise.reject(new Error('init failed')));
3969
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3970
+ const throwInitErrorSpy = jest.spyOn(embed, 'throwInitError');
3971
+ await embed.isReadyForRenderPromise;
3972
+ expect(throwInitErrorSpy).toHaveBeenCalled();
3973
+ });
3974
+ it('shouldWaitForRenderPromise flips to false even when getInitPromise rejects', async () => {
3975
+ jest.spyOn(baseInstance, 'getIsInitCompleted').mockReturnValue(false);
3976
+ jest.spyOn(baseInstance, 'getInitPromise').mockReturnValue(Promise.reject(new Error('init failed')));
3977
+ const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
3978
+ await embed.isReadyForRenderPromise;
3979
+ expect(embed.shouldWaitForRenderPromise).toBe(false);
3980
+ });
3981
+ });
3982
+ describe('preRender ID object includes placeHolder (SCAL-315058)', () => {
3983
+ beforeAll(() => {
3984
+ init({
3985
+ thoughtSpotHost: 'tshost',
3986
+ authType: AuthType.None,
3987
+ });
3988
+ });
3989
+ it('getPreRenderIds returns placeHolder key', () => {
3990
+ createRootEleForEmbed();
3991
+ const embed = new LiveboardEmbed('#tsEmbedDiv', {
3992
+ preRenderId: 'ph-test',
3993
+ liveboardId: 'lb-id',
3994
+ });
3995
+ const ids = embed.getPreRenderIds();
3996
+ expect(ids.placeHolder).toBe('tsEmbed-pre-render-placeholder-ph-test');
3997
+ });
3998
+ });
3999
+ describe('isPreRenderConnected logic (SCAL-315058)', () => {
4000
+ beforeAll(() => {
4001
+ init({
4002
+ thoughtSpotHost: 'tshost',
4003
+ authType: AuthType.None,
4004
+ });
4005
+ });
4006
+ it('returns false when preRenderWrapper is absent', () => {
4007
+ createRootEleForEmbed();
4008
+ const embed = new LiveboardEmbed('#tsEmbedDiv', {
4009
+ preRenderId: 'conn-test',
4010
+ liveboardId: 'lb-id',
4011
+ });
4012
+ expect(embed.isPreRenderConnected()).toBe(false);
4013
+ });
4014
+ it('returns true once preRenderWrapper and preRenderChild are set', () => {
4015
+ createRootEleForEmbed();
4016
+ const embed = new LiveboardEmbed('#tsEmbedDiv', {
4017
+ preRenderId: 'conn-test-2',
4018
+ liveboardId: 'lb-id',
4019
+ });
4020
+ embed.preRenderWrapper = document.createElement('div');
4021
+ embed.preRenderChild = document.createElement('div');
4022
+ expect(embed.isPreRenderConnected()).toBe(true);
4023
+ });
4024
+ });
4025
+ describe('showPreRender inserts placeholder into hostElement (SCAL-315058)', () => {
4026
+ beforeAll(() => {
4027
+ // Clear spy implementations that may have leaked from prior
4028
+ // describe blocks (e.g. getIsInitCompleted/getInitPromise mocks set
4029
+ // in 'constructor init-path branching' persist across describes
4030
+ // because clearAllMocks only clears call history, not
4031
+ // implementations).
4032
+ jest.restoreAllMocks();
4033
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(undefined);
4034
+ init({
4035
+ thoughtSpotHost: 'tshost',
4036
+ authType: AuthType.None,
4037
+ });
4038
+ window.ResizeObserver = jest.fn().mockImplementation(() => ({
4039
+ disconnect: jest.fn(),
4040
+ observe: jest.fn(),
4041
+ unobserve: jest.fn(),
4042
+ }));
4043
+ });
4044
+ it('showPreRender creates a placeholder element with the correct id', async () => {
4045
+ createRootEleForEmbed();
4046
+ const embed = new LiveboardEmbed('#tsEmbedDiv', {
4047
+ preRenderId: 'ph-lifecycle-test',
4048
+ liveboardId: 'lb-id',
4049
+ });
4050
+ await embed.preRender();
4051
+ await waitFor(() => !!document.querySelector('#tsEmbed-pre-render-child-ph-lifecycle-test'));
4052
+ await embed.showPreRender();
4053
+ const placeholderEle = embed.getPreRenderPlaceHolderElement();
4054
+ expect(placeholderEle).not.toBeNull();
4055
+ expect(placeholderEle.id).toBe('tsEmbed-pre-render-placeholder-ph-lifecycle-test');
4056
+ // placeholder is attached to a parent element (inside hostElement)
4057
+ expect(placeholderEle.parentElement).not.toBeNull();
4058
+ embed.destroy();
4059
+ });
4060
+ });
3815
4061
  });
3816
4062
  //# sourceMappingURL=ts-embed.spec.js.map