@thoughtspot/visual-embed-sdk 1.40.1-alpha.2 → 1.41.0-pre-render-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 (111) hide show
  1. package/cjs/package.json +5 -4
  2. package/cjs/src/css-variables.d.ts +316 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts.map +1 -1
  5. package/cjs/src/embed/app.js +8 -0
  6. package/cjs/src/embed/app.js.map +1 -1
  7. package/cjs/src/embed/app.spec.js +12 -2
  8. package/cjs/src/embed/app.spec.js.map +1 -1
  9. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  11. package/cjs/src/embed/conversation.d.ts +63 -2
  12. package/cjs/src/embed/conversation.d.ts.map +1 -1
  13. package/cjs/src/embed/conversation.js +10 -2
  14. package/cjs/src/embed/conversation.js.map +1 -1
  15. package/cjs/src/embed/conversation.spec.js +102 -0
  16. package/cjs/src/embed/conversation.spec.js.map +1 -1
  17. package/cjs/src/embed/liveboard.d.ts +11 -2
  18. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  19. package/cjs/src/embed/liveboard.js +21 -7
  20. package/cjs/src/embed/liveboard.js.map +1 -1
  21. package/cjs/src/embed/liveboard.spec.js +185 -4
  22. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  23. package/cjs/src/embed/sage.js.map +1 -1
  24. package/cjs/src/embed/ts-embed.d.ts +22 -7
  25. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  26. package/cjs/src/embed/ts-embed.js +75 -46
  27. package/cjs/src/embed/ts-embed.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.spec.js +173 -1
  29. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  30. package/cjs/src/types.d.ts +152 -44
  31. package/cjs/src/types.d.ts.map +1 -1
  32. package/cjs/src/types.js +139 -42
  33. package/cjs/src/types.js.map +1 -1
  34. package/cjs/src/utils/liveboardService/liveboardService.d.ts +21 -6
  35. package/cjs/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  36. package/cjs/src/utils/liveboardService/liveboardService.js +21 -6
  37. package/cjs/src/utils/liveboardService/liveboardService.js.map +1 -1
  38. package/dist/index-BDlM0f0T.js +7371 -0
  39. package/dist/src/css-variables.d.ts +316 -0
  40. package/dist/src/css-variables.d.ts.map +1 -1
  41. package/dist/src/embed/app.d.ts.map +1 -1
  42. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  43. package/dist/src/embed/conversation.d.ts +63 -2
  44. package/dist/src/embed/conversation.d.ts.map +1 -1
  45. package/dist/src/embed/liveboard.d.ts +11 -2
  46. package/dist/src/embed/liveboard.d.ts.map +1 -1
  47. package/dist/src/embed/ts-embed.d.ts +22 -7
  48. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  49. package/dist/src/types.d.ts +152 -44
  50. package/dist/src/types.d.ts.map +1 -1
  51. package/dist/src/utils/liveboardService/liveboardService.d.ts +21 -6
  52. package/dist/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  53. package/dist/tsembed-react.es.js +256 -100
  54. package/dist/tsembed-react.js +255 -99
  55. package/dist/tsembed.es.js +277 -106
  56. package/dist/tsembed.js +276 -105
  57. package/dist/visual-embed-sdk-react-full.d.ts +575 -57
  58. package/dist/visual-embed-sdk-react.d.ts +575 -57
  59. package/dist/visual-embed-sdk.d.ts +575 -57
  60. package/lib/package.json +5 -4
  61. package/lib/src/css-variables.d.ts +316 -0
  62. package/lib/src/css-variables.d.ts.map +1 -1
  63. package/lib/src/embed/app.d.ts.map +1 -1
  64. package/lib/src/embed/app.js +8 -0
  65. package/lib/src/embed/app.js.map +1 -1
  66. package/lib/src/embed/app.spec.js +12 -2
  67. package/lib/src/embed/app.spec.js.map +1 -1
  68. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  69. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  70. package/lib/src/embed/conversation.d.ts +63 -2
  71. package/lib/src/embed/conversation.d.ts.map +1 -1
  72. package/lib/src/embed/conversation.js +11 -3
  73. package/lib/src/embed/conversation.js.map +1 -1
  74. package/lib/src/embed/conversation.spec.js +104 -2
  75. package/lib/src/embed/conversation.spec.js.map +1 -1
  76. package/lib/src/embed/liveboard.d.ts +11 -2
  77. package/lib/src/embed/liveboard.d.ts.map +1 -1
  78. package/lib/src/embed/liveboard.js +21 -7
  79. package/lib/src/embed/liveboard.js.map +1 -1
  80. package/lib/src/embed/liveboard.spec.js +185 -4
  81. package/lib/src/embed/liveboard.spec.js.map +1 -1
  82. package/lib/src/embed/sage.js.map +1 -1
  83. package/lib/src/embed/ts-embed.d.ts +22 -7
  84. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  85. package/lib/src/embed/ts-embed.js +75 -46
  86. package/lib/src/embed/ts-embed.js.map +1 -1
  87. package/lib/src/embed/ts-embed.spec.js +173 -1
  88. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  89. package/lib/src/types.d.ts +152 -44
  90. package/lib/src/types.d.ts.map +1 -1
  91. package/lib/src/types.js +139 -42
  92. package/lib/src/types.js.map +1 -1
  93. package/lib/src/utils/liveboardService/liveboardService.d.ts +21 -6
  94. package/lib/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  95. package/lib/src/utils/liveboardService/liveboardService.js +21 -6
  96. package/lib/src/utils/liveboardService/liveboardService.js.map +1 -1
  97. package/lib/src/visual-embed-sdk.d.ts +576 -58
  98. package/package.json +5 -4
  99. package/src/css-variables.ts +396 -1
  100. package/src/embed/app.spec.ts +17 -2
  101. package/src/embed/app.ts +8 -0
  102. package/src/embed/bodyless-conversation.ts +0 -1
  103. package/src/embed/conversation.spec.ts +131 -5
  104. package/src/embed/conversation.ts +89 -10
  105. package/src/embed/liveboard.spec.ts +236 -5
  106. package/src/embed/liveboard.ts +22 -7
  107. package/src/embed/sage.ts +1 -1
  108. package/src/embed/ts-embed.spec.ts +345 -113
  109. package/src/embed/ts-embed.ts +83 -56
  110. package/src/types.ts +199 -91
  111. package/src/utils/liveboardService/liveboardService.ts +21 -6
@@ -1,10 +1,10 @@
1
1
  import isUndefined from 'lodash/isUndefined';
2
2
  import { ERROR_MESSAGE } from '../errors';
3
- import { Param, BaseViewConfig } from '../types';
3
+ import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter } from '../types';
4
4
  import { TsEmbed } from './ts-embed';
5
- import { getQueryParamString } from '../utils';
5
+ import { getQueryParamString, getFilterQuery, getRuntimeParameters } from '../utils';
6
6
 
7
- /**
7
+ /**
8
8
  * Configuration for search options
9
9
  */
10
10
  export interface SearchOptions {
@@ -20,7 +20,8 @@ export interface SearchOptions {
20
20
  */
21
21
  export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAction'> {
22
22
  /**
23
- * The ID of the data source object. For example, Model, View, or Table. Spotter uses this object to query data and generate Answers.
23
+ * The ID of the data source object. For example, Model, View, or Table. Spotter uses
24
+ * this object to query data and generate Answers.
24
25
  */
25
26
  worksheetId: string;
26
27
  /**
@@ -30,7 +31,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
30
31
  /**
31
32
  * disableSourceSelection : Disables data source selection
32
33
  * but still display the selected data source.
33
- *
34
+ *
34
35
  * Supported embed types: `SpotterEmbed`
35
36
  * @example
36
37
  * ```js
@@ -44,7 +45,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
44
45
  disableSourceSelection?: boolean;
45
46
  /**
46
47
  * hideSourceSelection : Hide data source selection
47
- *
48
+ *
48
49
  * Supported embed types: `SpotterEmbed`
49
50
  * @example
50
51
  * ```js
@@ -58,7 +59,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
58
59
  hideSourceSelection?: boolean;
59
60
  /**
60
61
  * Flag to control Data panel experience
61
- *
62
+ *
62
63
  * Supported embed types: `SageEmbed`, `AppEmbed`, `SearchBarEmbed`, `LiveboardEmbed`, `SearchEmbed`
63
64
  * @default false
64
65
  * @version SDK: 1.36.0 | ThoughtSpot Cloud: 10.4.0.cl
@@ -76,7 +77,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
76
77
  * showSpotterLimitations : show limitation text
77
78
  * of the spotter underneath the chat input.
78
79
  * default is false.
79
- *
80
+ *
80
81
  * Supported embed types: `SpotterEmbed`
81
82
  * @example
82
83
  * ```js
@@ -91,7 +92,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
91
92
  /**
92
93
  * hideSampleQuestions : Hide sample questions on
93
94
  * the initial screen of the conversation.
94
- *
95
+ *
95
96
  * Supported embed types: `SpotterEmbed`
96
97
  * @example
97
98
  * ```js
@@ -103,6 +104,66 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
103
104
  * @version SDK: 1.36.0 | ThoughtSpot: 10.6.0.cl
104
105
  */
105
106
  hideSampleQuestions?: boolean;
107
+ /**
108
+ * The list of runtime filters to apply to a search Answer,
109
+ * visualization, or Liveboard.
110
+ *
111
+ * Supported embed types: `SpotterEmbed`
112
+ * @example
113
+ * ```js
114
+ * const embed = new SpotterEmbed('#tsEmbed', {
115
+ * // other embed view config
116
+ * runtimeFilters: [
117
+ * {
118
+ * columnName: 'color',
119
+ * operator: RuntimeFilterOp.EQ,
120
+ * values: ['red'],
121
+ * },
122
+ * ],
123
+ * })
124
+ * ```
125
+ * @version SDK: 1.41.0 | ThoughtSpot: 10.13.0.cl
126
+ */
127
+ runtimeFilters?: RuntimeFilter[];
128
+ /**
129
+ * Flag to control whether runtime filters should be included in the URL.
130
+ * If true, filters will be passed via app initialization payload instead.
131
+ * If false/undefined, filters will be added to URL (default behavior).
132
+ *
133
+ * Supported embed types: `SpotterEmbed`
134
+ * @default false
135
+ * @version SDK: 1.41.0 | ThoughtSpot: 10.13.0.cl
136
+ */
137
+ excludeRuntimeFiltersfromURL?: boolean;
138
+ /**
139
+ * The list of runtime parameters to apply to the conversation.
140
+ *
141
+ * Supported embed types: `SpotterEmbed`
142
+ * @example
143
+ * ```js
144
+ * const embed = new SpotterEmbed('#tsEmbed', {
145
+ * // other embed view config
146
+ * runtimeParameters: [
147
+ * {
148
+ * name: 'Integer Param',
149
+ * value: 10,
150
+ * },
151
+ * ],
152
+ * })
153
+ * ```
154
+ * @version SDK: 1.41.0 | ThoughtSpot: 10.13.0.cl
155
+ */
156
+ runtimeParameters?: RuntimeParameter[];
157
+ /**
158
+ * Flag to control whether runtime parameters should be included in the URL.
159
+ * If true, parameters will be passed via app initialization payload instead.
160
+ * If false/undefined, parameters will be added to URL (default behavior).
161
+ *
162
+ * Supported embed types: `SpotterEmbed`
163
+ * @default false
164
+ * @version SDK: 1.41.0 | ThoughtSpot: 10.13.0.cl
165
+ */
166
+ excludeRuntimeParametersfromURL?: boolean;
106
167
  }
107
168
 
108
169
  /**
@@ -144,6 +205,10 @@ export class SpotterEmbed extends TsEmbed {
144
205
  dataPanelV2,
145
206
  showSpotterLimitations,
146
207
  hideSampleQuestions,
208
+ runtimeFilters,
209
+ excludeRuntimeFiltersfromURL,
210
+ runtimeParameters,
211
+ excludeRuntimeParametersfromURL,
147
212
  } = this.viewConfig;
148
213
 
149
214
  if (!worksheetId) {
@@ -177,6 +242,10 @@ export class SpotterEmbed extends TsEmbed {
177
242
  const {
178
243
  worksheetId,
179
244
  searchOptions,
245
+ runtimeFilters,
246
+ excludeRuntimeFiltersfromURL,
247
+ runtimeParameters,
248
+ excludeRuntimeParametersfromURL,
180
249
  } = this.viewConfig;
181
250
  const path = 'insights/conv-assist';
182
251
  const queryParams = this.getEmbedParamsObject();
@@ -186,11 +255,21 @@ export class SpotterEmbed extends TsEmbed {
186
255
  if (queryParamsString) {
187
256
  query = `?${queryParamsString}`;
188
257
  }
258
+
259
+ const filterQuery = getFilterQuery(runtimeFilters || []);
260
+ if (filterQuery && !excludeRuntimeFiltersfromURL) {
261
+ query += `&${filterQuery}`;
262
+ }
263
+
264
+ const parameterQuery = getRuntimeParameters(runtimeParameters || []);
265
+ if (parameterQuery && !excludeRuntimeParametersfromURL) {
266
+ query += `&${parameterQuery}`;
267
+ }
268
+
189
269
  const tsPostHashParams = this.getThoughtSpotPostUrlParams({
190
270
  worksheet: worksheetId,
191
271
  query: searchOptions?.searchQuery || '',
192
272
  });
193
-
194
273
  return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
195
274
  }
196
275
 
@@ -642,7 +642,7 @@ describe('Liveboard/viz embed tests', () => {
642
642
  privileges: [],
643
643
  mixpanelToken: '1234567890',
644
644
  });
645
-
645
+
646
646
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
647
647
  ...defaultViewConfig,
648
648
  preRenderId: 'test',
@@ -721,6 +721,12 @@ describe('Liveboard/viz embed tests', () => {
721
721
  });
722
722
 
723
723
  describe('PreRender flow for liveboard embed', () => {
724
+ beforeAll(() => {
725
+ init({
726
+ thoughtSpotHost: "http://tshost",
727
+ authType: AuthType.None,
728
+ });
729
+ });
724
730
  test('it should preRender generic with liveboard id is not passed', async (done) => {
725
731
  const consoleSpy = jest.spyOn(console, 'error');
726
732
  const libEmbed = new LiveboardEmbed(getRootEl(), {
@@ -787,7 +793,7 @@ describe('Liveboard/viz embed tests', () => {
787
793
  });
788
794
  });
789
795
 
790
- test('it should navigateToLiveboard with liveboard id is not passed', async (done) => {
796
+ test('it should navigateToLiveboard with liveboard id is not passed with EmbedListenerReady event', async (done) => {
791
797
  mockMessageChannel();
792
798
  const consoleSpy = jest.spyOn(console, 'error');
793
799
  const testPreRenderId = 'testPreRender';
@@ -816,12 +822,19 @@ describe('Liveboard/viz embed tests', () => {
816
822
  libEmbed,
817
823
  );
818
824
 
825
+ await executeAfterWait(() => {
826
+ const iframe = getIFrameEl();
827
+ postMessageToParent(iframe.contentWindow, {
828
+ type: EmbedEvent.EmbedListenerReady,
829
+ });
830
+ });
831
+
819
832
  const testLiveboardId = 'testLiveboardId';
820
833
  const newLibEmbed = new LiveboardEmbed(getRootEl(), {
821
834
  preRenderId: testPreRenderId,
822
835
  liveboardId: testLiveboardId,
823
- activeTabId: 'tab1',
824
- vizId: 'viz1',
836
+ vizId: 'testVizId',
837
+ activeTabId: 'testActiveTabId',
825
838
  });
826
839
  const navigateToLiveboardSpy = jest.spyOn(newLibEmbed, 'navigateToLiveboard');
827
840
  await newLibEmbed.showPreRender();
@@ -832,7 +845,7 @@ describe('Liveboard/viz embed tests', () => {
832
845
  ) as HTMLIFrameElement;
833
846
 
834
847
  // should render the generic link
835
- expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'viz1', 'tab1', expect.any(Function));
848
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'testVizId', 'testActiveTabId');
836
849
  expect(iFrame.src).toMatch(/http:\/\/tshost\/.*&isLiveboardEmbed=true.*#$/);
837
850
 
838
851
  expect(consoleSpy).toHaveBeenCalledTimes(0);
@@ -840,6 +853,71 @@ describe('Liveboard/viz embed tests', () => {
840
853
  done();
841
854
  });
842
855
  });
856
+
857
+ test('it should navigateToLiveboard with liveboard id is not passed with AuthInit event', async (done) => {
858
+ mockMessageChannel();
859
+ const consoleSpy = jest.spyOn(console, 'error');
860
+ const testPreRenderId = 'testPreRender';
861
+ const libEmbed = new LiveboardEmbed(getRootEl(), {
862
+ preRenderId: testPreRenderId,
863
+ });
864
+
865
+ jest.spyOn(SessionInfoService, 'getSessionInfo').mockResolvedValue({
866
+ releaseVersion: '1.0.0',
867
+ userGUID: '1234567890',
868
+ currentOrgId: 1,
869
+ privileges: [],
870
+ mixpanelToken: '1234567890',
871
+ });
872
+ let resizeObserverCb: any;
873
+ (window as any).ResizeObserver =
874
+ window.ResizeObserver ||
875
+ jest.fn().mockImplementation((resizeObserverCbParam: any) => {
876
+ resizeObserverCb = resizeObserverCbParam;
877
+ return {
878
+ disconnect: jest.fn(),
879
+ observe: jest.fn(),
880
+ unobserve: jest.fn(),
881
+ };
882
+ });
883
+ await libEmbed.preRender();
884
+ await waitFor(() => !!getIFrameEl());
885
+ const ts = '__tsEmbed';
886
+ expect((document.getElementById(libEmbed.getPreRenderIds().wrapper) as any)[ts]).toEqual(
887
+ libEmbed,
888
+ );
889
+ const testLiveboardId = 'testLiveboardId';
890
+ const newLibEmbed = new LiveboardEmbed(getRootEl(), {
891
+ preRenderId: testPreRenderId,
892
+ liveboardId: testLiveboardId,
893
+ vizId: 'testVizId',
894
+ activeTabId: 'testActiveTabId',
895
+ });
896
+ const navigateToLiveboardSpy = jest.spyOn(newLibEmbed, 'navigateToLiveboard');
897
+
898
+ await newLibEmbed.showPreRender();
899
+
900
+ await executeAfterWait(() => {
901
+ const iFrame = document.getElementById(
902
+ newLibEmbed.getPreRenderIds().child,
903
+ ) as HTMLIFrameElement;
904
+ postMessageToParent(iFrame.contentWindow, {
905
+ type: EmbedEvent.AuthInit,
906
+ });
907
+ });
908
+
909
+
910
+ await executeAfterWait(() => {
911
+ const iFrame = document.getElementById(
912
+ libEmbed.getPreRenderIds().child,
913
+ ) as HTMLIFrameElement;
914
+ // should render the generic link
915
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'testVizId', 'testActiveTabId');
916
+ expect(iFrame.src).toMatch(/http:\/\/tshost\/.*&isLiveboardEmbed=true.*#$/);
917
+ expect(consoleSpy).toHaveBeenCalledTimes(0);
918
+ done();
919
+ }, 1005);
920
+ });
843
921
  });
844
922
 
845
923
  describe('LazyLoadingForFullHeight functionality', () => {
@@ -1113,4 +1191,157 @@ describe('Liveboard/viz embed tests', () => {
1113
1191
  });
1114
1192
  });
1115
1193
  });
1194
+
1195
+ describe('Liveboard Embed Container Loading and PreRender', () => {
1196
+ beforeEach(() => {
1197
+ document.body.innerHTML = getDocumentBody();
1198
+ });
1199
+
1200
+ test('should call navigateToLiveboard after embed container is loaded in beforePrerenderVisible', async () => {
1201
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1202
+ liveboardId,
1203
+ vizId,
1204
+ activeTabId,
1205
+ ...defaultViewConfig,
1206
+ });
1207
+
1208
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1209
+
1210
+ // Mock embed container as not loaded initially
1211
+ liveboardEmbed.isEmbedContainerLoaded = false;
1212
+
1213
+ // Call beforePrerenderVisible
1214
+ liveboardEmbed['beforePrerenderVisible']();
1215
+
1216
+ // navigateToLiveboard should not be called immediately
1217
+ expect(navigateToLiveboardSpy).not.toHaveBeenCalled();
1218
+
1219
+ // Simulate embed container becoming ready
1220
+ liveboardEmbed.isEmbedContainerLoaded = true;
1221
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1222
+
1223
+ // Now navigateToLiveboard should be called
1224
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1225
+ });
1226
+
1227
+ test('should update currentLiveboardState for prerender object when embed container loads', async () => {
1228
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1229
+ liveboardId,
1230
+ vizId,
1231
+ activeTabId,
1232
+ ...defaultViewConfig,
1233
+ });
1234
+
1235
+ const mockPreRenderObj = {
1236
+ currentLiveboardState: {},
1237
+ };
1238
+
1239
+ jest.spyOn(liveboardEmbed as any, 'getPreRenderObj').mockReturnValue(mockPreRenderObj as any);
1240
+ jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1241
+
1242
+ // Mock embed container as not loaded initially
1243
+ liveboardEmbed.isEmbedContainerLoaded = false;
1244
+
1245
+ // Call beforePrerenderVisible
1246
+ liveboardEmbed['beforePrerenderVisible']();
1247
+
1248
+ // Simulate embed container becoming ready
1249
+ liveboardEmbed.isEmbedContainerLoaded = true;
1250
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1251
+
1252
+ // Check that currentLiveboardState was updated
1253
+ expect(mockPreRenderObj.currentLiveboardState).toEqual({
1254
+ liveboardId,
1255
+ vizId,
1256
+ activeTabId,
1257
+ });
1258
+ });
1259
+
1260
+ test('should handle beforePrerenderVisible when embed container is already loaded', async () => {
1261
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1262
+ liveboardId,
1263
+ vizId,
1264
+ activeTabId,
1265
+ ...defaultViewConfig,
1266
+ });
1267
+
1268
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1269
+
1270
+ // Mock embed container as already loaded
1271
+ liveboardEmbed.isEmbedContainerLoaded = true;
1272
+
1273
+ // Call beforePrerenderVisible
1274
+ liveboardEmbed['beforePrerenderVisible']();
1275
+
1276
+ // navigateToLiveboard should be called immediately
1277
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1278
+ });
1279
+
1280
+ test('should handle beforePrerenderVisible without prerender object', async () => {
1281
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1282
+ liveboardId,
1283
+ vizId,
1284
+ activeTabId,
1285
+ ...defaultViewConfig,
1286
+ });
1287
+
1288
+ jest.spyOn(liveboardEmbed as any, 'getPreRenderObj').mockReturnValue(null);
1289
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1290
+
1291
+ // Mock embed container as not loaded initially
1292
+ liveboardEmbed.isEmbedContainerLoaded = false;
1293
+
1294
+ // Call beforePrerenderVisible
1295
+ liveboardEmbed['beforePrerenderVisible']();
1296
+
1297
+ // Simulate embed container becoming ready
1298
+ liveboardEmbed.isEmbedContainerLoaded = true;
1299
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1300
+
1301
+ // navigateToLiveboard should still be called
1302
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1303
+ });
1304
+
1305
+ test('should work with all liveboard parameters', async () => {
1306
+ const customLiveboardId = 'custom-liveboard-id';
1307
+ const customVizId = 'custom-viz-id';
1308
+ const customActiveTabId = 'custom-active-tab-id';
1309
+
1310
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1311
+ liveboardId: customLiveboardId,
1312
+ vizId: customVizId,
1313
+ activeTabId: customActiveTabId,
1314
+ ...defaultViewConfig,
1315
+ });
1316
+
1317
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1318
+
1319
+ // Mock embed container as already loaded
1320
+ liveboardEmbed.isEmbedContainerLoaded = true;
1321
+
1322
+ // Call beforePrerenderVisible
1323
+ liveboardEmbed['beforePrerenderVisible']();
1324
+
1325
+ // Check that all parameters are passed correctly
1326
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(customLiveboardId, customVizId, customActiveTabId);
1327
+ });
1328
+
1329
+ test('should work with minimal liveboard parameters', async () => {
1330
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1331
+ liveboardId,
1332
+ ...defaultViewConfig,
1333
+ });
1334
+
1335
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1336
+
1337
+ // Mock embed container as already loaded
1338
+ liveboardEmbed.isEmbedContainerLoaded = true;
1339
+
1340
+ // Call beforePrerenderVisible
1341
+ liveboardEmbed['beforePrerenderVisible']();
1342
+
1343
+ // Check that undefined parameters are passed correctly
1344
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, undefined, undefined);
1345
+ });
1346
+ });
1116
1347
  });
@@ -674,12 +674,29 @@ export class LiveboardEmbed extends V1Embed {
674
674
  }
675
675
  }
676
676
 
677
+ /**
678
+ * @hidden
679
+ * Internal state to track the current liveboard id.
680
+ * This is used to navigate to the correct liveboard when the prerender is visible.
681
+ */
682
+ public currentLiveboardState = {
683
+ liveboardId: this.viewConfig.liveboardId,
684
+ vizId: this.viewConfig.vizId,
685
+ activeTabId: this.viewConfig.activeTabId,
686
+ };
687
+
677
688
  protected beforePrerenderVisible(): void {
678
689
  const embedObj = this.getPreRenderObj<LiveboardEmbed>();
679
690
 
680
- const libId = this.currentLiveboardId;
681
- this.navigateToLiveboard(libId, this.viewConfig.vizId, this.viewConfig.activeTabId, () => {
682
- if (embedObj) embedObj.currentLiveboardId = libId;
691
+ this.executeAfterEmbedContainerLoaded(() => {
692
+ this.navigateToLiveboard(this.viewConfig.liveboardId, this.viewConfig.vizId, this.viewConfig.activeTabId);
693
+ if (embedObj) {
694
+ embedObj.currentLiveboardState = {
695
+ liveboardId: this.viewConfig.liveboardId,
696
+ vizId: this.viewConfig.vizId,
697
+ activeTabId: this.viewConfig.activeTabId,
698
+ };
699
+ }
683
700
  });
684
701
  }
685
702
 
@@ -754,15 +771,13 @@ export class LiveboardEmbed extends V1Embed {
754
771
  return this;
755
772
  }
756
773
 
757
- public currentLiveboardId: string = this.viewConfig.liveboardId;
758
-
759
- public navigateToLiveboard(liveboardId: string, vizId?: string, activeTabId?: string, onNavigateCalled?: () => void) {
774
+ public navigateToLiveboard(liveboardId: string, vizId?: string, activeTabId?: string) {
760
775
  const path = this.getIframeSuffixSrc(liveboardId, vizId, activeTabId);
761
776
  this.viewConfig.liveboardId = liveboardId;
762
777
  this.viewConfig.activeTabId = activeTabId;
763
778
  this.viewConfig.vizId = vizId;
764
779
  if (this.isRendered) {
765
- this.triggerAfterLoad(HostEvent.Navigate, path.substring(1), onNavigateCalled);
780
+ this.trigger(HostEvent.Navigate, path.substring(1));
766
781
  } else if (this.viewConfig.preRenderId) {
767
782
  this.preRender(true);
768
783
  } else {
package/src/embed/sage.ts CHANGED
@@ -199,7 +199,7 @@ export class SageEmbed extends V1Embed {
199
199
  */
200
200
  public getIFrameSrc(): string {
201
201
  const path = 'eureka';
202
- const postHashObj = {};
202
+ const postHashObj: Record<string, any> = {};
203
203
  const tsPostHashParams = this.getThoughtSpotPostUrlParams();
204
204
  const {
205
205
  dataSource, searchOptions,