@thoughtspot/visual-embed-sdk 1.43.1 → 1.44.1-test

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 (151) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/api-intercept.d.ts.map +1 -1
  3. package/cjs/src/api-intercept.js +8 -3
  4. package/cjs/src/api-intercept.js.map +1 -1
  5. package/cjs/src/api-intercept.spec.js +19 -3
  6. package/cjs/src/api-intercept.spec.js.map +1 -1
  7. package/cjs/src/embed/app.d.ts +32 -0
  8. package/cjs/src/embed/app.d.ts.map +1 -1
  9. package/cjs/src/embed/app.js +9 -4
  10. package/cjs/src/embed/app.js.map +1 -1
  11. package/cjs/src/embed/app.spec.js +104 -1
  12. package/cjs/src/embed/app.spec.js.map +1 -1
  13. package/cjs/src/embed/base.d.ts +7 -0
  14. package/cjs/src/embed/base.d.ts.map +1 -1
  15. package/cjs/src/embed/base.js +16 -1
  16. package/cjs/src/embed/base.js.map +1 -1
  17. package/cjs/src/embed/base.spec.js +21 -0
  18. package/cjs/src/embed/base.spec.js.map +1 -1
  19. package/cjs/src/embed/conversation.d.ts +15 -0
  20. package/cjs/src/embed/conversation.d.ts.map +1 -1
  21. package/cjs/src/embed/conversation.js +10 -2
  22. package/cjs/src/embed/conversation.js.map +1 -1
  23. package/cjs/src/embed/conversation.spec.js +30 -1
  24. package/cjs/src/embed/conversation.spec.js.map +1 -1
  25. package/cjs/src/embed/liveboard.d.ts +33 -0
  26. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  27. package/cjs/src/embed/liveboard.js +13 -5
  28. package/cjs/src/embed/liveboard.js.map +1 -1
  29. package/cjs/src/embed/liveboard.spec.js +108 -0
  30. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  31. package/cjs/src/embed/ts-embed.d.ts +3 -2
  32. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  33. package/cjs/src/embed/ts-embed.js +51 -17
  34. package/cjs/src/embed/ts-embed.js.map +1 -1
  35. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  36. package/cjs/src/embed/ts-embed.spec.js +93 -5
  37. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  38. package/cjs/src/errors.d.ts +7 -0
  39. package/cjs/src/errors.d.ts.map +1 -1
  40. package/cjs/src/errors.js +7 -0
  41. package/cjs/src/errors.js.map +1 -1
  42. package/cjs/src/index.d.ts +2 -2
  43. package/cjs/src/index.d.ts.map +1 -1
  44. package/cjs/src/index.js +2 -1
  45. package/cjs/src/index.js.map +1 -1
  46. package/cjs/src/react/all-types-export.d.ts +1 -1
  47. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  48. package/cjs/src/react/all-types-export.js +2 -1
  49. package/cjs/src/react/all-types-export.js.map +1 -1
  50. package/cjs/src/types.d.ts +250 -7
  51. package/cjs/src/types.d.ts.map +1 -1
  52. package/cjs/src/types.js +135 -2
  53. package/cjs/src/types.js.map +1 -1
  54. package/dist/{index-CpkMygsc.js → index-BXCUJ09L.js} +1 -1
  55. package/dist/src/api-intercept.d.ts.map +1 -1
  56. package/dist/src/embed/app.d.ts +32 -0
  57. package/dist/src/embed/app.d.ts.map +1 -1
  58. package/dist/src/embed/base.d.ts +7 -0
  59. package/dist/src/embed/base.d.ts.map +1 -1
  60. package/dist/src/embed/conversation.d.ts +15 -0
  61. package/dist/src/embed/conversation.d.ts.map +1 -1
  62. package/dist/src/embed/liveboard.d.ts +33 -0
  63. package/dist/src/embed/liveboard.d.ts.map +1 -1
  64. package/dist/src/embed/ts-embed.d.ts +3 -2
  65. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  66. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  67. package/dist/src/errors.d.ts +7 -0
  68. package/dist/src/errors.d.ts.map +1 -1
  69. package/dist/src/index.d.ts +2 -2
  70. package/dist/src/index.d.ts.map +1 -1
  71. package/dist/src/react/all-types-export.d.ts +1 -1
  72. package/dist/src/react/all-types-export.d.ts.map +1 -1
  73. package/dist/src/types.d.ts +250 -7
  74. package/dist/src/types.d.ts.map +1 -1
  75. package/dist/tsembed-react.es.js +304 -105
  76. package/dist/tsembed-react.js +303 -104
  77. package/dist/tsembed.es.js +318 -106
  78. package/dist/tsembed.js +317 -104
  79. package/dist/visual-embed-sdk-react-full.d.ts +290 -7
  80. package/dist/visual-embed-sdk-react.d.ts +283 -7
  81. package/dist/visual-embed-sdk.d.ts +290 -7
  82. package/lib/package.json +1 -1
  83. package/lib/src/api-intercept.d.ts.map +1 -1
  84. package/lib/src/api-intercept.js +9 -4
  85. package/lib/src/api-intercept.js.map +1 -1
  86. package/lib/src/api-intercept.spec.js +20 -4
  87. package/lib/src/api-intercept.spec.js.map +1 -1
  88. package/lib/src/embed/app.d.ts +32 -0
  89. package/lib/src/embed/app.d.ts.map +1 -1
  90. package/lib/src/embed/app.js +10 -5
  91. package/lib/src/embed/app.js.map +1 -1
  92. package/lib/src/embed/app.spec.js +104 -1
  93. package/lib/src/embed/app.spec.js.map +1 -1
  94. package/lib/src/embed/base.d.ts +7 -0
  95. package/lib/src/embed/base.d.ts.map +1 -1
  96. package/lib/src/embed/base.js +14 -0
  97. package/lib/src/embed/base.js.map +1 -1
  98. package/lib/src/embed/base.spec.js +21 -0
  99. package/lib/src/embed/base.spec.js.map +1 -1
  100. package/lib/src/embed/conversation.d.ts +15 -0
  101. package/lib/src/embed/conversation.d.ts.map +1 -1
  102. package/lib/src/embed/conversation.js +11 -3
  103. package/lib/src/embed/conversation.js.map +1 -1
  104. package/lib/src/embed/conversation.spec.js +31 -2
  105. package/lib/src/embed/conversation.spec.js.map +1 -1
  106. package/lib/src/embed/liveboard.d.ts +33 -0
  107. package/lib/src/embed/liveboard.d.ts.map +1 -1
  108. package/lib/src/embed/liveboard.js +14 -6
  109. package/lib/src/embed/liveboard.js.map +1 -1
  110. package/lib/src/embed/liveboard.spec.js +108 -0
  111. package/lib/src/embed/liveboard.spec.js.map +1 -1
  112. package/lib/src/embed/ts-embed.d.ts +3 -2
  113. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  114. package/lib/src/embed/ts-embed.js +52 -18
  115. package/lib/src/embed/ts-embed.js.map +1 -1
  116. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  117. package/lib/src/embed/ts-embed.spec.js +94 -6
  118. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  119. package/lib/src/errors.d.ts +7 -0
  120. package/lib/src/errors.d.ts.map +1 -1
  121. package/lib/src/errors.js +7 -0
  122. package/lib/src/errors.js.map +1 -1
  123. package/lib/src/index.d.ts +2 -2
  124. package/lib/src/index.d.ts.map +1 -1
  125. package/lib/src/index.js +2 -2
  126. package/lib/src/index.js.map +1 -1
  127. package/lib/src/react/all-types-export.d.ts +1 -1
  128. package/lib/src/react/all-types-export.d.ts.map +1 -1
  129. package/lib/src/react/all-types-export.js +1 -1
  130. package/lib/src/react/all-types-export.js.map +1 -1
  131. package/lib/src/types.d.ts +250 -7
  132. package/lib/src/types.d.ts.map +1 -1
  133. package/lib/src/types.js +134 -1
  134. package/lib/src/types.js.map +1 -1
  135. package/package.json +1 -1
  136. package/src/api-intercept.spec.ts +23 -10
  137. package/src/api-intercept.ts +9 -4
  138. package/src/embed/app.spec.ts +146 -4
  139. package/src/embed/app.ts +69 -24
  140. package/src/embed/base.spec.ts +28 -0
  141. package/src/embed/base.ts +15 -0
  142. package/src/embed/conversation.spec.ts +39 -2
  143. package/src/embed/conversation.ts +28 -2
  144. package/src/embed/liveboard.spec.ts +136 -0
  145. package/src/embed/liveboard.ts +51 -4
  146. package/src/embed/ts-embed.spec.ts +107 -15
  147. package/src/embed/ts-embed.ts +56 -19
  148. package/src/errors.ts +7 -0
  149. package/src/index.ts +2 -0
  150. package/src/react/all-types-export.ts +1 -0
  151. package/src/types.ts +260 -6
@@ -20,6 +20,8 @@ import {
20
20
  SearchLiveboardCommonViewConfig as LiveboardOtherViewConfig,
21
21
  BaseViewConfig,
22
22
  LiveboardAppEmbedViewConfig,
23
+ ErrorDetailsTypes,
24
+ EmbedErrorCodes,
23
25
  } from '../types';
24
26
  import { calculateVisibleElementData, getQueryParamString, isUndefined } from '../utils';
25
27
  import { getAuthPromise } from './base';
@@ -65,6 +67,7 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
65
67
  * Supported embed types: `LiveboardEmbed`
66
68
  * @version SDK: 1.5.0 | ThoughtSpot: ts7.oct.cl, 7.2.1
67
69
  * @default 500
70
+ * @deprecated Use `minimumHeight` instead.
68
71
  * @example
69
72
  * ```js
70
73
  * const embed = new LiveboardEmbed('#embed', {
@@ -75,6 +78,23 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
75
78
  * ```
76
79
  */
77
80
  defaultHeight?: number;
81
+ /**
82
+ * This is the minimum height (in pixels) for a full-height Liveboard.
83
+ * Setting this height helps resolve issues with empty Liveboards and
84
+ * other screens navigable from a Liveboard.
85
+ *
86
+ * @version SDK: 1.44.2 | ThoughtSpot: 26.0.2.cl
87
+ * @default 500
88
+ * @example
89
+ * ```js
90
+ * const embed = new LiveboardEmbed('#embed', {
91
+ * ... // other liveboard view config
92
+ * fullHeight: true,
93
+ * minimumHeight: 600,
94
+ * });
95
+ * ```
96
+ */
97
+ minimumHeight?: number;
78
98
  /**
79
99
  * @Deprecated If set to true, the context menu in visualizations will be enabled.
80
100
  * @example
@@ -396,6 +416,21 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
396
416
  * @version SDK: 1.41.1 | ThoughtSpot: 10.5.0.cl
397
417
  */
398
418
  showSpotterLimitations?: boolean;
419
+ /**
420
+ * updatedSpotterChatPrompt : Controls the updated spotter chat prompt.
421
+ *
422
+ * Supported embed types: `LiveboardEmbed`
423
+ * @default false
424
+ * @example
425
+ * ```js
426
+ * const embed = new LiveboardEmbed('#tsEmbed', {
427
+ * ... //other embed view config
428
+ * updatedSpotterChatPrompt : true,
429
+ * })
430
+ * ```
431
+ * @version SDK: 1.45.0 | ThoughtSpot: 26.2.0.cl
432
+ */
433
+ updatedSpotterChatPrompt?: boolean;
399
434
  }
400
435
 
401
436
  /**
@@ -452,6 +487,7 @@ export class LiveboardEmbed extends V1Embed {
452
487
  enableVizTransformations,
453
488
  fullHeight,
454
489
  defaultHeight,
490
+ minimumHeight,
455
491
  visibleVizs,
456
492
  liveboardV2,
457
493
  vizId,
@@ -465,6 +501,8 @@ export class LiveboardEmbed extends V1Embed {
465
501
  showLiveboardVerifiedBadge = true,
466
502
  showLiveboardReverifyBanner = true,
467
503
  hideIrrelevantChipsInLiveboardTabs = false,
504
+ showMaskedFilterChip = false,
505
+ isLiveboardMasterpiecesEnabled = false,
468
506
  isEnhancedFilterInteractivityEnabled = false,
469
507
  enableAskSage,
470
508
  enable2ColumnLayout,
@@ -480,6 +518,7 @@ export class LiveboardEmbed extends V1Embed {
480
518
  showSpotterLimitations,
481
519
  isCentralizedLiveboardFilterUXEnabled = false,
482
520
  isLinkParametersEnabled,
521
+ updatedSpotterChatPrompt,
483
522
  } = this.viewConfig;
484
523
 
485
524
  const preventLiveboardFilterRemoval = this.viewConfig.preventLiveboardFilterRemoval
@@ -492,15 +531,16 @@ export class LiveboardEmbed extends V1Embed {
492
531
  params[Param.RootMarginForLazyLoad] = this.viewConfig.lazyLoadingMargin;
493
532
  }
494
533
  }
495
- if (defaultHeight) {
496
- this.defaultHeight = defaultHeight;
497
- }
534
+ this.defaultHeight = minimumHeight || defaultHeight || this.defaultHeight;
498
535
  if (enableVizTransformations !== undefined) {
499
536
  params[Param.EnableVizTransformations] = enableVizTransformations.toString();
500
537
  }
501
538
  if (preventLiveboardFilterRemoval) {
502
539
  params[Param.preventLiveboardFilterRemoval] = true;
503
540
  }
541
+ if (!isUndefined(updatedSpotterChatPrompt)) {
542
+ params[Param.UpdatedSpotterChatPrompt] = !!updatedSpotterChatPrompt;
543
+ }
504
544
  if (visibleVizs) {
505
545
  params[Param.visibleVizs] = visibleVizs;
506
546
  }
@@ -570,6 +610,8 @@ export class LiveboardEmbed extends V1Embed {
570
610
  params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
571
611
  params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
572
612
  params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
613
+ params[Param.ShowMaskedFilterChip] = showMaskedFilterChip;
614
+ params[Param.IsLiveboardMasterpiecesEnabled] = isLiveboardMasterpiecesEnabled;
573
615
  params[Param.IsEnhancedFilterInteractivityEnabled] = isEnhancedFilterInteractivityEnabled;
574
616
  params[Param.DataPanelV2Enabled] = dataPanelV2;
575
617
  params[Param.EnableCustomColumnGroups] = enableCustomColumnGroups;
@@ -623,7 +665,12 @@ export class LiveboardEmbed extends V1Embed {
623
665
  const liveboardId = this.viewConfig.liveboardId ?? this.viewConfig.pinboardId;
624
666
 
625
667
  if (!liveboardId) {
626
- this.handleError(ERROR_MESSAGE.LIVEBOARD_VIZ_ID_VALIDATION);
668
+ this.handleError({
669
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
670
+ message: ERROR_MESSAGE.LIVEBOARD_VIZ_ID_VALIDATION,
671
+ code: EmbedErrorCodes.LIVEBOARD_ID_MISSING,
672
+ error: ERROR_MESSAGE.LIVEBOARD_VIZ_ID_VALIDATION,
673
+ });
627
674
  }
628
675
  return `${this.getRootIframeSrc()}${this.getIframeSuffixSrc(
629
676
  liveboardId,
@@ -29,6 +29,8 @@ import {
29
29
  CustomActionTarget,
30
30
  CustomActionsPosition,
31
31
  DefaultAppInitData,
32
+ ErrorDetailsTypes,
33
+ EmbedErrorCodes,
32
34
  } from '../types';
33
35
  import {
34
36
  executeAfterWait,
@@ -1613,9 +1615,12 @@ describe('Unit test case for ts embed', () => {
1613
1615
  } as LiveboardViewConfig);
1614
1616
  await pinboardEmbed.render();
1615
1617
  expect(pinboardEmbed['isError']).toBe(true);
1616
- expect(logger.error).toHaveBeenCalledWith(
1617
- 'You cannot have both hidden actions and visible actions',
1618
- );
1618
+ expect(logger.error).toHaveBeenCalledWith({
1619
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1620
+ message: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1621
+ code: EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG,
1622
+ error: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1623
+ });
1619
1624
  });
1620
1625
  test('should not throw error when there are only visible or hidden actions - pinboard', async () => {
1621
1626
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
@@ -1645,9 +1650,12 @@ describe('Unit test case for ts embed', () => {
1645
1650
  } as LiveboardViewConfig);
1646
1651
  await liveboardEmbed.render();
1647
1652
  expect(liveboardEmbed['isError']).toBe(true);
1648
- expect(logger.error).toHaveBeenCalledWith(
1649
- 'You cannot have both hidden actions and visible actions',
1650
- );
1653
+ expect(logger.error).toHaveBeenCalledWith({
1654
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1655
+ message: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1656
+ code: EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG,
1657
+ error: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
1658
+ });
1651
1659
  }
1652
1660
  test('should throw error when there are both visible and hidden action arrays', async () => {
1653
1661
  await testActionsForLiveboards([Action.DownloadAsCsv], [Action.DownloadAsCsv]);
@@ -1690,9 +1698,12 @@ describe('Unit test case for ts embed', () => {
1690
1698
  } as LiveboardViewConfig);
1691
1699
  await pinboardEmbed.render();
1692
1700
  expect(pinboardEmbed['isError']).toBe(true);
1693
- expect(logger.error).toHaveBeenCalledWith(
1694
- 'You cannot have both hidden Tabs and visible Tabs',
1695
- );
1701
+ expect(logger.error).toHaveBeenCalledWith({
1702
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1703
+ message: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1704
+ code: EmbedErrorCodes.CONFLICTING_TABS_CONFIG,
1705
+ error: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1706
+ });
1696
1707
  });
1697
1708
  test('should not throw error when there are only visible or hidden Tabs - pinboard', async () => {
1698
1709
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
@@ -1722,9 +1733,12 @@ describe('Unit test case for ts embed', () => {
1722
1733
  } as LiveboardViewConfig);
1723
1734
  await liveboardEmbed.render();
1724
1735
  expect(liveboardEmbed['isError']).toBe(true);
1725
- expect(logger.error).toHaveBeenCalledWith(
1726
- 'You cannot have both hidden Tabs and visible Tabs',
1727
- );
1736
+ expect(logger.error).toHaveBeenCalledWith({
1737
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1738
+ message: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1739
+ code: EmbedErrorCodes.CONFLICTING_TABS_CONFIG,
1740
+ error: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
1741
+ });
1728
1742
  }
1729
1743
  test('should throw error when there are both visible and hidden Tab arrays', async () => {
1730
1744
  await testTabsForLiveboards([tabId1], [tabId2]);
@@ -1770,9 +1784,12 @@ describe('Unit test case for ts embed', () => {
1770
1784
  const tsEmbed = new SearchEmbed(getRootEl(), {});
1771
1785
  await tsEmbed.render();
1772
1786
  expect(tsEmbed['isError']).toBe(true);
1773
- expect(logger.error).toHaveBeenCalledWith(
1774
- 'You need to init the ThoughtSpot SDK module first',
1775
- );
1787
+ expect(logger.error).toHaveBeenCalledWith({
1788
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1789
+ message: ERROR_MESSAGE.INIT_SDK_REQUIRED,
1790
+ code: EmbedErrorCodes.INIT_ERROR,
1791
+ error: ERROR_MESSAGE.INIT_SDK_REQUIRED,
1792
+ });
1776
1793
  });
1777
1794
  });
1778
1795
 
@@ -3829,3 +3846,78 @@ describe('Unit test case for ts embed', () => {
3829
3846
  });
3830
3847
  });
3831
3848
  });
3849
+
3850
+
3851
+ describe('Additional Coverage Tests', () => {
3852
+ beforeAll(() => {
3853
+ init({
3854
+ thoughtSpotHost: 'tshost',
3855
+ authType: AuthType.None,
3856
+ });
3857
+ });
3858
+
3859
+ test('should handle getAuthTokenForCookielessInit with non-cookieless auth', async () => {
3860
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3861
+ const token = await searchEmbed['getAuthTokenForCookielessInit']();
3862
+ expect(token).toBe('');
3863
+ });
3864
+
3865
+ test('should call setIFrameHeight', async () => {
3866
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3867
+ await searchEmbed.render();
3868
+ await executeAfterWait(() => {
3869
+ searchEmbed['setIFrameHeight'](500);
3870
+ expect(getIFrameEl().style.height).toBe('500px');
3871
+ });
3872
+ });
3873
+
3874
+ test('should test getIframeCenter calculation', async () => {
3875
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3876
+ await searchEmbed.render();
3877
+ await executeAfterWait(() => {
3878
+ const center = searchEmbed['getIframeCenter']();
3879
+ expect(center).toHaveProperty('iframeCenter');
3880
+ expect(center).toHaveProperty('iframeHeight');
3881
+ expect(center).toHaveProperty('viewPortHeight');
3882
+ });
3883
+ });
3884
+
3885
+ test('should handle preRender with replaceExistingPreRender=true', async () => {
3886
+ createRootEleForEmbed();
3887
+ const embed1 = new LiveboardEmbed('#tsEmbedDiv', {
3888
+ preRenderId: 'test-replace',
3889
+ liveboardId: 'lb1',
3890
+ });
3891
+ await embed1.preRender();
3892
+ const embed2 = new LiveboardEmbed('#tsEmbedDiv', {
3893
+ preRenderId: 'test-replace',
3894
+ liveboardId: 'lb2',
3895
+ });
3896
+ await embed2.preRender(false, true);
3897
+ expect(document.getElementById('tsEmbed-pre-render-wrapper-test-replace')).toBeTruthy();
3898
+ });
3899
+
3900
+ test('should test getIframeSrc base implementation', () => {
3901
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3902
+ expect(searchEmbed.getIframeSrc()).toBe('');
3903
+ });
3904
+
3905
+ test('should handle createEmbedEventResponder with OnBeforeGetVizDataIntercept', async () => {
3906
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3907
+ const mockPort: any = { postMessage: jest.fn() };
3908
+ const responder = searchEmbed['createEmbedEventResponder'](
3909
+ mockPort,
3910
+ EmbedEvent.OnBeforeGetVizDataIntercept,
3911
+ );
3912
+ responder({ data: 'test' });
3913
+ expect(mockPort.postMessage).toHaveBeenCalled();
3914
+ });
3915
+
3916
+ test('should clean up message event listeners', async () => {
3917
+ const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
3918
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
3919
+ await searchEmbed.render();
3920
+ searchEmbed['unsubscribeToMessageEvents']();
3921
+ expect(removeEventListenerSpy).toHaveBeenCalledWith('message', expect.any(Function));
3922
+ });
3923
+ });
@@ -57,6 +57,9 @@ import {
57
57
  ContextMenuTriggerOptions,
58
58
  DefaultAppInitData,
59
59
  AllEmbedViewConfig as ViewConfig,
60
+ EmbedErrorDetailsEvent,
61
+ ErrorDetailsTypes,
62
+ EmbedErrorCodes,
60
63
  } from '../types';
61
64
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
62
65
  import { processEventData, processAuthFailure } from '../utils/processData';
@@ -218,20 +221,24 @@ export class TsEmbed {
218
221
  * Throws error encountered during initialization.
219
222
  */
220
223
  private throwInitError() {
221
- this.handleError('You need to init the ThoughtSpot SDK module first');
224
+ this.handleError({
225
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
226
+ message: ERROR_MESSAGE.INIT_SDK_REQUIRED,
227
+ code: EmbedErrorCodes.INIT_ERROR,
228
+ error : ERROR_MESSAGE.INIT_SDK_REQUIRED,
229
+ });
222
230
  }
223
231
 
224
232
  /**
225
233
  * Handles errors within the SDK
226
234
  * @param error The error message or object
235
+ * @param errorDetails The error details
227
236
  */
228
- protected handleError(error: string | Record<string, unknown>) {
237
+ protected handleError(errorDetails: EmbedErrorDetailsEvent) {
229
238
  this.isError = true;
230
- this.executeCallbacks(EmbedEvent.Error, {
231
- error,
232
- });
239
+ this.executeCallbacks(EmbedEvent.Error, errorDetails);
233
240
  // Log error
234
- logger.error(error);
241
+ logger.error(errorDetails);
235
242
  }
236
243
 
237
244
  /**
@@ -325,11 +332,14 @@ export class TsEmbed {
325
332
  window.addEventListener('online', onlineEventListener);
326
333
 
327
334
  const offlineEventListener = (e: Event) => {
328
- const offlineWarning = ERROR_MESSAGE.OFFLINE_WARNING;
329
- this.executeCallbacks(EmbedEvent.Error, {
330
- offlineWarning,
331
- });
332
- logger.warn(offlineWarning);
335
+ const errorDetails = {
336
+ errorType: ErrorDetailsTypes.NETWORK,
337
+ message: ERROR_MESSAGE.OFFLINE_WARNING,
338
+ code: EmbedErrorCodes.NETWORK_ERROR,
339
+ offlineWarning : ERROR_MESSAGE.OFFLINE_WARNING,
340
+ };
341
+ this.executeCallbacks(EmbedEvent.Error, errorDetails);
342
+ logger.warn(errorDetails);
333
343
  };
334
344
  window.addEventListener('offline', offlineEventListener);
335
345
 
@@ -444,9 +454,11 @@ export class TsEmbed {
444
454
  ]);
445
455
  if (customActionsResult.errors.length > 0) {
446
456
  this.handleError({
447
- type: 'CUSTOM_ACTION_VALIDATION',
448
- message: customActionsResult.errors,
449
- });
457
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
458
+ message: customActionsResult.errors,
459
+ code: EmbedErrorCodes.CUSTOM_ACTION_VALIDATION,
460
+ error : { type: EmbedErrorCodes.CUSTOM_ACTION_VALIDATION, message: customActionsResult.errors }
461
+ });
450
462
  }
451
463
  const baseInitData = {
452
464
  customisations: getCustomisations(this.embedConfig, this.viewConfig),
@@ -658,12 +670,22 @@ export class TsEmbed {
658
670
  };
659
671
 
660
672
  if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
661
- this.handleError('You cannot have both hidden actions and visible actions');
673
+ this.handleError({
674
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
675
+ message: ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
676
+ code: EmbedErrorCodes.CONFLICTING_ACTIONS_CONFIG,
677
+ error : ERROR_MESSAGE.CONFLICTING_ACTIONS_CONFIG,
678
+ });
662
679
  return queryParams;
663
680
  }
664
681
 
665
682
  if (Array.isArray(visibleTabs) && Array.isArray(hiddenTabs)) {
666
- this.handleError('You cannot have both hidden Tabs and visible Tabs');
683
+ this.handleError({
684
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
685
+ message: ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
686
+ code: EmbedErrorCodes.CONFLICTING_TABS_CONFIG,
687
+ error : ERROR_MESSAGE.CONFLICTING_TABS_CONFIG,
688
+ });
667
689
  return queryParams;
668
690
  }
669
691
  if (primaryAction) {
@@ -916,7 +938,12 @@ export class TsEmbed {
916
938
  error: JSON.stringify(error),
917
939
  });
918
940
  this.handleInsertionIntoDOM(this.embedConfig.loginFailedMessage);
919
- this.handleError(error);
941
+ this.handleError({
942
+ errorType: ErrorDetailsTypes.API,
943
+ message: error.message || ERROR_MESSAGE.LOGIN_FAILED,
944
+ code: EmbedErrorCodes.LOGIN_FAILED,
945
+ error : error,
946
+ });
920
947
  });
921
948
  });
922
949
  }
@@ -1323,12 +1350,22 @@ export class TsEmbed {
1323
1350
  uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_TRIGGER}-${messageType}`);
1324
1351
 
1325
1352
  if (!this.isRendered) {
1326
- this.handleError('Please call render before triggering events');
1353
+ this.handleError({
1354
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1355
+ message: ERROR_MESSAGE.RENDER_BEFORE_EVENTS_REQUIRED,
1356
+ code: EmbedErrorCodes.RENDER_NOT_CALLED,
1357
+ error: ERROR_MESSAGE.RENDER_BEFORE_EVENTS_REQUIRED,
1358
+ });
1327
1359
  return null;
1328
1360
  }
1329
1361
 
1330
1362
  if (!messageType) {
1331
- this.handleError('Host event type is undefined');
1363
+ this.handleError({
1364
+ errorType: ErrorDetailsTypes.VALIDATION_ERROR,
1365
+ message: ERROR_MESSAGE.HOST_EVENT_TYPE_UNDEFINED,
1366
+ code: EmbedErrorCodes.HOST_EVENT_TYPE_UNDEFINED,
1367
+ error: ERROR_MESSAGE.HOST_EVENT_TYPE_UNDEFINED,
1368
+ });
1332
1369
  return null;
1333
1370
  }
1334
1371
 
package/src/errors.ts CHANGED
@@ -20,6 +20,13 @@ export const ERROR_MESSAGE = {
20
20
  RENDER_CALLED_BEFORE_INIT: 'Looks like render was called before calling init, the render won\'t start until init is called.\nFor more info check\n1. https://developers.thoughtspot.com/docs/Function_init#_init\n2.https://developers.thoughtspot.com/docs/getting-started#initSdk',
21
21
  SPOTTER_AGENT_NOT_INITIALIZED: 'SpotterAgent not initialized',
22
22
  OFFLINE_WARNING : 'Network not Detected. Embed is offline. Please reconnect and refresh',
23
+ INIT_SDK_REQUIRED: 'You need to init the ThoughtSpot SDK module first',
24
+ CONFLICTING_ACTIONS_CONFIG: 'You cannot have both hidden actions and visible actions',
25
+ CONFLICTING_TABS_CONFIG: 'You cannot have both hidden Tabs and visible Tabs',
26
+ RENDER_BEFORE_EVENTS_REQUIRED: 'Please call render before triggering events',
27
+ HOST_EVENT_TYPE_UNDEFINED: 'Host event type is undefined',
28
+ LOGIN_FAILED: 'Login failed',
29
+ ERROR_PARSING_API_INTERCEPT_BODY: 'Error parsing api intercept body',
23
30
  };
24
31
 
25
32
  export const CUSTOM_ACTIONS_ERROR_MESSAGE = {
package/src/index.ts CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  exportTML,
27
27
  executeTMLInput,
28
28
  exportTMLInput,
29
+ reloadIframe,
29
30
  } from './embed/base';
30
31
  import { PinboardEmbed, LiveboardViewConfig, LiveboardEmbed } from './embed/liveboard';
31
32
  import { SearchEmbed, SearchViewConfig } from './embed/search';
@@ -83,6 +84,7 @@ export {
83
84
  executeTML,
84
85
  exportTML,
85
86
  executeTMLInput,
87
+ reloadIframe,
86
88
  exportTMLInput,
87
89
  getEmbedConfig as getInitConfig,
88
90
  getSessionInfo,
@@ -22,6 +22,7 @@ export {
22
22
  init,
23
23
  logout,
24
24
  prefetch,
25
+ reloadIframe,
25
26
  getInitConfig,
26
27
  getSessionInfo,
27
28
  uploadMixpanelEvent,