@thoughtspot/visual-embed-sdk 1.40.1-alpha.2 → 1.40.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 (155) hide show
  1. package/cjs/package.json +7 -6
  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 +6 -1
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +22 -0
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +39 -2
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.d.ts +0 -1
  11. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.js +3 -7
  13. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.d.ts +63 -3
  15. package/cjs/src/embed/conversation.d.ts.map +1 -1
  16. package/cjs/src/embed/conversation.js +11 -8
  17. package/cjs/src/embed/conversation.js.map +1 -1
  18. package/cjs/src/embed/conversation.spec.js +102 -0
  19. package/cjs/src/embed/conversation.spec.js.map +1 -1
  20. package/cjs/src/embed/liveboard.d.ts +11 -3
  21. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  22. package/cjs/src/embed/liveboard.js +23 -33
  23. package/cjs/src/embed/liveboard.js.map +1 -1
  24. package/cjs/src/embed/liveboard.spec.js +182 -29
  25. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  26. package/cjs/src/embed/sage.d.ts +0 -1
  27. package/cjs/src/embed/sage.d.ts.map +1 -1
  28. package/cjs/src/embed/sage.js +6 -10
  29. package/cjs/src/embed/sage.js.map +1 -1
  30. package/cjs/src/embed/search-bar.d.ts +0 -1
  31. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  32. package/cjs/src/embed/search-bar.js +7 -11
  33. package/cjs/src/embed/search-bar.js.map +1 -1
  34. package/cjs/src/embed/search.d.ts +0 -1
  35. package/cjs/src/embed/search.d.ts.map +1 -1
  36. package/cjs/src/embed/search.js +8 -7
  37. package/cjs/src/embed/search.js.map +1 -1
  38. package/cjs/src/embed/ts-embed.d.ts +22 -9
  39. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  40. package/cjs/src/embed/ts-embed.js +75 -59
  41. package/cjs/src/embed/ts-embed.js.map +1 -1
  42. package/cjs/src/embed/ts-embed.spec.js +173 -1
  43. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  44. package/cjs/src/types.d.ts +154 -54
  45. package/cjs/src/types.d.ts.map +1 -1
  46. package/cjs/src/types.js +140 -52
  47. package/cjs/src/types.js.map +1 -1
  48. package/cjs/src/utils/liveboardService/liveboardService.d.ts +21 -6
  49. package/cjs/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  50. package/cjs/src/utils/liveboardService/liveboardService.js +21 -6
  51. package/cjs/src/utils/liveboardService/liveboardService.js.map +1 -1
  52. package/dist/{index-CmEQfuE3.js → index-P5YjBOuJ.js} +1 -1
  53. package/dist/src/css-variables.d.ts +316 -0
  54. package/dist/src/css-variables.d.ts.map +1 -1
  55. package/dist/src/embed/app.d.ts +6 -1
  56. package/dist/src/embed/app.d.ts.map +1 -1
  57. package/dist/src/embed/bodyless-conversation.d.ts +0 -1
  58. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  59. package/dist/src/embed/conversation.d.ts +63 -3
  60. package/dist/src/embed/conversation.d.ts.map +1 -1
  61. package/dist/src/embed/liveboard.d.ts +11 -3
  62. package/dist/src/embed/liveboard.d.ts.map +1 -1
  63. package/dist/src/embed/sage.d.ts +0 -1
  64. package/dist/src/embed/sage.d.ts.map +1 -1
  65. package/dist/src/embed/search-bar.d.ts +0 -1
  66. package/dist/src/embed/search-bar.d.ts.map +1 -1
  67. package/dist/src/embed/search.d.ts +0 -1
  68. package/dist/src/embed/search.d.ts.map +1 -1
  69. package/dist/src/embed/ts-embed.d.ts +22 -9
  70. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  71. package/dist/src/types.d.ts +154 -54
  72. package/dist/src/types.d.ts.map +1 -1
  73. package/dist/src/utils/liveboardService/liveboardService.d.ts +21 -6
  74. package/dist/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  75. package/dist/tsembed-react.es.js +298 -190
  76. package/dist/tsembed-react.js +297 -189
  77. package/dist/tsembed.es.js +319 -196
  78. package/dist/tsembed.js +318 -195
  79. package/dist/visual-embed-sdk-react-full.d.ts +583 -76
  80. package/dist/visual-embed-sdk-react.d.ts +583 -76
  81. package/dist/visual-embed-sdk.d.ts +583 -76
  82. package/lib/package.json +7 -6
  83. package/lib/src/css-variables.d.ts +316 -0
  84. package/lib/src/css-variables.d.ts.map +1 -1
  85. package/lib/src/embed/app.d.ts +6 -1
  86. package/lib/src/embed/app.d.ts.map +1 -1
  87. package/lib/src/embed/app.js +22 -0
  88. package/lib/src/embed/app.js.map +1 -1
  89. package/lib/src/embed/app.spec.js +39 -2
  90. package/lib/src/embed/app.spec.js.map +1 -1
  91. package/lib/src/embed/bodyless-conversation.d.ts +0 -1
  92. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  93. package/lib/src/embed/bodyless-conversation.js +3 -7
  94. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  95. package/lib/src/embed/conversation.d.ts +63 -3
  96. package/lib/src/embed/conversation.d.ts.map +1 -1
  97. package/lib/src/embed/conversation.js +12 -9
  98. package/lib/src/embed/conversation.js.map +1 -1
  99. package/lib/src/embed/conversation.spec.js +104 -2
  100. package/lib/src/embed/conversation.spec.js.map +1 -1
  101. package/lib/src/embed/liveboard.d.ts +11 -3
  102. package/lib/src/embed/liveboard.d.ts.map +1 -1
  103. package/lib/src/embed/liveboard.js +23 -33
  104. package/lib/src/embed/liveboard.js.map +1 -1
  105. package/lib/src/embed/liveboard.spec.js +182 -29
  106. package/lib/src/embed/liveboard.spec.js.map +1 -1
  107. package/lib/src/embed/sage.d.ts +0 -1
  108. package/lib/src/embed/sage.d.ts.map +1 -1
  109. package/lib/src/embed/sage.js +6 -10
  110. package/lib/src/embed/sage.js.map +1 -1
  111. package/lib/src/embed/search-bar.d.ts +0 -1
  112. package/lib/src/embed/search-bar.d.ts.map +1 -1
  113. package/lib/src/embed/search-bar.js +7 -11
  114. package/lib/src/embed/search-bar.js.map +1 -1
  115. package/lib/src/embed/search.d.ts +0 -1
  116. package/lib/src/embed/search.d.ts.map +1 -1
  117. package/lib/src/embed/search.js +8 -7
  118. package/lib/src/embed/search.js.map +1 -1
  119. package/lib/src/embed/ts-embed.d.ts +22 -9
  120. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  121. package/lib/src/embed/ts-embed.js +75 -59
  122. package/lib/src/embed/ts-embed.js.map +1 -1
  123. package/lib/src/embed/ts-embed.spec.js +173 -1
  124. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  125. package/lib/src/types.d.ts +154 -54
  126. package/lib/src/types.d.ts.map +1 -1
  127. package/lib/src/types.js +140 -52
  128. package/lib/src/types.js.map +1 -1
  129. package/lib/src/utils/liveboardService/liveboardService.d.ts +21 -6
  130. package/lib/src/utils/liveboardService/liveboardService.d.ts.map +1 -1
  131. package/lib/src/utils/liveboardService/liveboardService.js +21 -6
  132. package/lib/src/utils/liveboardService/liveboardService.js.map +1 -1
  133. package/lib/src/visual-embed-sdk.d.ts +584 -77
  134. package/package.json +7 -6
  135. package/src/css-variables.ts +396 -1
  136. package/src/embed/app.spec.ts +54 -2
  137. package/src/embed/app.ts +24 -0
  138. package/src/embed/bodyless-conversation.ts +3 -9
  139. package/src/embed/conversation.spec.ts +131 -5
  140. package/src/embed/conversation.ts +87 -23
  141. package/src/embed/liveboard.spec.ts +233 -32
  142. package/src/embed/liveboard.ts +24 -39
  143. package/src/embed/sage.ts +6 -11
  144. package/src/embed/search-bar.tsx +7 -14
  145. package/src/embed/search.ts +7 -18
  146. package/src/embed/ts-embed.spec.ts +344 -112
  147. package/src/embed/ts-embed.ts +82 -70
  148. package/src/types.ts +153 -54
  149. package/src/utils/liveboardService/liveboardService.ts +21 -6
  150. package/dist/index-D1pyb7RG.js +0 -7371
  151. package/dist/index-DeFzsyFF.js +0 -7371
  152. package/dist/index-Dpf0rd6w.js +0 -7371
  153. package/dist/index-UuEbsISo.js +0 -7447
  154. package/dist/index-e3Uw3YFO.js +0 -7371
  155. package/dist/index-k7pkZMhx.js +0 -7371
@@ -1,10 +1,8 @@
1
- import {
2
- SpotterEmbed,
3
- SpotterEmbedViewConfig,
4
- } from './conversation';
1
+ import { SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed } from './conversation';
2
+ import { TsEmbed } from './ts-embed';
5
3
  import * as authInstance from '../auth';
6
4
  import { Action, init } from '../index';
7
- import { AuthType, Param } from '../types';
5
+ import { AuthType, Param, RuntimeFilterOp } from '../types';
8
6
  import {
9
7
  getDocumentBody,
10
8
  getIFrameSrc,
@@ -180,4 +178,132 @@ describe('ConversationEmbed', () => {
180
178
  `http://${thoughtSpotHost}/v2/?${defaultParams}&${Param.DisableActions}=[%22${Action.InConversationTraining}%22]&${Param.DisableActionReason}=${disabledReason}&isSpotterExperienceEnabled=true&enableDataPanelV2=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
181
179
  );
182
180
  });
181
+
182
+ it('should render the conversation embed with runtime filters', async () => {
183
+ const viewConfig: SpotterEmbedViewConfig = {
184
+ worksheetId: 'worksheetId',
185
+ searchOptions: {
186
+ searchQuery: 'searchQuery',
187
+ },
188
+ runtimeFilters: [
189
+ {
190
+ columnName: 'revenue',
191
+ operator: RuntimeFilterOp.EQ,
192
+ values: [1000],
193
+ },
194
+ ],
195
+ };
196
+
197
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
198
+ await conversationEmbed.render();
199
+ expectUrlMatchesWithParams(
200
+ getIFrameSrc(),
201
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&col1=revenue&op1=EQ&val1=1000#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
202
+ );
203
+ });
204
+
205
+ it('should render the conversation embed with runtime parameters', async () => {
206
+ const viewConfig: SpotterEmbedViewConfig = {
207
+ worksheetId: 'worksheetId',
208
+ searchOptions: {
209
+ searchQuery: 'searchQuery',
210
+ },
211
+ runtimeParameters: [
212
+ {
213
+ name: 'Date Range',
214
+ value: '30',
215
+ },
216
+ ],
217
+ };
218
+
219
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
220
+ await conversationEmbed.render();
221
+ expectUrlMatchesWithParams(
222
+ getIFrameSrc(),
223
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&param1=Date%20Range&paramVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
224
+ );
225
+ });
226
+
227
+ it('should render the conversation embed with runtime parameters excluded from URL', async () => {
228
+ const viewConfig: SpotterEmbedViewConfig = {
229
+ worksheetId: 'worksheetId',
230
+ searchOptions: {
231
+ searchQuery: 'searchQuery',
232
+ },
233
+ runtimeParameters: [
234
+ {
235
+ name: 'Date Range',
236
+ value: '30',
237
+ },
238
+ {
239
+ name: 'Region',
240
+ value: 'North America',
241
+ },
242
+ ],
243
+ excludeRuntimeParametersfromURL: true,
244
+ };
245
+
246
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
247
+ await conversationEmbed.render();
248
+ expectUrlMatchesWithParams(
249
+ getIFrameSrc(),
250
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
251
+ );
252
+ });
253
+
254
+ it('should render the conversation embed with both runtime filters and parameters', async () => {
255
+ const viewConfig: SpotterEmbedViewConfig = {
256
+ worksheetId: 'worksheetId',
257
+ searchOptions: {
258
+ searchQuery: 'searchQuery',
259
+ },
260
+ runtimeParameters: [
261
+ {
262
+ name: 'Date Range',
263
+ value: '30',
264
+ },
265
+ ],
266
+ runtimeFilters: [
267
+ {
268
+ columnName: 'revenue',
269
+ operator: RuntimeFilterOp.EQ,
270
+ values: [1000],
271
+ },
272
+ ],
273
+ excludeRuntimeParametersfromURL: false,
274
+ excludeRuntimeFiltersfromURL: false,
275
+ };
276
+
277
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
278
+ await conversationEmbed.render();
279
+ expectUrlMatchesWithParams(
280
+ getIFrameSrc(),
281
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&col1=revenue&op1=EQ&val1=1000&param1=Date%20Range&paramVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
282
+ );
283
+ });
284
+
285
+ it('should ensure deprecated ConversationEmbed class maintains same functionality as SpotterEmbed', async () => {
286
+ const viewConfig: SpotterEmbedViewConfig = {
287
+ worksheetId: 'worksheetId',
288
+ searchOptions: {
289
+ searchQuery: 'searchQuery',
290
+ },
291
+ runtimeParameters: [
292
+ {
293
+ name: 'Date Range',
294
+ value: '30',
295
+ },
296
+ ],
297
+ };
298
+
299
+ // Test with deprecated class
300
+ const conversationEmbed = new ConversationEmbed(getRootEl(), viewConfig);
301
+ await conversationEmbed.render();
302
+
303
+ // Verify it generates the same URL structure as SpotterEmbed
304
+ expectUrlMatchesWithParams(
305
+ getIFrameSrc(),
306
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&param1=Date%20Range&paramVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
307
+ );
308
+ });
183
309
  });
@@ -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
  /**
@@ -135,7 +196,7 @@ export class SpotterEmbed extends TsEmbed {
135
196
  super(container, viewConfig);
136
197
  }
137
198
 
138
- protected getEmbedParamsObject() {
199
+ public getIframeSrc(): string {
139
200
  const {
140
201
  worksheetId,
141
202
  searchOptions,
@@ -144,8 +205,12 @@ 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
+ const path = 'insights/conv-assist';
149
214
  if (!worksheetId) {
150
215
  this.handleError(ERROR_MESSAGE.SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND);
151
216
  }
@@ -170,27 +235,26 @@ export class SpotterEmbed extends TsEmbed {
170
235
  queryParams[Param.HideSampleQuestions] = !!hideSampleQuestions;
171
236
  }
172
237
 
173
- return queryParams;
174
- }
175
-
176
- public getIframeSrc(): string {
177
- const {
178
- worksheetId,
179
- searchOptions,
180
- } = this.viewConfig;
181
- const path = 'insights/conv-assist';
182
- const queryParams = this.getEmbedParamsObject();
183
-
184
238
  let query = '';
185
239
  const queryParamsString = getQueryParamString(queryParams, true);
186
240
  if (queryParamsString) {
187
241
  query = `?${queryParamsString}`;
188
242
  }
243
+
244
+ const filterQuery = getFilterQuery(runtimeFilters || []);
245
+ if (filterQuery && !excludeRuntimeFiltersfromURL) {
246
+ query += `&${filterQuery}`;
247
+ }
248
+
249
+ const parameterQuery = getRuntimeParameters(runtimeParameters || []);
250
+ if (parameterQuery && !excludeRuntimeParametersfromURL) {
251
+ query += `&${parameterQuery}`;
252
+ }
253
+
189
254
  const tsPostHashParams = this.getThoughtSpotPostUrlParams({
190
255
  worksheet: worksheetId,
191
256
  query: searchOptions?.searchQuery || '',
192
257
  });
193
-
194
258
  return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
195
259
  }
196
260
 
@@ -601,14 +601,6 @@ describe('Liveboard/viz embed tests', () => {
601
601
 
602
602
  test('navigateToLiveboard should trigger the navigate event with the correct path', async (done) => {
603
603
  mockMessageChannel();
604
- // mock getSessionInfo
605
- jest.spyOn(SessionInfoService, 'getSessionInfo').mockResolvedValue({
606
- releaseVersion: '1.0.0',
607
- userGUID: '1234567890',
608
- currentOrgId: 1,
609
- privileges: [],
610
- mixpanelToken: '1234567890',
611
- });
612
604
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
613
605
  ...defaultViewConfig,
614
606
  } as LiveboardViewConfig);
@@ -619,30 +611,16 @@ describe('Liveboard/viz embed tests', () => {
619
611
  postMessageToParent(iframe.contentWindow, {
620
612
  type: EmbedEvent.APP_INIT,
621
613
  });
622
- postMessageToParent(iframe.contentWindow, {
623
- type: EmbedEvent.AuthInit,
624
- });
625
- liveboardEmbed.navigateToLiveboard('lb1', 'viz1');
626
614
  });
627
-
628
615
  executeAfterWait(() => {
616
+ liveboardEmbed.navigateToLiveboard('lb1', 'viz1');
629
617
  expect(onSpy).toHaveBeenCalledWith(HostEvent.Navigate, 'embed/viz/lb1/viz1');
630
618
  done();
631
- }, 1002);
619
+ });
632
620
  });
633
621
 
634
622
  test('navigateToLiveboard with preRender', async (done) => {
635
623
  mockMessageChannel();
636
-
637
- // mock getSessionInfo
638
- jest.spyOn(SessionInfoService, 'getSessionInfo').mockResolvedValue({
639
- releaseVersion: '1.0.0',
640
- userGUID: '1234567890',
641
- currentOrgId: 1,
642
- privileges: [],
643
- mixpanelToken: '1234567890',
644
- });
645
-
646
624
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
647
625
  ...defaultViewConfig,
648
626
  preRenderId: 'test',
@@ -654,15 +632,12 @@ describe('Liveboard/viz embed tests', () => {
654
632
  postMessageToParent(iframe.contentWindow, {
655
633
  type: EmbedEvent.APP_INIT,
656
634
  });
657
- postMessageToParent(iframe.contentWindow, {
658
- type: EmbedEvent.AuthInit,
659
- });
660
635
  });
661
636
  executeAfterWait(() => {
662
637
  liveboardEmbed.navigateToLiveboard('lb1', 'viz1');
663
638
  expect(onSpy).toHaveBeenCalledWith(HostEvent.Navigate, 'embed/viz/lb1/viz1');
664
639
  done();
665
- }, 1002);
640
+ });
666
641
  });
667
642
  test('should set runtime parametere values in url params', async () => {
668
643
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
@@ -787,7 +762,7 @@ describe('Liveboard/viz embed tests', () => {
787
762
  });
788
763
  });
789
764
 
790
- test('it should navigateToLiveboard with liveboard id is not passed', async (done) => {
765
+ test('it should navigateToLiveboard with liveboard id is not passed with EmbedListenerReady event', async (done) => {
791
766
  mockMessageChannel();
792
767
  const consoleSpy = jest.spyOn(console, 'error');
793
768
  const testPreRenderId = 'testPreRender';
@@ -816,12 +791,19 @@ describe('Liveboard/viz embed tests', () => {
816
791
  libEmbed,
817
792
  );
818
793
 
794
+ await executeAfterWait(() => {
795
+ const iframe = getIFrameEl();
796
+ postMessageToParent(iframe.contentWindow, {
797
+ type: EmbedEvent.EmbedListenerReady,
798
+ });
799
+ });
800
+
819
801
  const testLiveboardId = 'testLiveboardId';
820
802
  const newLibEmbed = new LiveboardEmbed(getRootEl(), {
821
803
  preRenderId: testPreRenderId,
822
804
  liveboardId: testLiveboardId,
823
- activeTabId: 'tab1',
824
- vizId: 'viz1',
805
+ vizId: 'testVizId',
806
+ activeTabId: 'testActiveTabId',
825
807
  });
826
808
  const navigateToLiveboardSpy = jest.spyOn(newLibEmbed, 'navigateToLiveboard');
827
809
  await newLibEmbed.showPreRender();
@@ -832,7 +814,7 @@ describe('Liveboard/viz embed tests', () => {
832
814
  ) as HTMLIFrameElement;
833
815
 
834
816
  // should render the generic link
835
- expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'viz1', 'tab1', expect.any(Function));
817
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'testVizId', 'testActiveTabId');
836
818
  expect(iFrame.src).toMatch(/http:\/\/tshost\/.*&isLiveboardEmbed=true.*#$/);
837
819
 
838
820
  expect(consoleSpy).toHaveBeenCalledTimes(0);
@@ -840,6 +822,72 @@ describe('Liveboard/viz embed tests', () => {
840
822
  done();
841
823
  });
842
824
  });
825
+
826
+ test('it should navigateToLiveboard with liveboard id is not passed with AuthInit event', async (done) => {
827
+ mockMessageChannel();
828
+ const consoleSpy = jest.spyOn(console, 'error');
829
+ const testPreRenderId = 'testPreRender';
830
+ const libEmbed = new LiveboardEmbed(getRootEl(), {
831
+ preRenderId: testPreRenderId,
832
+ });
833
+
834
+ jest.spyOn(SessionInfoService, 'getSessionInfo').mockResolvedValue({
835
+ releaseVersion: '1.0.0',
836
+ userGUID: '1234567890',
837
+ currentOrgId: 1,
838
+ privileges: [],
839
+ mixpanelToken: '1234567890',
840
+ });
841
+ let resizeObserverCb: any;
842
+ (window as any).ResizeObserver =
843
+ window.ResizeObserver ||
844
+ jest.fn().mockImplementation((resizeObserverCbParam: any) => {
845
+ resizeObserverCb = resizeObserverCbParam;
846
+ return {
847
+ disconnect: jest.fn(),
848
+ observe: jest.fn(),
849
+ unobserve: jest.fn(),
850
+ };
851
+ });
852
+ await libEmbed.preRender();
853
+ await waitFor(() => !!getIFrameEl());
854
+ const ts = '__tsEmbed';
855
+ expect((document.getElementById(libEmbed.getPreRenderIds().wrapper) as any)[ts]).toEqual(
856
+ libEmbed,
857
+ );
858
+ const testLiveboardId = 'testLiveboardId';
859
+ const newLibEmbed = new LiveboardEmbed(getRootEl(), {
860
+ preRenderId: testPreRenderId,
861
+ liveboardId: testLiveboardId,
862
+ vizId: 'testVizId',
863
+ activeTabId: 'testActiveTabId',
864
+ });
865
+ const navigateToLiveboardSpy = jest.spyOn(newLibEmbed, 'navigateToLiveboard');
866
+
867
+ await newLibEmbed.showPreRender();
868
+
869
+ await executeAfterWait(() => {
870
+ const iFrame = document.getElementById(
871
+ newLibEmbed.getPreRenderIds().child,
872
+ ) as HTMLIFrameElement;
873
+ postMessageToParent(iFrame.contentWindow, {
874
+ type: EmbedEvent.AuthInit,
875
+ });
876
+ });
877
+
878
+
879
+ await executeAfterWait(() => {
880
+ const iFrame = document.getElementById(
881
+ libEmbed.getPreRenderIds().child,
882
+ ) as HTMLIFrameElement;
883
+ // should render the generic link
884
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(testLiveboardId, 'testVizId', 'testActiveTabId');
885
+ expect(iFrame.src).toMatch(/http:\/\/tshost\/.*&isLiveboardEmbed=true.*#$/);
886
+ expect(consoleSpy).toHaveBeenCalledTimes(0);
887
+ done();
888
+ }, 1005);
889
+ });
890
+
843
891
  });
844
892
 
845
893
  describe('LazyLoadingForFullHeight functionality', () => {
@@ -1113,4 +1161,157 @@ describe('Liveboard/viz embed tests', () => {
1113
1161
  });
1114
1162
  });
1115
1163
  });
1164
+
1165
+ describe('Liveboard Embed Container Loading and PreRender', () => {
1166
+ beforeEach(() => {
1167
+ document.body.innerHTML = getDocumentBody();
1168
+ });
1169
+
1170
+ test('should call navigateToLiveboard after embed container is loaded in beforePrerenderVisible', async () => {
1171
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1172
+ liveboardId,
1173
+ vizId,
1174
+ activeTabId,
1175
+ ...defaultViewConfig,
1176
+ });
1177
+
1178
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1179
+
1180
+ // Mock embed container as not loaded initially
1181
+ liveboardEmbed.isEmbedContainerLoaded = false;
1182
+
1183
+ // Call beforePrerenderVisible
1184
+ liveboardEmbed['beforePrerenderVisible']();
1185
+
1186
+ // navigateToLiveboard should not be called immediately
1187
+ expect(navigateToLiveboardSpy).not.toHaveBeenCalled();
1188
+
1189
+ // Simulate embed container becoming ready
1190
+ liveboardEmbed.isEmbedContainerLoaded = true;
1191
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1192
+
1193
+ // Now navigateToLiveboard should be called
1194
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1195
+ });
1196
+
1197
+ test('should update currentLiveboardState for prerender object when embed container loads', async () => {
1198
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1199
+ liveboardId,
1200
+ vizId,
1201
+ activeTabId,
1202
+ ...defaultViewConfig,
1203
+ });
1204
+
1205
+ const mockPreRenderObj = {
1206
+ currentLiveboardState: {},
1207
+ };
1208
+
1209
+ jest.spyOn(liveboardEmbed as any, 'getPreRenderObj').mockReturnValue(mockPreRenderObj as any);
1210
+ jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1211
+
1212
+ // Mock embed container as not loaded initially
1213
+ liveboardEmbed.isEmbedContainerLoaded = false;
1214
+
1215
+ // Call beforePrerenderVisible
1216
+ liveboardEmbed['beforePrerenderVisible']();
1217
+
1218
+ // Simulate embed container becoming ready
1219
+ liveboardEmbed.isEmbedContainerLoaded = true;
1220
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1221
+
1222
+ // Check that currentLiveboardState was updated
1223
+ expect(mockPreRenderObj.currentLiveboardState).toEqual({
1224
+ liveboardId,
1225
+ vizId,
1226
+ activeTabId,
1227
+ });
1228
+ });
1229
+
1230
+ test('should handle beforePrerenderVisible when embed container is already loaded', async () => {
1231
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1232
+ liveboardId,
1233
+ vizId,
1234
+ activeTabId,
1235
+ ...defaultViewConfig,
1236
+ });
1237
+
1238
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1239
+
1240
+ // Mock embed container as already loaded
1241
+ liveboardEmbed.isEmbedContainerLoaded = true;
1242
+
1243
+ // Call beforePrerenderVisible
1244
+ liveboardEmbed['beforePrerenderVisible']();
1245
+
1246
+ // navigateToLiveboard should be called immediately
1247
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1248
+ });
1249
+
1250
+ test('should handle beforePrerenderVisible without prerender object', async () => {
1251
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1252
+ liveboardId,
1253
+ vizId,
1254
+ activeTabId,
1255
+ ...defaultViewConfig,
1256
+ });
1257
+
1258
+ jest.spyOn(liveboardEmbed as any, 'getPreRenderObj').mockReturnValue(null);
1259
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1260
+
1261
+ // Mock embed container as not loaded initially
1262
+ liveboardEmbed.isEmbedContainerLoaded = false;
1263
+
1264
+ // Call beforePrerenderVisible
1265
+ liveboardEmbed['beforePrerenderVisible']();
1266
+
1267
+ // Simulate embed container becoming ready
1268
+ liveboardEmbed.isEmbedContainerLoaded = true;
1269
+ liveboardEmbed['executeEmbedContainerReadyCallbacks']();
1270
+
1271
+ // navigateToLiveboard should still be called
1272
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, vizId, activeTabId);
1273
+ });
1274
+
1275
+ test('should work with all liveboard parameters', async () => {
1276
+ const customLiveboardId = 'custom-liveboard-id';
1277
+ const customVizId = 'custom-viz-id';
1278
+ const customActiveTabId = 'custom-active-tab-id';
1279
+
1280
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1281
+ liveboardId: customLiveboardId,
1282
+ vizId: customVizId,
1283
+ activeTabId: customActiveTabId,
1284
+ ...defaultViewConfig,
1285
+ });
1286
+
1287
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1288
+
1289
+ // Mock embed container as already loaded
1290
+ liveboardEmbed.isEmbedContainerLoaded = true;
1291
+
1292
+ // Call beforePrerenderVisible
1293
+ liveboardEmbed['beforePrerenderVisible']();
1294
+
1295
+ // Check that all parameters are passed correctly
1296
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(customLiveboardId, customVizId, customActiveTabId);
1297
+ });
1298
+
1299
+ test('should work with minimal liveboard parameters', async () => {
1300
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1301
+ liveboardId,
1302
+ ...defaultViewConfig,
1303
+ });
1304
+
1305
+ const navigateToLiveboardSpy = jest.spyOn(liveboardEmbed, 'navigateToLiveboard').mockResolvedValue(undefined);
1306
+
1307
+ // Mock embed container as already loaded
1308
+ liveboardEmbed.isEmbedContainerLoaded = true;
1309
+
1310
+ // Call beforePrerenderVisible
1311
+ liveboardEmbed['beforePrerenderVisible']();
1312
+
1313
+ // Check that undefined parameters are passed correctly
1314
+ expect(navigateToLiveboardSpy).toHaveBeenCalledWith(liveboardId, undefined, undefined);
1315
+ });
1316
+ });
1116
1317
  });