@thoughtspot/visual-embed-sdk 1.39.1 → 1.39.2-alpha.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 (190) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/config.spec.js +9 -0
  3. package/cjs/src/config.spec.js.map +1 -1
  4. package/cjs/src/embed/app.d.ts +75 -15
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +69 -9
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +374 -12
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
  11. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.js +24 -4
  13. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  14. package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
  15. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/conversation.spec.js +28 -0
  17. package/cjs/src/embed/conversation.spec.js.map +1 -1
  18. package/cjs/src/embed/embedConfig.d.ts +9 -7
  19. package/cjs/src/embed/embedConfig.d.ts.map +1 -1
  20. package/cjs/src/embed/embedConfig.js +9 -7
  21. package/cjs/src/embed/embedConfig.js.map +1 -1
  22. package/cjs/src/embed/liveboard.d.ts +56 -17
  23. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  24. package/cjs/src/embed/liveboard.js +48 -4
  25. package/cjs/src/embed/liveboard.js.map +1 -1
  26. package/cjs/src/embed/liveboard.spec.js +215 -11
  27. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.d.ts +5 -0
  29. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  30. package/cjs/src/embed/ts-embed.js +16 -1
  31. package/cjs/src/embed/ts-embed.js.map +1 -1
  32. package/cjs/src/embed/ts-embed.spec.js +164 -0
  33. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  34. package/cjs/src/errors.d.ts +1 -0
  35. package/cjs/src/errors.d.ts.map +1 -1
  36. package/cjs/src/errors.js +1 -0
  37. package/cjs/src/errors.js.map +1 -1
  38. package/cjs/src/index.d.ts +2 -2
  39. package/cjs/src/index.d.ts.map +1 -1
  40. package/cjs/src/index.js +2 -1
  41. package/cjs/src/index.js.map +1 -1
  42. package/cjs/src/react/all-types-export.d.ts +1 -1
  43. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  44. package/cjs/src/react/all-types-export.js +3 -2
  45. package/cjs/src/react/all-types-export.js.map +1 -1
  46. package/cjs/src/react/index.d.ts +71 -20
  47. package/cjs/src/react/index.d.ts.map +1 -1
  48. package/cjs/src/react/index.js +79 -42
  49. package/cjs/src/react/index.js.map +1 -1
  50. package/cjs/src/react/index.spec.js +436 -100
  51. package/cjs/src/react/index.spec.js.map +1 -1
  52. package/cjs/src/types.d.ts +80 -6
  53. package/cjs/src/types.d.ts.map +1 -1
  54. package/cjs/src/types.js +45 -1
  55. package/cjs/src/types.js.map +1 -1
  56. package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  57. package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
  58. package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  59. package/cjs/src/utils/processTrigger.js +2 -1
  60. package/cjs/src/utils/processTrigger.js.map +1 -1
  61. package/cjs/src/utils.d.ts +6 -0
  62. package/cjs/src/utils.d.ts.map +1 -1
  63. package/cjs/src/utils.js +23 -3
  64. package/cjs/src/utils.js.map +1 -1
  65. package/cjs/src/utils.spec.js +237 -1
  66. package/cjs/src/utils.spec.js.map +1 -1
  67. package/dist/{index-JaFaxrvQ.js → index-CmEQfuE3.js} +1 -1
  68. package/dist/index-DeFzsyFF.js +7371 -0
  69. package/dist/index-Dpf0rd6w.js +7371 -0
  70. package/dist/index-UuEbsISo.js +7447 -0
  71. package/dist/index-e3Uw3YFO.js +7371 -0
  72. package/dist/src/embed/app.d.ts +75 -15
  73. package/dist/src/embed/app.d.ts.map +1 -1
  74. package/dist/src/embed/bodyless-conversation.d.ts +19 -7
  75. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  76. package/dist/src/embed/embedConfig.d.ts +9 -7
  77. package/dist/src/embed/embedConfig.d.ts.map +1 -1
  78. package/dist/src/embed/liveboard.d.ts +56 -17
  79. package/dist/src/embed/liveboard.d.ts.map +1 -1
  80. package/dist/src/embed/ts-embed.d.ts +5 -0
  81. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  82. package/dist/src/errors.d.ts +1 -0
  83. package/dist/src/errors.d.ts.map +1 -1
  84. package/dist/src/index.d.ts +2 -2
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/react/all-types-export.d.ts +1 -1
  87. package/dist/src/react/all-types-export.d.ts.map +1 -1
  88. package/dist/src/react/index.d.ts +71 -20
  89. package/dist/src/react/index.d.ts.map +1 -1
  90. package/dist/src/types.d.ts +80 -6
  91. package/dist/src/types.d.ts.map +1 -1
  92. package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  93. package/dist/src/utils.d.ts +6 -0
  94. package/dist/src/utils.d.ts.map +1 -1
  95. package/dist/tsembed-react.es.js +320 -78
  96. package/dist/tsembed-react.js +320 -76
  97. package/dist/tsembed.es.js +238 -31
  98. package/dist/tsembed.js +236 -29
  99. package/dist/visual-embed-sdk-react-full.d.ts +288 -72
  100. package/dist/visual-embed-sdk-react.d.ts +288 -72
  101. package/dist/visual-embed-sdk.d.ts +218 -53
  102. package/lib/package.json +1 -1
  103. package/lib/src/config.spec.js +9 -0
  104. package/lib/src/config.spec.js.map +1 -1
  105. package/lib/src/embed/app.d.ts +75 -15
  106. package/lib/src/embed/app.d.ts.map +1 -1
  107. package/lib/src/embed/app.js +69 -9
  108. package/lib/src/embed/app.js.map +1 -1
  109. package/lib/src/embed/app.spec.js +376 -14
  110. package/lib/src/embed/app.spec.js.map +1 -1
  111. package/lib/src/embed/bodyless-conversation.d.ts +19 -7
  112. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  113. package/lib/src/embed/bodyless-conversation.js +23 -4
  114. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  115. package/lib/src/embed/bodyless-conversation.spec.js +9 -191
  116. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  117. package/lib/src/embed/conversation.spec.js +30 -2
  118. package/lib/src/embed/conversation.spec.js.map +1 -1
  119. package/lib/src/embed/embedConfig.d.ts +9 -7
  120. package/lib/src/embed/embedConfig.d.ts.map +1 -1
  121. package/lib/src/embed/embedConfig.js +9 -7
  122. package/lib/src/embed/embedConfig.js.map +1 -1
  123. package/lib/src/embed/liveboard.d.ts +56 -17
  124. package/lib/src/embed/liveboard.d.ts.map +1 -1
  125. package/lib/src/embed/liveboard.js +49 -5
  126. package/lib/src/embed/liveboard.js.map +1 -1
  127. package/lib/src/embed/liveboard.spec.js +215 -11
  128. package/lib/src/embed/liveboard.spec.js.map +1 -1
  129. package/lib/src/embed/ts-embed.d.ts +5 -0
  130. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  131. package/lib/src/embed/ts-embed.js +16 -1
  132. package/lib/src/embed/ts-embed.js.map +1 -1
  133. package/lib/src/embed/ts-embed.spec.js +164 -0
  134. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  135. package/lib/src/errors.d.ts +1 -0
  136. package/lib/src/errors.d.ts.map +1 -1
  137. package/lib/src/errors.js +1 -0
  138. package/lib/src/errors.js.map +1 -1
  139. package/lib/src/index.d.ts +2 -2
  140. package/lib/src/index.d.ts.map +1 -1
  141. package/lib/src/index.js +2 -2
  142. package/lib/src/index.js.map +1 -1
  143. package/lib/src/react/all-types-export.d.ts +1 -1
  144. package/lib/src/react/all-types-export.d.ts.map +1 -1
  145. package/lib/src/react/all-types-export.js +1 -1
  146. package/lib/src/react/all-types-export.js.map +1 -1
  147. package/lib/src/react/index.d.ts +71 -20
  148. package/lib/src/react/index.d.ts.map +1 -1
  149. package/lib/src/react/index.js +79 -43
  150. package/lib/src/react/index.js.map +1 -1
  151. package/lib/src/react/index.spec.js +439 -103
  152. package/lib/src/react/index.spec.js.map +1 -1
  153. package/lib/src/types.d.ts +80 -6
  154. package/lib/src/types.d.ts.map +1 -1
  155. package/lib/src/types.js +45 -1
  156. package/lib/src/types.js.map +1 -1
  157. package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  158. package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
  159. package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  160. package/lib/src/utils/processTrigger.js +2 -1
  161. package/lib/src/utils/processTrigger.js.map +1 -1
  162. package/lib/src/utils.d.ts +6 -0
  163. package/lib/src/utils.d.ts.map +1 -1
  164. package/lib/src/utils.js +21 -2
  165. package/lib/src/utils.js.map +1 -1
  166. package/lib/src/utils.spec.js +238 -2
  167. package/lib/src/utils.spec.js.map +1 -1
  168. package/lib/src/visual-embed-sdk.d.ts +219 -54
  169. package/package.json +1 -1
  170. package/src/config.spec.ts +11 -0
  171. package/src/embed/app.spec.ts +479 -26
  172. package/src/embed/app.ts +133 -27
  173. package/src/embed/bodyless-conversation.spec.ts +9 -203
  174. package/src/embed/bodyless-conversation.ts +24 -10
  175. package/src/embed/conversation.spec.ts +40 -2
  176. package/src/embed/embedConfig.ts +10 -8
  177. package/src/embed/liveboard.spec.ts +256 -5
  178. package/src/embed/liveboard.ts +99 -27
  179. package/src/embed/ts-embed.spec.ts +225 -0
  180. package/src/embed/ts-embed.ts +19 -0
  181. package/src/errors.ts +1 -0
  182. package/src/index.ts +2 -0
  183. package/src/react/all-types-export.ts +2 -1
  184. package/src/react/index.spec.tsx +556 -157
  185. package/src/react/index.tsx +117 -51
  186. package/src/types.ts +117 -43
  187. package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
  188. package/src/utils/processTrigger.ts +1 -1
  189. package/src/utils.spec.ts +279 -2
  190. package/src/utils.ts +28 -2
@@ -6,11 +6,10 @@ import {
6
6
  HomePageSearchBarMode,
7
7
  PrimaryNavbarVersion,
8
8
  HomePage,
9
+ ListPage,
9
10
  } from './app';
10
11
  import { init } from '../index';
11
- import {
12
- Action, AuthType, EmbedEvent, HostEvent, RuntimeFilterOp,
13
- } from '../types';
12
+ import { Action, AuthType, EmbedEvent, HostEvent, RuntimeFilterOp } from '../types';
14
13
  import {
15
14
  executeAfterWait,
16
15
  getDocumentBody,
@@ -45,12 +44,13 @@ beforeAll(() => {
45
44
  authType: AuthType.None,
46
45
  });
47
46
  jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
48
- (window as any).ResizeObserver = window.ResizeObserver
49
- || jest.fn().mockImplementation(() => ({
50
- disconnect: jest.fn(),
51
- observe: jest.fn(),
52
- unobserve: jest.fn(),
53
- }));
47
+ (window as any).ResizeObserver =
48
+ window.ResizeObserver ||
49
+ jest.fn().mockImplementation(() => ({
50
+ disconnect: jest.fn(),
51
+ observe: jest.fn(),
52
+ unobserve: jest.fn(),
53
+ }));
54
54
  });
55
55
 
56
56
  const cleanUp = () => {
@@ -316,6 +316,20 @@ describe('App embed tests', () => {
316
316
  });
317
317
  });
318
318
 
319
+ test('should set coverAndFilterOptionInPDF to false in url', async () => {
320
+ const appEmbed = new AppEmbed(getRootEl(), {
321
+ ...defaultViewConfig,
322
+ coverAndFilterOptionInPDF: false,
323
+ } as AppViewConfig);
324
+ appEmbed.render();
325
+ await executeAfterWait(() => {
326
+ expectUrlMatchesWithParams(
327
+ getIFrameSrc(),
328
+ `http://${thoughtSpotHost}/?embedApp=true&profileAndHelpInNavBarHidden=false&arePdfCoverFilterPageCheckboxesEnabled=false${defaultParamsPost}#/home`,
329
+ );
330
+ });
331
+ });
332
+
319
333
  test('should set isLiveboardStylingAndGroupingEnabled to true in url', async () => {
320
334
  const appEmbed = new AppEmbed(getRootEl(), {
321
335
  ...defaultViewConfig,
@@ -611,6 +625,59 @@ describe('App embed tests', () => {
611
625
  });
612
626
  });
613
627
 
628
+ test('Should add listpageVersion=v3 when listPageVersion is ListWithUXChanges to the iframe src', async () => {
629
+ const appEmbed = new AppEmbed(getRootEl(), {
630
+ ...defaultViewConfig,
631
+ discoveryExperience: {
632
+ listPageVersion: ListPage.ListWithUXChanges,
633
+ },
634
+ } as AppViewConfig);
635
+
636
+ appEmbed.render();
637
+ await executeAfterWait(() => {
638
+ expectUrlMatchesWithParams(
639
+ getIFrameSrc(),
640
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=false&listpageVersion=v3${defaultParams}${defaultParamsPost}#/home`,
641
+ );
642
+ });
643
+ });
644
+
645
+ test('Should not add listpageVersion when listPageVersion is List (v2) to the iframe src', async () => {
646
+ const appEmbed = new AppEmbed(getRootEl(), {
647
+ ...defaultViewConfig,
648
+ discoveryExperience: {
649
+ listPageVersion: ListPage.List,
650
+ },
651
+ } as AppViewConfig);
652
+
653
+ appEmbed.render();
654
+ await executeAfterWait(() => {
655
+ expectUrlMatchesWithParams(
656
+ getIFrameSrc(),
657
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=false${defaultParams}${defaultParamsPost}#/home`,
658
+ );
659
+ });
660
+ });
661
+
662
+ test('Should add listpageVersion=v3 combined with other discoveryExperience options to the iframe src', async () => {
663
+ const appEmbed = new AppEmbed(getRootEl(), {
664
+ ...defaultViewConfig,
665
+ discoveryExperience: {
666
+ primaryNavbarVersion: PrimaryNavbarVersion.Sliding,
667
+ homePage: HomePage.Modular,
668
+ listPageVersion: ListPage.ListWithUXChanges,
669
+ },
670
+ } as AppViewConfig);
671
+
672
+ appEmbed.render();
673
+ await executeAfterWait(() => {
674
+ expectUrlMatchesWithParams(
675
+ getIFrameSrc(),
676
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=true&navigationVersion=v3&listpageVersion=v3${defaultParams}${defaultParamsPost}#/home`,
677
+ );
678
+ });
679
+ });
680
+
614
681
  test('Should add enablePendoHelp flag to the iframe src conditional on navbar', async () => {
615
682
  const appEmbed = new AppEmbed(getRootEl(), {
616
683
  ...defaultViewConfig,
@@ -687,7 +754,8 @@ describe('App embed tests', () => {
687
754
  const appEmbed = new AppEmbed(getRootEl(), {
688
755
  ...defaultViewConfig,
689
756
  // eslint-disable-next-line max-len
690
- dataPanelCustomGroupsAccordionInitialState: DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST,
757
+ dataPanelCustomGroupsAccordionInitialState:
758
+ DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST,
691
759
  } as AppViewConfig);
692
760
 
693
761
  appEmbed.render();
@@ -700,34 +768,41 @@ describe('App embed tests', () => {
700
768
  });
701
769
 
702
770
  test('should register event handlers to adjust iframe height', async () => {
703
- const onSpy = jest.spyOn(AppEmbed.prototype, 'on')
704
- .mockImplementation((event, callback) => {
705
- if (event === EmbedEvent.RouteChange) {
706
- callback({ data: { currentPath: '/answers' } }, jest.fn());
707
- }
708
- if (event === EmbedEvent.EmbedHeight) {
709
- callback({ data: '100%' });
710
- }
711
- if (event === EmbedEvent.EmbedIframeCenter) {
712
- callback({}, jest.fn());
713
- }
714
- return null;
715
- });
771
+ let embedHeightCallback: any = () => {};
772
+ const onSpy = jest.spyOn(AppEmbed.prototype, 'on').mockImplementation((event, callback) => {
773
+ if (event === EmbedEvent.RouteChange) {
774
+ callback({ data: { currentPath: '/answers' } }, jest.fn());
775
+ }
776
+ if (event === EmbedEvent.EmbedHeight) {
777
+ embedHeightCallback = callback;
778
+ }
779
+ if (event === EmbedEvent.EmbedIframeCenter) {
780
+ callback({}, jest.fn());
781
+ }
782
+ return null;
783
+ });
716
784
  jest.spyOn(TsEmbed.prototype as any, 'getIframeCenter').mockReturnValue({});
717
785
  jest.spyOn(TsEmbed.prototype as any, 'setIFrameHeight').mockReturnValue({});
718
786
  const appEmbed = new AppEmbed(getRootEl(), {
719
787
  ...defaultViewConfig,
720
788
  fullHeight: true,
789
+ lazyLoadingForFullHeight: true,
721
790
  } as AppViewConfig);
722
791
 
723
- appEmbed.render();
792
+ // Set the iframe before render
793
+ (appEmbed as any).iFrame = document.createElement('iframe');
794
+
795
+ // Wait for render to complete
796
+ await appEmbed.render();
797
+ embedHeightCallback({ data: '100%' });
724
798
 
799
+ // Verify event handlers were registered
725
800
  await executeAfterWait(() => {
726
801
  expect(onSpy).toHaveBeenCalledWith(EmbedEvent.EmbedHeight, expect.anything());
727
802
  expect(onSpy).toHaveBeenCalledWith(EmbedEvent.RouteChange, expect.anything());
728
803
  expect(onSpy).toHaveBeenCalledWith(EmbedEvent.EmbedIframeCenter, expect.anything());
729
- });
730
- jest.clearAllMocks();
804
+ expect(onSpy).toHaveBeenCalledWith(EmbedEvent.RequestVisibleEmbedCoordinates, expect.anything());
805
+ }, 100);
731
806
  });
732
807
 
733
808
  describe('Navigate to Page API', () => {
@@ -815,4 +890,382 @@ describe('App embed tests', () => {
815
890
  );
816
891
  });
817
892
  });
893
+
894
+ describe('LazyLoadingForFullHeight functionality', () => {
895
+ let mockIFrame: HTMLIFrameElement;
896
+
897
+ beforeEach(() => {
898
+ mockIFrame = document.createElement('iframe');
899
+ mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
900
+ top: 100,
901
+ left: 150,
902
+ bottom: 600,
903
+ right: 800,
904
+ width: 650,
905
+ height: 500,
906
+ });
907
+ jest.spyOn(document, 'createElement').mockImplementation((tagName) => {
908
+ if (tagName === 'iframe') {
909
+ return mockIFrame;
910
+ }
911
+ return document.createElement(tagName);
912
+ });
913
+ });
914
+
915
+ afterEach(() => {
916
+ jest.restoreAllMocks();
917
+ });
918
+
919
+ test('should set lazyLoadingMargin parameter when provided', async () => {
920
+ const appEmbed = new AppEmbed(getRootEl(), {
921
+ ...defaultViewConfig,
922
+ fullHeight: true,
923
+ lazyLoadingForFullHeight: true,
924
+ lazyLoadingMargin: '100px 0px',
925
+ } as AppViewConfig);
926
+
927
+ await appEmbed.render();
928
+
929
+ await executeAfterWait(() => {
930
+ const iframeSrc = getIFrameSrc();
931
+ expect(iframeSrc).toContain('isLazyLoadingForEmbedEnabled=true');
932
+ expect(iframeSrc).toContain('isFullHeightPinboard=true');
933
+ expect(iframeSrc).toContain('rootMarginForLazyLoad=100px%200px');
934
+ }, 100);
935
+ });
936
+
937
+ test('should set isLazyLoadingForEmbedEnabled=true when both fullHeight and lazyLoadingForFullHeight are enabled', async () => {
938
+ // Mock the iframe element first
939
+ mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
940
+ top: 100,
941
+ left: 150,
942
+ bottom: 600,
943
+ right: 800,
944
+ width: 650,
945
+ height: 500,
946
+ });
947
+ Object.defineProperty(mockIFrame, 'scrollHeight', { value: 500 });
948
+
949
+ // Mock the event handlers
950
+ const onSpy = jest.spyOn(AppEmbed.prototype, 'on').mockImplementation((event, callback) => {
951
+ return null;
952
+ });
953
+ jest.spyOn(TsEmbed.prototype as any, 'getIframeCenter').mockReturnValue({});
954
+ jest.spyOn(TsEmbed.prototype as any, 'setIFrameHeight').mockReturnValue({});
955
+
956
+ // Create the AppEmbed instance
957
+ const appEmbed = new AppEmbed(getRootEl(), {
958
+ ...defaultViewConfig,
959
+ fullHeight: true,
960
+ lazyLoadingForFullHeight: true,
961
+ } as AppViewConfig);
962
+
963
+ // Set the iframe before render
964
+ (appEmbed as any).iFrame = mockIFrame;
965
+
966
+ // Add the iframe to the DOM
967
+ const rootEl = getRootEl();
968
+ rootEl.appendChild(mockIFrame);
969
+
970
+ // Wait for render to complete
971
+ await appEmbed.render();
972
+
973
+ // Wait for iframe initialization and URL parameters to be set
974
+ await executeAfterWait(() => {
975
+ const iframeSrc = appEmbed.getIFrameSrc();
976
+ expect(iframeSrc).toContain('isLazyLoadingForEmbedEnabled=true');
977
+ expect(iframeSrc).toContain('isFullHeightPinboard=true');
978
+ }, 100);
979
+ });
980
+
981
+ test('should not set lazyLoadingForEmbed when lazyLoadingForFullHeight is enabled but fullHeight is false', async () => {
982
+ const appEmbed = new AppEmbed(getRootEl(), {
983
+ ...defaultViewConfig,
984
+ fullHeight: false,
985
+ lazyLoadingForFullHeight: true,
986
+ } as AppViewConfig);
987
+
988
+ // Wait for render to complete
989
+ await appEmbed.render();
990
+
991
+ // Wait for iframe initialization and URL parameters to be set
992
+ await executeAfterWait(() => {
993
+ const iframeSrc = getIFrameSrc();
994
+ expect(iframeSrc).not.toContain('isLazyLoadingForEmbedEnabled=true');
995
+ expect(iframeSrc).not.toContain('isFullHeightPinboard=true');
996
+ }, 100); // 100ms wait time to ensure iframe src is set
997
+ });
998
+
999
+ test('should not set isLazyLoadingForEmbedEnabled when fullHeight is true but lazyLoadingForFullHeight is false', async () => {
1000
+ const appEmbed = new AppEmbed(getRootEl(), {
1001
+ ...defaultViewConfig,
1002
+ fullHeight: true,
1003
+ lazyLoadingForFullHeight: false,
1004
+ } as AppViewConfig);
1005
+
1006
+ // Wait for render to complete
1007
+ await appEmbed.render();
1008
+
1009
+ // Wait for iframe initialization and URL parameters to be set
1010
+ await executeAfterWait(() => {
1011
+ const iframeSrc = getIFrameSrc();
1012
+ expect(iframeSrc).not.toContain('isLazyLoadingForEmbedEnabled=true');
1013
+ expect(iframeSrc).toContain('isFullHeightPinboard=true');
1014
+ }, 100); // 100ms wait time to ensure iframe src is set
1015
+ });
1016
+
1017
+ test('should register RequestFullHeightLazyLoadData event handler when fullHeight is enabled', async () => {
1018
+ const onSpy = jest.spyOn(AppEmbed.prototype, 'on');
1019
+
1020
+ const appEmbed = new AppEmbed(getRootEl(), {
1021
+ ...defaultViewConfig,
1022
+ fullHeight: true,
1023
+ } as AppViewConfig);
1024
+
1025
+ await appEmbed.render();
1026
+
1027
+ expect(onSpy).toHaveBeenCalledWith(EmbedEvent.RequestVisibleEmbedCoordinates, expect.any(Function));
1028
+
1029
+ onSpy.mockRestore();
1030
+ });
1031
+
1032
+ test('should send correct visible data when RequestFullHeightLazyLoadData is triggered', async () => {
1033
+ const appEmbed = new AppEmbed(getRootEl(), {
1034
+ ...defaultViewConfig,
1035
+ fullHeight: true,
1036
+ lazyLoadingForFullHeight: true,
1037
+ } as AppViewConfig);
1038
+
1039
+ const mockTrigger = jest.spyOn(appEmbed, 'trigger');
1040
+
1041
+ await appEmbed.render();
1042
+
1043
+ // Trigger the lazy load data calculation
1044
+ (appEmbed as any).sendFullHeightLazyLoadData();
1045
+
1046
+ expect(mockTrigger).toHaveBeenCalledWith(HostEvent.VisibleEmbedCoordinates, {
1047
+ top: 0,
1048
+ height: 500,
1049
+ left: 0,
1050
+ width: 650,
1051
+ });
1052
+ });
1053
+
1054
+ test('should calculate correct visible data for partially visible full height element', async () => {
1055
+ // Mock iframe partially clipped from top and left
1056
+ mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
1057
+ top: -50,
1058
+ left: -30,
1059
+ bottom: 700,
1060
+ right: 1024,
1061
+ width: 1054,
1062
+ height: 750,
1063
+ });
1064
+
1065
+ const appEmbed = new AppEmbed(getRootEl(), {
1066
+ ...defaultViewConfig,
1067
+ fullHeight: true,
1068
+ lazyLoadingForFullHeight: true,
1069
+ } as AppViewConfig);
1070
+
1071
+ const mockTrigger = jest.spyOn(appEmbed, 'trigger');
1072
+
1073
+ await appEmbed.render();
1074
+
1075
+ // Trigger the lazy load data calculation
1076
+ (appEmbed as any).sendFullHeightLazyLoadData();
1077
+
1078
+ expect(mockTrigger).toHaveBeenCalledWith(HostEvent.VisibleEmbedCoordinates, {
1079
+ top: 50, // 50px clipped from top
1080
+ height: 700, // visible height (from 0 to 700)
1081
+ left: 30, // 30px clipped from left
1082
+ width: 1024, // visible width (from 0 to 1024)
1083
+ });
1084
+ });
1085
+
1086
+ test('should add window event listeners for resize and scroll when fullHeight and lazyLoadingForFullHeight are enabled', async () => {
1087
+ const addEventListenerSpy = jest.spyOn(window, 'addEventListener');
1088
+
1089
+ const appEmbed = new AppEmbed(getRootEl(), {
1090
+ ...defaultViewConfig,
1091
+ fullHeight: true,
1092
+ lazyLoadingForFullHeight: true,
1093
+ } as AppViewConfig);
1094
+
1095
+ await appEmbed.render();
1096
+
1097
+ expect(addEventListenerSpy).toHaveBeenCalledWith('resize', expect.any(Function));
1098
+ expect(addEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
1099
+
1100
+ addEventListenerSpy.mockRestore();
1101
+ });
1102
+
1103
+ test('should remove window event listeners on destroy when fullHeight and lazyLoadingForFullHeight are enabled', async () => {
1104
+ const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
1105
+
1106
+ const appEmbed = new AppEmbed(getRootEl(), {
1107
+ ...defaultViewConfig,
1108
+ fullHeight: true,
1109
+ lazyLoadingForFullHeight: true,
1110
+ } as AppViewConfig);
1111
+
1112
+ await appEmbed.render();
1113
+ appEmbed.destroy();
1114
+
1115
+ expect(removeEventListenerSpy).toHaveBeenCalledWith('resize', expect.any(Function));
1116
+ expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
1117
+
1118
+ removeEventListenerSpy.mockRestore();
1119
+ });
1120
+
1121
+ test('should handle RequestVisibleEmbedCoordinates event and respond with correct data', async () => {
1122
+ // Mock the iframe element
1123
+ mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
1124
+ top: 100,
1125
+ left: 150,
1126
+ bottom: 600,
1127
+ right: 800,
1128
+ width: 650,
1129
+ height: 500,
1130
+ });
1131
+ Object.defineProperty(mockIFrame, 'scrollHeight', { value: 500 });
1132
+
1133
+ const appEmbed = new AppEmbed(getRootEl(), {
1134
+ ...defaultViewConfig,
1135
+ fullHeight: true,
1136
+ lazyLoadingForFullHeight: true,
1137
+ } as AppViewConfig);
1138
+
1139
+ // Set the iframe before render
1140
+ (appEmbed as any).iFrame = mockIFrame;
1141
+
1142
+ await appEmbed.render();
1143
+
1144
+ // Create a mock responder function
1145
+ const mockResponder = jest.fn();
1146
+
1147
+ // Trigger the handler directly
1148
+ (appEmbed as any).requestVisibleEmbedCoordinatesHandler({}, mockResponder);
1149
+
1150
+ // Verify the responder was called with the correct data
1151
+ expect(mockResponder).toHaveBeenCalledWith({
1152
+ type: EmbedEvent.RequestVisibleEmbedCoordinates,
1153
+ data: {
1154
+ top: 0,
1155
+ height: 500,
1156
+ left: 0,
1157
+ width: 650,
1158
+ },
1159
+ });
1160
+ });
1161
+ });
1162
+
1163
+ describe('IFrame height management', () => {
1164
+ let mockIFrame: HTMLIFrameElement;
1165
+
1166
+ beforeEach(() => {
1167
+ mockIFrame = document.createElement('iframe');
1168
+ mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
1169
+ top: 100,
1170
+ left: 150,
1171
+ bottom: 600,
1172
+ right: 800,
1173
+ width: 650,
1174
+ height: 500,
1175
+ });
1176
+ Object.defineProperty(mockIFrame, 'scrollHeight', { value: 500 });
1177
+ });
1178
+
1179
+ test('should not call setIFrameHeight if currentPath starts with "/embed/viz/"', () => {
1180
+ const appEmbed = new AppEmbed(getRootEl(), {
1181
+ ...defaultViewConfig,
1182
+ fullHeight: true,
1183
+ } as AppViewConfig) as any;
1184
+ const spySetIFrameHeight = jest.spyOn(appEmbed, 'setIFrameHeight');
1185
+
1186
+ appEmbed.render();
1187
+ appEmbed.setIframeHeightForNonEmbedLiveboard({
1188
+ data: { currentPath: '/embed/viz/' },
1189
+ type: 'Route',
1190
+ });
1191
+
1192
+ expect(spySetIFrameHeight).not.toHaveBeenCalled();
1193
+ });
1194
+
1195
+ test('should not call setIFrameHeight if currentPath starts with "/embed/insights/viz/"', () => {
1196
+ const appEmbed = new AppEmbed(getRootEl(), {
1197
+ ...defaultViewConfig,
1198
+ fullHeight: true,
1199
+ } as AppViewConfig) as any;
1200
+ const spySetIFrameHeight = jest.spyOn(appEmbed, 'setIFrameHeight');
1201
+
1202
+ appEmbed.render();
1203
+ appEmbed.setIframeHeightForNonEmbedLiveboard({
1204
+ data: { currentPath: '/embed/insights/viz/' },
1205
+ type: 'Route',
1206
+ });
1207
+
1208
+ expect(spySetIFrameHeight).not.toHaveBeenCalled();
1209
+ });
1210
+
1211
+ test('should call setIFrameHeight if currentPath starts with "/some/other/path/"', () => {
1212
+ const appEmbed = new AppEmbed(getRootEl(), {
1213
+ ...defaultViewConfig,
1214
+ fullHeight: true,
1215
+ } as AppViewConfig) as any;
1216
+ const spySetIFrameHeight = jest
1217
+ .spyOn(appEmbed, 'setIFrameHeight')
1218
+ .mockImplementation(jest.fn());
1219
+
1220
+ appEmbed.render();
1221
+ appEmbed.setIframeHeightForNonEmbedLiveboard({
1222
+ data: { currentPath: '/some/other/path/' },
1223
+ type: 'Route',
1224
+ });
1225
+
1226
+ expect(spySetIFrameHeight).toHaveBeenCalled();
1227
+ });
1228
+
1229
+ test('should update iframe height correctly', async () => {
1230
+ const appEmbed = new AppEmbed(getRootEl(), {
1231
+ ...defaultViewConfig,
1232
+ fullHeight: true,
1233
+ } as AppViewConfig) as any;
1234
+
1235
+ // Set up the mock iframe
1236
+ appEmbed.iFrame = mockIFrame;
1237
+ document.body.appendChild(mockIFrame);
1238
+
1239
+ await appEmbed.render();
1240
+ const mockEvent = {
1241
+ data: 600,
1242
+ type: EmbedEvent.EmbedHeight,
1243
+ };
1244
+ appEmbed.updateIFrameHeight(mockEvent);
1245
+
1246
+ // Check if the iframe style was updated
1247
+ expect(mockIFrame.style.height).toBe('600px');
1248
+ });
1249
+
1250
+ test('should handle updateIFrameHeight with default height', async () => {
1251
+ const appEmbed = new AppEmbed(getRootEl(), {
1252
+ ...defaultViewConfig,
1253
+ fullHeight: true,
1254
+ } as AppViewConfig) as any;
1255
+
1256
+ // Set up the mock iframe
1257
+ appEmbed.iFrame = mockIFrame;
1258
+ document.body.appendChild(mockIFrame);
1259
+
1260
+ await appEmbed.render();
1261
+ const mockEvent = {
1262
+ data: 0, // This will make it use the scrollHeight
1263
+ type: EmbedEvent.EmbedHeight,
1264
+ };
1265
+ appEmbed.updateIFrameHeight(mockEvent);
1266
+
1267
+ // Should use the scrollHeight
1268
+ expect(mockIFrame.style.height).toBe('500px');
1269
+ });
1270
+ });
818
1271
  });