@thoughtspot/visual-embed-sdk 1.52.1 → 1.52.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/cjs/package.json +10 -3
  2. package/cjs/src/contracts/host-event-contracts.d.ts +49 -11
  3. package/cjs/src/contracts/host-event-contracts.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +4 -3
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js.map +1 -1
  7. package/cjs/src/embed/app.spec.js +10 -0
  8. package/cjs/src/embed/app.spec.js.map +1 -1
  9. package/cjs/src/embed/auto-frame-renderer.spec.js +24 -13
  10. package/cjs/src/embed/auto-frame-renderer.spec.js.map +1 -1
  11. package/cjs/src/embed/conversation.d.ts +1 -0
  12. package/cjs/src/embed/conversation.d.ts.map +1 -1
  13. package/cjs/src/embed/conversation.js +3 -3
  14. package/cjs/src/embed/conversation.js.map +1 -1
  15. package/cjs/src/embed/conversation.spec.js +35 -24
  16. package/cjs/src/embed/conversation.spec.js.map +1 -1
  17. package/cjs/src/embed/embedConfig.spec.js +2 -1
  18. package/cjs/src/embed/embedConfig.spec.js.map +1 -1
  19. package/cjs/src/embed/hostEventClient/host-event-client.d.ts +2 -2
  20. package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  21. package/cjs/src/embed/hostEventClient/host-event-client.js +16 -10
  22. package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
  23. package/cjs/src/embed/hostEventClient/host-event-client.spec.js +14 -8
  24. package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  25. package/cjs/src/embed/hostEventClient/utils.d.ts +9 -0
  26. package/cjs/src/embed/hostEventClient/utils.d.ts.map +1 -1
  27. package/cjs/src/embed/hostEventClient/utils.js +49 -3
  28. package/cjs/src/embed/hostEventClient/utils.js.map +1 -1
  29. package/cjs/src/embed/hostEventClient/utils.spec.js +151 -0
  30. package/cjs/src/embed/hostEventClient/utils.spec.js.map +1 -1
  31. package/cjs/src/embed/liveboard.d.ts +4 -3
  32. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  33. package/cjs/src/embed/liveboard.js +17 -12
  34. package/cjs/src/embed/liveboard.js.map +1 -1
  35. package/cjs/src/embed/liveboard.spec.js +2 -1
  36. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  37. package/cjs/src/embed/spotter-utils.d.ts +8 -1
  38. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  39. package/cjs/src/embed/spotter-utils.js +14 -1
  40. package/cjs/src/embed/spotter-utils.js.map +1 -1
  41. package/cjs/src/embed/spotter-utils.spec.js +26 -0
  42. package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
  43. package/cjs/src/embed/ts-embed.d.ts +35 -10
  44. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  45. package/cjs/src/embed/ts-embed.js +108 -73
  46. package/cjs/src/embed/ts-embed.js.map +1 -1
  47. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  48. package/cjs/src/embed/ts-embed.spec.js +203 -30
  49. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  50. package/cjs/src/errors.js +1 -1
  51. package/cjs/src/errors.js.map +1 -1
  52. package/cjs/src/index.d.ts +2 -1
  53. package/cjs/src/index.d.ts.map +1 -1
  54. package/cjs/src/index.js +3 -1
  55. package/cjs/src/index.js.map +1 -1
  56. package/cjs/src/react/all-types-export.d.ts +1 -1
  57. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  58. package/cjs/src/react/all-types-export.js +2 -1
  59. package/cjs/src/react/all-types-export.js.map +1 -1
  60. package/cjs/src/types.d.ts +45 -22
  61. package/cjs/src/types.d.ts.map +1 -1
  62. package/cjs/src/types.js +44 -21
  63. package/cjs/src/types.js.map +1 -1
  64. package/cjs/src/utils/authService/tokenizedAuthService.spec.js +2 -1
  65. package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  66. package/cjs/src/utils/custom-actions.spec.js +4 -2
  67. package/cjs/src/utils/custom-actions.spec.js.map +1 -1
  68. package/cjs/src/utils/filterConverter.d.ts +106 -0
  69. package/cjs/src/utils/filterConverter.d.ts.map +1 -0
  70. package/cjs/src/utils/filterConverter.js +215 -0
  71. package/cjs/src/utils/filterConverter.js.map +1 -0
  72. package/cjs/src/utils/filterConverter.spec.d.ts +2 -0
  73. package/cjs/src/utils/filterConverter.spec.d.ts.map +1 -0
  74. package/cjs/src/utils/filterConverter.spec.js +709 -0
  75. package/cjs/src/utils/filterConverter.spec.js.map +1 -0
  76. package/cjs/src/utils/processData.spec.js +2 -1
  77. package/cjs/src/utils/processData.spec.js.map +1 -1
  78. package/dist/{index-C1pmYb5H.js → index-BrJMbt8r.js} +1 -1
  79. package/dist/src/contracts/host-event-contracts.d.ts +49 -11
  80. package/dist/src/contracts/host-event-contracts.d.ts.map +1 -1
  81. package/dist/src/embed/app.d.ts +4 -3
  82. package/dist/src/embed/app.d.ts.map +1 -1
  83. package/dist/src/embed/conversation.d.ts +1 -0
  84. package/dist/src/embed/conversation.d.ts.map +1 -1
  85. package/dist/src/embed/hostEventClient/host-event-client.d.ts +2 -2
  86. package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  87. package/dist/src/embed/hostEventClient/utils.d.ts +9 -0
  88. package/dist/src/embed/hostEventClient/utils.d.ts.map +1 -1
  89. package/dist/src/embed/liveboard.d.ts +4 -3
  90. package/dist/src/embed/liveboard.d.ts.map +1 -1
  91. package/dist/src/embed/spotter-utils.d.ts +8 -1
  92. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  93. package/dist/src/embed/ts-embed.d.ts +35 -10
  94. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  95. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  96. package/dist/src/index.d.ts +2 -1
  97. package/dist/src/index.d.ts.map +1 -1
  98. package/dist/src/react/all-types-export.d.ts +1 -1
  99. package/dist/src/react/all-types-export.d.ts.map +1 -1
  100. package/dist/src/types.d.ts +45 -22
  101. package/dist/src/types.d.ts.map +1 -1
  102. package/dist/src/utils/filterConverter.d.ts +106 -0
  103. package/dist/src/utils/filterConverter.d.ts.map +1 -0
  104. package/dist/src/utils/filterConverter.spec.d.ts +2 -0
  105. package/dist/src/utils/filterConverter.spec.d.ts.map +1 -0
  106. package/dist/tsembed-react.es.js +252 -126
  107. package/dist/tsembed-react.js +251 -125
  108. package/dist/tsembed.es.js +460 -127
  109. package/dist/tsembed.js +459 -125
  110. package/dist/visual-embed-sdk-react-full.d.ts +233 -49
  111. package/dist/visual-embed-sdk-react.d.ts +139 -49
  112. package/dist/visual-embed-sdk.d.ts +233 -49
  113. package/lib/package.json +10 -3
  114. package/lib/src/contracts/host-event-contracts.d.ts +49 -11
  115. package/lib/src/contracts/host-event-contracts.d.ts.map +1 -1
  116. package/lib/src/embed/app.d.ts +4 -3
  117. package/lib/src/embed/app.d.ts.map +1 -1
  118. package/lib/src/embed/app.js.map +1 -1
  119. package/lib/src/embed/app.spec.js +10 -0
  120. package/lib/src/embed/app.spec.js.map +1 -1
  121. package/lib/src/embed/auto-frame-renderer.spec.js +24 -13
  122. package/lib/src/embed/auto-frame-renderer.spec.js.map +1 -1
  123. package/lib/src/embed/conversation.d.ts +1 -0
  124. package/lib/src/embed/conversation.d.ts.map +1 -1
  125. package/lib/src/embed/conversation.js +4 -4
  126. package/lib/src/embed/conversation.js.map +1 -1
  127. package/lib/src/embed/conversation.spec.js +35 -24
  128. package/lib/src/embed/conversation.spec.js.map +1 -1
  129. package/lib/src/embed/embedConfig.spec.js +2 -1
  130. package/lib/src/embed/embedConfig.spec.js.map +1 -1
  131. package/lib/src/embed/hostEventClient/host-event-client.d.ts +2 -2
  132. package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  133. package/lib/src/embed/hostEventClient/host-event-client.js +17 -11
  134. package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
  135. package/lib/src/embed/hostEventClient/host-event-client.spec.js +14 -8
  136. package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  137. package/lib/src/embed/hostEventClient/utils.d.ts +9 -0
  138. package/lib/src/embed/hostEventClient/utils.d.ts.map +1 -1
  139. package/lib/src/embed/hostEventClient/utils.js +47 -2
  140. package/lib/src/embed/hostEventClient/utils.js.map +1 -1
  141. package/lib/src/embed/hostEventClient/utils.spec.js +152 -1
  142. package/lib/src/embed/hostEventClient/utils.spec.js.map +1 -1
  143. package/lib/src/embed/liveboard.d.ts +4 -3
  144. package/lib/src/embed/liveboard.d.ts.map +1 -1
  145. package/lib/src/embed/liveboard.js +17 -12
  146. package/lib/src/embed/liveboard.js.map +1 -1
  147. package/lib/src/embed/liveboard.spec.js +2 -1
  148. package/lib/src/embed/liveboard.spec.js.map +1 -1
  149. package/lib/src/embed/spotter-utils.d.ts +8 -1
  150. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  151. package/lib/src/embed/spotter-utils.js +12 -0
  152. package/lib/src/embed/spotter-utils.js.map +1 -1
  153. package/lib/src/embed/spotter-utils.spec.js +27 -1
  154. package/lib/src/embed/spotter-utils.spec.js.map +1 -1
  155. package/lib/src/embed/ts-embed.d.ts +35 -10
  156. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  157. package/lib/src/embed/ts-embed.js +109 -74
  158. package/lib/src/embed/ts-embed.js.map +1 -1
  159. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  160. package/lib/src/embed/ts-embed.spec.js +203 -30
  161. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  162. package/lib/src/errors.js +1 -1
  163. package/lib/src/errors.js.map +1 -1
  164. package/lib/src/index.d.ts +2 -1
  165. package/lib/src/index.d.ts.map +1 -1
  166. package/lib/src/index.js +2 -1
  167. package/lib/src/index.js.map +1 -1
  168. package/lib/src/react/all-types-export.d.ts +1 -1
  169. package/lib/src/react/all-types-export.d.ts.map +1 -1
  170. package/lib/src/react/all-types-export.js +1 -1
  171. package/lib/src/react/all-types-export.js.map +1 -1
  172. package/lib/src/types.d.ts +45 -22
  173. package/lib/src/types.d.ts.map +1 -1
  174. package/lib/src/types.js +44 -21
  175. package/lib/src/types.js.map +1 -1
  176. package/lib/src/utils/authService/tokenizedAuthService.spec.js +2 -1
  177. package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -1
  178. package/lib/src/utils/custom-actions.spec.js +4 -2
  179. package/lib/src/utils/custom-actions.spec.js.map +1 -1
  180. package/lib/src/utils/filterConverter.d.ts +106 -0
  181. package/lib/src/utils/filterConverter.d.ts.map +1 -0
  182. package/lib/src/utils/filterConverter.js +210 -0
  183. package/lib/src/utils/filterConverter.js.map +1 -0
  184. package/lib/src/utils/filterConverter.spec.d.ts +2 -0
  185. package/lib/src/utils/filterConverter.spec.d.ts.map +1 -0
  186. package/lib/src/utils/filterConverter.spec.js +707 -0
  187. package/lib/src/utils/filterConverter.spec.js.map +1 -0
  188. package/lib/src/utils/processData.spec.js +2 -1
  189. package/lib/src/utils/processData.spec.js.map +1 -1
  190. package/lib/src/visual-embed-sdk.d.ts +233 -49
  191. package/package.json +10 -3
  192. package/src/contracts/host-event-contracts.ts +55 -11
  193. package/src/embed/app.spec.ts +15 -0
  194. package/src/embed/app.ts +4 -3
  195. package/src/embed/auto-frame-renderer.spec.ts +24 -13
  196. package/src/embed/conversation.spec.ts +38 -27
  197. package/src/embed/conversation.ts +4 -4
  198. package/src/embed/embedConfig.spec.ts +2 -1
  199. package/src/embed/hostEventClient/host-event-client.spec.ts +14 -8
  200. package/src/embed/hostEventClient/host-event-client.ts +18 -10
  201. package/src/embed/hostEventClient/utils.spec.ts +176 -1
  202. package/src/embed/hostEventClient/utils.ts +51 -2
  203. package/src/embed/liveboard.spec.ts +4 -3
  204. package/src/embed/liveboard.ts +21 -15
  205. package/src/embed/spotter-utils.spec.ts +29 -0
  206. package/src/embed/spotter-utils.ts +16 -0
  207. package/src/embed/ts-embed.spec.ts +245 -30
  208. package/src/embed/ts-embed.ts +107 -74
  209. package/src/errors.ts +1 -1
  210. package/src/index.ts +10 -0
  211. package/src/react/all-types-export.ts +4 -0
  212. package/src/types.ts +44 -21
  213. package/src/utils/authService/tokenizedAuthService.spec.ts +2 -1
  214. package/src/utils/custom-actions.spec.ts +4 -2
  215. package/src/utils/filterConverter.spec.ts +801 -0
  216. package/src/utils/filterConverter.ts +304 -0
  217. package/src/utils/processData.spec.ts +2 -1
@@ -71,6 +71,10 @@ import * as processData from '../utils/processData';
71
71
  jest.mock('../utils/processTrigger');
72
72
 
73
73
  const mockProcessTrigger = processTrigger as jest.Mock;
74
+
75
+ const flushAnimationFrame = () => new Promise<void>((resolve) => {
76
+ requestAnimationFrame(() => resolve());
77
+ });
74
78
  const mockHandleInterceptEvent = jest.spyOn(apiIntercept, 'handleInterceptEvent');
75
79
  const defaultViewConfig = {
76
80
  frameParams: {
@@ -2620,12 +2624,14 @@ describe('Unit test case for ts embed', () => {
2620
2624
  contentRect: { height: 297, width: 987 },
2621
2625
  },
2622
2626
  ]);
2627
+ // Syncs are coalesced to one per frame.
2628
+ await flushAnimationFrame();
2623
2629
 
2624
2630
  expect(preRenderWrapper.style.height).toEqual(`${297}px`);
2625
2631
  expect(preRenderWrapper.style.width).toEqual(`${987}px`);
2626
2632
 
2627
2633
  expect(preRenderWrapper.style.opacity).toBe('');
2628
- expect(preRenderWrapper.style.pointerEvents).toBe('');
2634
+ expect(preRenderWrapper.style.pointerEvents).toBe('auto');
2629
2635
  expect(preRenderWrapper.style.zIndex).toBe('');
2630
2636
 
2631
2637
  libEmbed.hidePreRender();
@@ -2662,7 +2668,7 @@ describe('Unit test case for ts embed', () => {
2662
2668
  const preRenderWrapper = document.getElementById(preRenderIds.wrapper);
2663
2669
 
2664
2670
  expect(preRenderWrapper.style.opacity).toBe('');
2665
- expect(preRenderWrapper.style.pointerEvents).toBe('');
2671
+ expect(preRenderWrapper.style.pointerEvents).toBe('auto');
2666
2672
  expect(preRenderWrapper.style.zIndex).toBe('');
2667
2673
  });
2668
2674
 
@@ -2835,6 +2841,211 @@ describe('Unit test case for ts embed', () => {
2835
2841
  (logger.debug as any).mockRestore();
2836
2842
  });
2837
2843
 
2844
+ describe('position tracking (SCAL-338563)', () => {
2845
+ /**
2846
+ * A host app whose page scrolls in an inner element rather than the
2847
+ * document — the shape both reported cases have. The placeholder's
2848
+ * rect is driven off that element's scrollTop, the way a real
2849
+ * layout would move it.
2850
+ */
2851
+ const mountInNestedScroller = () => {
2852
+ createRootEleForEmbed();
2853
+ const scroller = document.createElement('div');
2854
+ scroller.id = 'inner-scroller';
2855
+ document.body.appendChild(scroller);
2856
+ scroller.appendChild(document.getElementById('tsEmbedDiv'));
2857
+
2858
+ let scrollTop = 0;
2859
+ Object.defineProperty(scroller, 'scrollTop', {
2860
+ configurable: true,
2861
+ get: () => scrollTop,
2862
+ set: (value) => {
2863
+ scrollTop = value;
2864
+ },
2865
+ });
2866
+ scroller.getBoundingClientRect = () =>
2867
+ ({
2868
+ x: 0, y: 0, width: 800, height: 600,
2869
+ top: 0, left: 0, bottom: 600, right: 800,
2870
+ } as DOMRect);
2871
+
2872
+ const placeholderTopAtRest = 400;
2873
+ const readPlaceholderTop = () => placeholderTopAtRest - scroller.scrollTop;
2874
+
2875
+ return { scroller, readPlaceholderTop };
2876
+ };
2877
+
2878
+ const stubPlaceholderRect = (embed: any, readTop: () => number) => {
2879
+ const placeholder = embed.getPreRenderPlaceHolderElement() as HTMLElement;
2880
+ placeholder.getBoundingClientRect = () => {
2881
+ const top = readTop();
2882
+ return {
2883
+ x: 0, y: top, width: 800, height: 300,
2884
+ top, left: 0, bottom: top + 300, right: 800,
2885
+ } as DOMRect;
2886
+ };
2887
+ return placeholder;
2888
+ };
2889
+
2890
+ it('should stop tracking once the frame is hidden', async () => {
2891
+ const { scroller, readPlaceholderTop } = mountInNestedScroller();
2892
+
2893
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2894
+ preRenderId: 'scroll-stops-on-hide',
2895
+ liveboardId: 'myLiveboardId',
2896
+ });
2897
+ libEmbed.preRender();
2898
+ await waitFor(() => !!getIFrameEl());
2899
+ await libEmbed.showPreRender();
2900
+
2901
+ stubPlaceholderRect(libEmbed, readPlaceholderTop);
2902
+ libEmbed.hidePreRender();
2903
+
2904
+ const syncSpy = jest.spyOn(libEmbed, 'syncPreRenderStyle');
2905
+ scroller.scrollTop = 250;
2906
+ scroller.dispatchEvent(new Event('scroll'));
2907
+ await flushAnimationFrame();
2908
+
2909
+ expect(syncSpy).not.toHaveBeenCalled();
2910
+
2911
+ syncSpy.mockRestore();
2912
+ libEmbed.destroy();
2913
+ scroller.remove();
2914
+ });
2915
+
2916
+ it('should default the container to the host scrolling ancestor', async () => {
2917
+ const { scroller } = mountInNestedScroller();
2918
+ scroller.style.overflowY = 'auto';
2919
+
2920
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2921
+ preRenderId: 'auto-scroll-container',
2922
+ liveboardId: 'myLiveboardId',
2923
+ });
2924
+ libEmbed.preRender();
2925
+ await waitFor(() => !!getIFrameEl());
2926
+ await libEmbed.showPreRender();
2927
+
2928
+ const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2929
+ // In the scroller, so the browser moves it — no repositioning.
2930
+ expect(wrapper.parentElement).toBe(scroller);
2931
+ expect((libEmbed as any).preRenderContainerEl).toBe(scroller);
2932
+
2933
+ libEmbed.destroy();
2934
+ scroller.remove();
2935
+ });
2936
+
2937
+ it('should still use document.body when nothing scrolls', async () => {
2938
+ createRootEleForEmbed();
2939
+
2940
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2941
+ preRenderId: 'no-scroller-body',
2942
+ liveboardId: 'myLiveboardId',
2943
+ });
2944
+ libEmbed.preRender();
2945
+ await waitFor(() => !!getIFrameEl());
2946
+ await libEmbed.showPreRender();
2947
+
2948
+ const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2949
+ expect(wrapper.parentElement).toBe(document.body);
2950
+
2951
+ libEmbed.destroy();
2952
+ });
2953
+
2954
+ it('should set pointer-events on show rather than dropping the property', async () => {
2955
+ createRootEleForEmbed();
2956
+ const container = document.createElement('div');
2957
+ container.id = 'parking-root';
2958
+ // Usual styling for a parking root: no swallowed clicks.
2959
+ container.style.pointerEvents = 'none';
2960
+ document.body.appendChild(container);
2961
+
2962
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2963
+ preRenderId: 'pointer-events-restored',
2964
+ liveboardId: 'myLiveboardId',
2965
+ preRenderContainer: '#parking-root',
2966
+ });
2967
+ libEmbed.preRender();
2968
+ await waitFor(() => !!getIFrameEl());
2969
+ await libEmbed.showPreRender();
2970
+
2971
+ const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2972
+ // Merely removing the property would leave the container's
2973
+ // inherited `none` in force, and the frame dead to input.
2974
+ expect(wrapper.style.pointerEvents).toBe('auto');
2975
+
2976
+ libEmbed.destroy();
2977
+ container.remove();
2978
+ });
2979
+
2980
+ it('should park a hidden wrapper out of the scrollable area', async () => {
2981
+ createRootEleForEmbed();
2982
+
2983
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
2984
+ preRenderId: 'hidden-parked',
2985
+ liveboardId: 'myLiveboardId',
2986
+ });
2987
+ libEmbed.preRender();
2988
+ await waitFor(() => !!getIFrameEl());
2989
+ await libEmbed.showPreRender();
2990
+
2991
+ const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2992
+ expect(wrapper.style.transform).toBe('');
2993
+
2994
+ libEmbed.hidePreRender();
2995
+ expect(wrapper.style.transform).toBe('translateY(-100%)');
2996
+
2997
+ await libEmbed.showPreRender();
2998
+ expect(wrapper.style.transform).toBe('');
2999
+
3000
+ libEmbed.destroy();
3001
+ });
3002
+
3003
+ it('should not seed the placeholder with the unmeasured wrapper height', async () => {
3004
+ createRootEleForEmbed();
3005
+
3006
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
3007
+ preRenderId: 'unmeasured-height',
3008
+ liveboardId: 'myLiveboardId',
3009
+ fullHeight: true,
3010
+ frameParams: { height: 420 },
3011
+ });
3012
+ libEmbed.preRender();
3013
+ await waitFor(() => !!getIFrameEl());
3014
+
3015
+ const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
3016
+ // createPreRenderWrapper() seeds 100vh, not a measurement.
3017
+ expect(wrapper.style.height).toBe('100vh');
3018
+
3019
+ await libEmbed.showPreRender();
3020
+
3021
+ const placeholder = (libEmbed as any).getPreRenderPlaceHolderElement() as HTMLElement;
3022
+ expect(placeholder.style.height).toBe('420px');
3023
+
3024
+ libEmbed.destroy();
3025
+ });
3026
+
3027
+ it('should seed the placeholder with a height fullHeight has measured', async () => {
3028
+ createRootEleForEmbed();
3029
+
3030
+ const libEmbed = new LiveboardEmbed('#tsEmbedDiv', {
3031
+ preRenderId: 'measured-height',
3032
+ liveboardId: 'myLiveboardId',
3033
+ fullHeight: true,
3034
+ frameParams: { height: 420 },
3035
+ });
3036
+ libEmbed.preRender();
3037
+ await waitFor(() => !!getIFrameEl());
3038
+
3039
+ (libEmbed as any).setIFrameHeight(1180);
3040
+ await libEmbed.showPreRender();
3041
+
3042
+ const placeholder = (libEmbed as any).getPreRenderPlaceHolderElement() as HTMLElement;
3043
+ expect(placeholder.style.height).toBe('1180px');
3044
+
3045
+ libEmbed.destroy();
3046
+ });
3047
+ });
3048
+
2838
3049
  describe('preRenderContainer', () => {
2839
3050
  it('should append preRenderWrapper to document.body when preRenderContainer is not set', async () => {
2840
3051
  createRootEleForEmbed();
@@ -2964,8 +3175,8 @@ describe('Unit test case for ts embed', () => {
2964
3175
 
2965
3176
  // Reverts to the exact value the container had before.
2966
3177
  expect(customContainer.style.position).toBe('static');
2967
- // The custom container reference is dropped (back to the default
2968
- // body) so a destroyed embed does not pin the (possibly
3178
+ // The custom container reference is dropped (back to the
3179
+ // default body) so a destroyed embed does not pin the (possibly
2969
3180
  // detached) element in memory.
2970
3181
  expect((libEmbed as any).preRenderContainerEl).toBe(document.body);
2971
3182
 
@@ -3019,8 +3230,8 @@ describe('Unit test case for ts embed', () => {
3019
3230
 
3020
3231
  libEmbed.destroy();
3021
3232
 
3022
- // The body sentinel must never be treated as a custom container:
3023
- // no position override to apply and none to restore.
3233
+ // The body sentinel must never be treated as a custom
3234
+ // container: no position override to apply and none to restore.
3024
3235
  expect(document.body.style.position).toBe(originalBodyPosition);
3025
3236
  expect(document.body.dataset.tsEmbedOriginalPosition).toBeUndefined();
3026
3237
  });
@@ -3108,21 +3319,16 @@ describe('Unit test case for ts embed', () => {
3108
3319
 
3109
3320
  // Simulate React remounting the container: the old node (with
3110
3321
  // our wrapper) is detached and a fresh node takes its place.
3111
- const removeSpy = jest.spyOn(oldContainer, 'removeEventListener');
3112
3322
  oldContainer.remove();
3113
3323
  const newContainer = document.createElement('div');
3114
3324
  newContainer.id = 'remount-container';
3115
3325
  document.body.appendChild(newContainer);
3116
- const addSpy = jest.spyOn(newContainer, 'addEventListener');
3117
3326
 
3118
3327
  // A reposition (scroll/resize/re-show) heals the stale ref.
3119
3328
  libEmbed.syncPreRenderStyle();
3120
3329
 
3121
3330
  expect(newContainer.contains(wrapper)).toBe(true);
3122
3331
  expect(oldContainer.contains(wrapper)).toBe(false);
3123
- // The scroll listener is migrated to the live container.
3124
- expect(removeSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
3125
- expect(addSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
3126
3332
 
3127
3333
  libEmbed.destroy();
3128
3334
  newContainer.remove();
@@ -3155,10 +3361,11 @@ describe('Unit test case for ts embed', () => {
3155
3361
 
3156
3362
  libEmbed.syncPreRenderStyle();
3157
3363
 
3158
- // applyPreRenderContainerPositioning() reads preRenderContainerEl
3159
- // instead of taking the container as an argument, so reconcile has
3160
- // to assign the field before calling it — otherwise the override
3161
- // lands on the detached node and the fresh one stays static.
3364
+ // applyPreRenderContainerPositioning() reads
3365
+ // preRenderContainerEl instead of taking the container as an
3366
+ // argument, so reconcile has to assign the field before calling
3367
+ // it — otherwise the override lands on the detached node and
3368
+ // the fresh one stays static.
3162
3369
  expect((libEmbed as any).preRenderContainerEl).toBe(newContainer);
3163
3370
  expect(newContainer.style.position).toBe('relative');
3164
3371
  expect(newContainer.dataset.tsEmbedOriginalPosition).toBe('static');
@@ -3289,7 +3496,8 @@ describe('Unit test case for ts embed', () => {
3289
3496
  await firstEmbed.preRender();
3290
3497
  await waitFor(() => !!getIFrameEl());
3291
3498
 
3292
- // Reset position to static so the connecting embed also triggers the guard.
3499
+ // Reset position to static so the connecting embed also
3500
+ // triggers the guard.
3293
3501
  customContainer.style.position = 'static';
3294
3502
  delete customContainer.dataset['preRenderContainerOriginalPosition'];
3295
3503
 
@@ -3393,8 +3601,8 @@ describe('Unit test case for ts embed', () => {
3393
3601
  await firstEmbed.preRender();
3394
3602
  await waitFor(() => !!getIFrameEl());
3395
3603
 
3396
- // Same config on both components — the value is redundant but
3397
- // not wrong, so nagging about it would be noise.
3604
+ // Same config on both components — the value is redundant
3605
+ // but not wrong, so nagging about it would be noise.
3398
3606
  const connectingEmbed = new LiveboardEmbed('#tsEmbedDiv', {
3399
3607
  preRenderId: 'connect-same-element',
3400
3608
  liveboardId: 'myLiveboardId',
@@ -3427,8 +3635,9 @@ describe('Unit test case for ts embed', () => {
3427
3635
  await firstEmbed.preRender();
3428
3636
  await waitFor(() => !!getIFrameEl());
3429
3637
 
3430
- // A selector that resolves to the owner's element is the same
3431
- // container, so the comparison must be by resolved node.
3638
+ // A selector that resolves to the owner's element is the
3639
+ // same container, so the comparison must be by resolved
3640
+ // node.
3432
3641
  const connectingEmbed = new LiveboardEmbed('#tsEmbedDiv', {
3433
3642
  preRenderId: 'connect-same-selector',
3434
3643
  liveboardId: 'myLiveboardId',
@@ -3492,8 +3701,8 @@ describe('Unit test case for ts embed', () => {
3492
3701
  await waitFor(() => !!getIFrameEl());
3493
3702
 
3494
3703
  // Simulate a wrapper with no live embed behind it: the
3495
- // __tsEmbed stamp used to locate the owner is gone, so there
3496
- // is no container to inherit.
3704
+ // __tsEmbed stamp used to locate the owner is gone, so
3705
+ // there is no container to inherit.
3497
3706
  const wrapper = document.getElementById(
3498
3707
  firstEmbed.getPreRenderIds().wrapper,
3499
3708
  );
@@ -5361,12 +5570,14 @@ describe('Trigger method edge cases', () => {
5361
5570
  const handleErrorSpy = jest.spyOn(searchEmbed as any, 'handleError').mockImplementation(() => {});
5362
5571
  await searchEmbed.render();
5363
5572
 
5364
- // First processTrigger call is getAvailableUIPassthroughKeys for DrillDown
5573
+ // First processTrigger call is getAvailableUIPassthroughKeys for
5574
+ // DrillDown
5365
5575
  mockProcessTrigger.mockResolvedValueOnce([
5366
5576
  { value: { keys: Object.values(UIPassthroughEvent) } },
5367
5577
  ]);
5368
5578
 
5369
- // DrillDown with no points → throwDrillDownValidationError → isValidationError=true
5579
+ // DrillDown with no points → throwDrillDownValidationError →
5580
+ // isValidationError=true
5370
5581
  await expect(
5371
5582
  searchEmbed.trigger(HostEvent.DrillDown, {} as any),
5372
5583
  ).rejects.toThrow('DrillDown requires a valid points object');
@@ -5541,7 +5752,8 @@ describe('Fullscreen change handler behavior', () => {
5541
5752
  init({
5542
5753
  thoughtSpotHost: 'tshost',
5543
5754
  authType: AuthType.None,
5544
- // disableFullscreenPresentation not set → defaults to true via ?? true
5755
+ // disableFullscreenPresentation not set → defaults to true via ??
5756
+ // true
5545
5757
  });
5546
5758
 
5547
5759
  const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
@@ -5567,7 +5779,8 @@ describe('Fullscreen change handler behavior', () => {
5567
5779
 
5568
5780
  embed['setupFullscreenChangeHandler']();
5569
5781
 
5570
- // Capture the registered handler directly instead of dispatching to document
5782
+ // Capture the registered handler directly instead of dispatching to
5783
+ // document
5571
5784
  const fullscreenCall = addEventListenerSpy.mock.calls.find((c) => c[0] === 'fullscreenchange');
5572
5785
  expect(fullscreenCall).toBeTruthy();
5573
5786
  const handler = fullscreenCall[1] as EventListener;
@@ -6039,8 +6252,8 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
6039
6252
  undefined,
6040
6253
  );
6041
6254
 
6042
- // A parameter always carries a value, so the payload says everything
6043
- // there is to say — no follow-up event.
6255
+ // A parameter always carries a value, so the payload says
6256
+ // everything there is to say — no follow-up event.
6044
6257
  const parameterCalls = mockProcessTrigger.mock.calls.filter(
6045
6258
  (call: any[]) => call[1] === HostEvent.UpdateParameters,
6046
6259
  );
@@ -6641,7 +6854,8 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
6641
6854
  expect(hostElement.querySelector(`#${placeHolderId}`)).toBe(staleNestedPlaceholder);
6642
6855
  // Before the fix this threw NotFoundError.
6643
6856
  await expect(embed.showPreRender()).resolves.toBeDefined();
6644
- // The stale nested placeholder is gone; the fresh one is a direct child.
6857
+ // The stale nested placeholder is gone; the fresh one is a direct
6858
+ // child.
6645
6859
  expect(staleNestedPlaceholder.isConnected).toBe(false);
6646
6860
  const currentPlaceholder = (
6647
6861
  embed as any
@@ -6673,7 +6887,8 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
6673
6887
  { numberOfTabs: number; orderedTabIds: string[] }
6674
6888
  > = true;
6675
6889
  const probeUnknownField = (r: TabsResponse) =>
6676
- // @ts-expect-error — field not on the GetTabs contract (was silent when `any`)
6890
+ // @ts-expect-error — field not on the GetTabs contract (was
6891
+ // silent when `any`)
6677
6892
  r.tabCount;
6678
6893
  void probeUnknownField;
6679
6894