@thoughtspot/visual-embed-sdk 1.37.1-spotter-embed → 1.38.0-alpha.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 (161) hide show
  1. package/README.md +1 -1
  2. package/cjs/package.json +2 -2
  3. package/cjs/src/embed/app.d.ts +43 -3
  4. package/cjs/src/embed/app.d.ts.map +1 -1
  5. package/cjs/src/embed/app.js +40 -7
  6. package/cjs/src/embed/app.js.map +1 -1
  7. package/cjs/src/embed/app.spec.js +23 -6
  8. package/cjs/src/embed/app.spec.js.map +1 -1
  9. package/cjs/src/embed/base.d.ts.map +1 -1
  10. package/cjs/src/embed/base.js +7 -0
  11. package/cjs/src/embed/base.js.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.d.ts +8 -3
  13. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  14. package/cjs/src/embed/bodyless-conversation.js +5 -2
  15. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  16. package/cjs/src/embed/bodyless-conversation.spec.js +286 -1
  17. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  18. package/cjs/src/embed/conversation.d.ts +5 -3
  19. package/cjs/src/embed/conversation.d.ts.map +1 -1
  20. package/cjs/src/embed/conversation.js +3 -2
  21. package/cjs/src/embed/conversation.js.map +1 -1
  22. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  23. package/cjs/src/embed/liveboard.js +21 -10
  24. package/cjs/src/embed/liveboard.js.map +1 -1
  25. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  26. package/cjs/src/embed/ts-embed.js +6 -4
  27. package/cjs/src/embed/ts-embed.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  29. package/cjs/src/embed/ts-embed.spec.js +105 -0
  30. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  31. package/cjs/src/index.d.ts +4 -4
  32. package/cjs/src/index.d.ts.map +1 -1
  33. package/cjs/src/index.js +5 -3
  34. package/cjs/src/index.js.map +1 -1
  35. package/cjs/src/react/all-types-export.d.ts +1 -1
  36. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  37. package/cjs/src/react/all-types-export.js +2 -1
  38. package/cjs/src/react/all-types-export.js.map +1 -1
  39. package/cjs/src/react/index.d.ts +32 -3
  40. package/cjs/src/react/index.d.ts.map +1 -1
  41. package/cjs/src/react/index.js +54 -2
  42. package/cjs/src/react/index.js.map +1 -1
  43. package/cjs/src/react/index.spec.js +94 -0
  44. package/cjs/src/react/index.spec.js.map +1 -1
  45. package/cjs/src/types.d.ts +25 -51
  46. package/cjs/src/types.d.ts.map +1 -1
  47. package/cjs/src/types.js +24 -50
  48. package/cjs/src/types.js.map +1 -1
  49. package/dist/{index-Cj4BVGHL.js → index-DeFzsyFF.js} +1 -1
  50. package/dist/{index-DnIvX1FR.js → index-NZYq1Tu3.js} +1 -2
  51. package/dist/src/embed/app.d.ts +43 -3
  52. package/dist/src/embed/app.d.ts.map +1 -1
  53. package/dist/src/embed/base.d.ts.map +1 -1
  54. package/dist/src/embed/bodyless-conversation.d.ts +8 -3
  55. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  56. package/dist/src/embed/conversation.d.ts +5 -3
  57. package/dist/src/embed/conversation.d.ts.map +1 -1
  58. package/dist/src/embed/liveboard.d.ts.map +1 -1
  59. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  60. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  61. package/dist/src/index.d.ts +4 -4
  62. package/dist/src/index.d.ts.map +1 -1
  63. package/dist/src/react/all-types-export.d.ts +1 -1
  64. package/dist/src/react/all-types-export.d.ts.map +1 -1
  65. package/dist/src/react/index.d.ts +32 -3
  66. package/dist/src/react/index.d.ts.map +1 -1
  67. package/dist/src/types.d.ts +25 -51
  68. package/dist/src/types.d.ts.map +1 -1
  69. package/dist/tsembed-react.es.js +614 -77
  70. package/dist/tsembed-react.js +758 -296
  71. package/dist/tsembed.es.js +153 -75
  72. package/dist/tsembed.js +297 -295
  73. package/dist/visual-embed-sdk-react-full.d.ts +194 -145
  74. package/dist/visual-embed-sdk-react.d.ts +194 -145
  75. package/dist/visual-embed-sdk.d.ts +82 -61
  76. package/lib/package.json +2 -2
  77. package/lib/src/embed/app.d.ts +43 -3
  78. package/lib/src/embed/app.d.ts.map +1 -1
  79. package/lib/src/embed/app.js +39 -6
  80. package/lib/src/embed/app.js.map +1 -1
  81. package/lib/src/embed/app.spec.js +24 -7
  82. package/lib/src/embed/app.spec.js.map +1 -1
  83. package/lib/src/embed/base.d.ts.map +1 -1
  84. package/lib/src/embed/base.js +7 -0
  85. package/lib/src/embed/base.js.map +1 -1
  86. package/lib/src/embed/bodyless-conversation.d.ts +8 -3
  87. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  88. package/lib/src/embed/bodyless-conversation.js +5 -2
  89. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  90. package/lib/src/embed/bodyless-conversation.spec.js +287 -2
  91. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  92. package/lib/src/embed/conversation.d.ts +5 -3
  93. package/lib/src/embed/conversation.d.ts.map +1 -1
  94. package/lib/src/embed/conversation.js +3 -2
  95. package/lib/src/embed/conversation.js.map +1 -1
  96. package/lib/src/embed/liveboard.d.ts.map +1 -1
  97. package/lib/src/embed/liveboard.js +21 -10
  98. package/lib/src/embed/liveboard.js.map +1 -1
  99. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  100. package/lib/src/embed/ts-embed.js +6 -4
  101. package/lib/src/embed/ts-embed.js.map +1 -1
  102. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  103. package/lib/src/embed/ts-embed.spec.js +105 -0
  104. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  105. package/lib/src/index.d.ts +4 -4
  106. package/lib/src/index.d.ts.map +1 -1
  107. package/lib/src/index.js +4 -4
  108. package/lib/src/index.js.map +1 -1
  109. package/lib/src/react/all-types-export.d.ts +1 -1
  110. package/lib/src/react/all-types-export.d.ts.map +1 -1
  111. package/lib/src/react/all-types-export.js +1 -1
  112. package/lib/src/react/all-types-export.js.map +1 -1
  113. package/lib/src/react/index.d.ts +32 -3
  114. package/lib/src/react/index.d.ts.map +1 -1
  115. package/lib/src/react/index.js +53 -1
  116. package/lib/src/react/index.js.map +1 -1
  117. package/lib/src/react/index.spec.js +96 -2
  118. package/lib/src/react/index.spec.js.map +1 -1
  119. package/lib/src/types.d.ts +25 -51
  120. package/lib/src/types.d.ts.map +1 -1
  121. package/lib/src/types.js +24 -50
  122. package/lib/src/types.js.map +1 -1
  123. package/lib/src/visual-embed-sdk.d.ts +85 -64
  124. package/package.json +2 -2
  125. package/src/embed/app.spec.ts +30 -6
  126. package/src/embed/app.ts +62 -9
  127. package/src/embed/base.ts +9 -0
  128. package/src/embed/bodyless-conversation.spec.ts +308 -1
  129. package/src/embed/bodyless-conversation.ts +13 -3
  130. package/src/embed/conversation.ts +5 -3
  131. package/src/embed/liveboard.ts +25 -10
  132. package/src/embed/ts-embed.spec.ts +130 -0
  133. package/src/embed/ts-embed.ts +6 -4
  134. package/src/index.ts +10 -3
  135. package/src/react/all-types-export.ts +1 -0
  136. package/src/react/index.spec.tsx +157 -1
  137. package/src/react/index.tsx +64 -3
  138. package/src/types.ts +24 -56
  139. package/cjs/src/pages/embed-test.page.d.ts +0 -8
  140. package/cjs/src/pages/embed-test.page.d.ts.map +0 -1
  141. package/cjs/src/pages/embed-test.page.js +0 -20
  142. package/cjs/src/pages/embed-test.page.js.map +0 -1
  143. package/cjs/src/pages/home.page.d.ts +0 -6
  144. package/cjs/src/pages/home.page.d.ts.map +0 -1
  145. package/cjs/src/pages/home.page.js +0 -12
  146. package/cjs/src/pages/home.page.js.map +0 -1
  147. package/cjs/src/pages/login.page.d.ts +0 -15
  148. package/cjs/src/pages/login.page.d.ts.map +0 -1
  149. package/cjs/src/pages/login.page.js +0 -22
  150. package/cjs/src/pages/login.page.js.map +0 -1
  151. package/cjs/src/tests/auth.test.d.ts +0 -1
  152. package/cjs/src/tests/auth.test.d.ts.map +0 -1
  153. package/cjs/src/tests/auth.test.js +0 -1
  154. package/cjs/src/tests/auth.test.js.map +0 -1
  155. package/cjs/src/tests/e2e/auth.spec.d.ts +0 -2
  156. package/cjs/src/tests/e2e/auth.spec.d.ts.map +0 -1
  157. package/cjs/src/tests/e2e/auth.spec.js +0 -54
  158. package/cjs/src/tests/e2e/auth.spec.js.map +0 -1
  159. package/dist/index-DUaG1OG2.js +0 -7447
  160. package/dist/index-Fhk1V_Gw.js +0 -7371
  161. package/dist/index-OuiZF3zE.js +0 -7371
@@ -31,7 +31,7 @@ describe('SpotterAgentEmbed', () => {
31
31
  fetchMock.resetMocks();
32
32
  });
33
33
 
34
- test('should render the bodyless conversation embed', async () => {
34
+ test('should render the SpotterAgent embed', async () => {
35
35
  fetchMock.mockResponses(
36
36
  JSON.stringify({
37
37
  data: {
@@ -137,4 +137,311 @@ describe('SpotterAgentEmbed', () => {
137
137
  const errorResult = await spotterEmbed.sendMessage('userMessage');
138
138
  expect(errorResult.error instanceof Error).toBeTruthy();
139
139
  });
140
+
141
+ test('should apply containerClassName to the container element', async () => {
142
+ fetchMock.mockResponses(
143
+ JSON.stringify({
144
+ data: {
145
+ ConvAssist__createConversation: {
146
+ convId: 'conversationId',
147
+ initialCtx: {
148
+ type: 'TS_ANSWER',
149
+ tsAnsCtx: {
150
+ sessionId: 'sessionId',
151
+ genNo: 1,
152
+ stateKey: {
153
+ transactionId: 'transactionId',
154
+ generationNumber: 1,
155
+ },
156
+ worksheet: {
157
+ worksheetId: 'worksheetId',
158
+ worksheetName: 'GTM',
159
+ },
160
+ },
161
+ },
162
+ },
163
+ },
164
+ }),
165
+ JSON.stringify({
166
+ data: {
167
+ ConvAssist__sendMessage: {
168
+ responses: [
169
+ {
170
+ msgId: 'msgId',
171
+ data: {
172
+ asstRespData: {
173
+ tool: 'TS_NLS',
174
+ asstRespText: '',
175
+ nlsAnsData: {
176
+ sageQuerySuggestions: [
177
+ {
178
+ llmReasoning: {
179
+ assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
180
+ clarifications: '',
181
+ interpretation: '',
182
+ __typename: 'eureka_SageQuerySuggestion_LLMReasoning',
183
+ },
184
+ tokens: [
185
+ 'sum sales',
186
+ "item type = 'jackets'",
187
+ "date = 'this year'",
188
+ ],
189
+ tmlTokens: [
190
+ 'sum [sales]',
191
+ "[date] = [date].'this year'",
192
+ "[item type] = [item type].'jackets'",
193
+ ],
194
+ worksheetId: 'worksheetId',
195
+ description: '',
196
+ title: '',
197
+ cached: false,
198
+ sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
199
+ sessionId: 'sessionId',
200
+ genNo: 2,
201
+ formulaInfo: [],
202
+ tmlPhrases: [],
203
+ stateKey: {
204
+ transactionId: 'transactionId',
205
+ generationNumber: 1,
206
+ __typename: 'sage_auto_complete_v2_ACStateKey',
207
+ },
208
+ __typename: 'eureka_SageQuerySuggestion',
209
+ },
210
+ ],
211
+ responseType: 'ANSWER',
212
+ __typename: 'convassist_nls_tool_NLSToolAsstRespData',
213
+ },
214
+ __typename: 'convassist_AsstResponseData',
215
+ },
216
+ __typename: 'convassist_MessageData',
217
+ },
218
+ type: 'ASST_RESPONSE',
219
+ __typename: 'convassist_MessagePayload',
220
+ },
221
+ ],
222
+ __typename: 'convassist_SendMessageResponse',
223
+ },
224
+ },
225
+ }),
226
+ );
227
+
228
+ const viewConfig: SpotterAgentEmbedViewConfig = {
229
+ worksheetId: 'worksheetId',
230
+ containerClassName: 'custom-conversation-container',
231
+ };
232
+
233
+ const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
234
+ const result = await spotterAgentEmbed.sendMessage('userMessage');
235
+
236
+ // Verify that the container has the custom class name
237
+ expect(result.container.className).toBe('custom-conversation-container');
238
+
239
+ // Also verify the iframe src is correct
240
+ const iframeSrc = getIFrameSrc(result.container);
241
+ expectUrlToHaveParamsWithValues(iframeSrc, {
242
+ sessionId: 'sessionId',
243
+ genNo: 2,
244
+ acSessionId: 'transactionId',
245
+ acGenNo: 1,
246
+ });
247
+ });
248
+
249
+ test('should not set className when containerClassName is not provided', async () => {
250
+ fetchMock.mockResponses(
251
+ JSON.stringify({
252
+ data: {
253
+ ConvAssist__createConversation: {
254
+ convId: 'conversationId',
255
+ initialCtx: {
256
+ type: 'TS_ANSWER',
257
+ tsAnsCtx: {
258
+ sessionId: 'sessionId',
259
+ genNo: 1,
260
+ stateKey: {
261
+ transactionId: 'transactionId',
262
+ generationNumber: 1,
263
+ },
264
+ worksheet: {
265
+ worksheetId: 'worksheetId',
266
+ worksheetName: 'GTM',
267
+ },
268
+ },
269
+ },
270
+ },
271
+ },
272
+ }),
273
+ JSON.stringify({
274
+ data: {
275
+ ConvAssist__sendMessage: {
276
+ responses: [
277
+ {
278
+ msgId: 'msgId',
279
+ data: {
280
+ asstRespData: {
281
+ tool: 'TS_NLS',
282
+ asstRespText: '',
283
+ nlsAnsData: {
284
+ sageQuerySuggestions: [
285
+ {
286
+ llmReasoning: {
287
+ assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
288
+ clarifications: '',
289
+ interpretation: '',
290
+ __typename: 'eureka_SageQuerySuggestion_LLMReasoning',
291
+ },
292
+ tokens: [
293
+ 'sum sales',
294
+ "item type = 'jackets'",
295
+ "date = 'this year'",
296
+ ],
297
+ tmlTokens: [
298
+ 'sum [sales]',
299
+ "[date] = [date].'this year'",
300
+ "[item type] = [item type].'jackets'",
301
+ ],
302
+ worksheetId: 'worksheetId',
303
+ description: '',
304
+ title: '',
305
+ cached: false,
306
+ sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
307
+ sessionId: 'sessionId',
308
+ genNo: 2,
309
+ formulaInfo: [],
310
+ tmlPhrases: [],
311
+ stateKey: {
312
+ transactionId: 'transactionId',
313
+ generationNumber: 1,
314
+ __typename: 'sage_auto_complete_v2_ACStateKey',
315
+ },
316
+ __typename: 'eureka_SageQuerySuggestion',
317
+ },
318
+ ],
319
+ responseType: 'ANSWER',
320
+ __typename: 'convassist_nls_tool_NLSToolAsstRespData',
321
+ },
322
+ __typename: 'convassist_AsstResponseData',
323
+ },
324
+ __typename: 'convassist_MessageData',
325
+ },
326
+ type: 'ASST_RESPONSE',
327
+ __typename: 'convassist_MessagePayload',
328
+ },
329
+ ],
330
+ __typename: 'convassist_SendMessageResponse',
331
+ },
332
+ },
333
+ }),
334
+ );
335
+
336
+ const viewConfig: SpotterAgentEmbedViewConfig = {
337
+ worksheetId: 'worksheetId',
338
+ // No containerClassName provided
339
+ };
340
+
341
+ const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
342
+ const result = await spotterAgentEmbed.sendMessage('userMessage');
343
+
344
+ // Verify that the container has no class name (empty string)
345
+ expect(result.container.className).toBe('');
346
+ });
347
+
348
+ test('should handle hideActions parameter correctly', async () => {
349
+ fetchMock.mockResponses(
350
+ JSON.stringify({
351
+ data: {
352
+ ConvAssist__createConversation: {
353
+ convId: 'conversationId',
354
+ initialCtx: {
355
+ type: 'TS_ANSWER',
356
+ tsAnsCtx: {
357
+ sessionId: 'sessionId',
358
+ genNo: 1,
359
+ stateKey: {
360
+ transactionId: 'transactionId',
361
+ generationNumber: 1,
362
+ },
363
+ worksheet: {
364
+ worksheetId: 'worksheetId',
365
+ worksheetName: 'GTM',
366
+ },
367
+ },
368
+ },
369
+ },
370
+ },
371
+ }),
372
+ JSON.stringify({
373
+ data: {
374
+ ConvAssist__sendMessage: {
375
+ responses: [
376
+ {
377
+ msgId: 'msgId',
378
+ data: {
379
+ asstRespData: {
380
+ tool: 'TS_NLS',
381
+ asstRespText: '',
382
+ nlsAnsData: {
383
+ sageQuerySuggestions: [
384
+ {
385
+ llmReasoning: {
386
+ assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
387
+ clarifications: '',
388
+ interpretation: '',
389
+ __typename: 'eureka_SageQuerySuggestion_LLMReasoning',
390
+ },
391
+ tokens: [
392
+ 'sum sales',
393
+ "item type = 'jackets'",
394
+ "date = 'this year'",
395
+ ],
396
+ tmlTokens: [
397
+ 'sum [sales]',
398
+ "[date] = [date].'this year'",
399
+ "[item type] = [item type].'jackets'",
400
+ ],
401
+ worksheetId: 'worksheetId',
402
+ description: '',
403
+ title: '',
404
+ cached: false,
405
+ sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
406
+ sessionId: 'sessionId',
407
+ genNo: 2,
408
+ formulaInfo: [],
409
+ tmlPhrases: [],
410
+ stateKey: {
411
+ transactionId: 'transactionId',
412
+ generationNumber: 1,
413
+ __typename: 'sage_auto_complete_v2_ACStateKey',
414
+ },
415
+ __typename: 'eureka_SageQuerySuggestion',
416
+ },
417
+ ],
418
+ responseType: 'ANSWER',
419
+ __typename: 'convassist_nls_tool_NLSToolAsstRespData',
420
+ },
421
+ __typename: 'convassist_AsstResponseData',
422
+ },
423
+ __typename: 'convassist_MessageData',
424
+ },
425
+ type: 'ASST_RESPONSE',
426
+ __typename: 'convassist_MessagePayload',
427
+ },
428
+ ],
429
+ __typename: 'convassist_SendMessageResponse',
430
+ },
431
+ },
432
+ }),
433
+ );
434
+
435
+ const viewConfig: SpotterAgentEmbedViewConfig = {
436
+ worksheetId: 'worksheetId',
437
+ hiddenActions: [Action.Download, Action.Save], // This should trigger the HideActions branch
438
+ };
439
+
440
+ const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
441
+ const result = await spotterAgentEmbed.sendMessage('userMessage');
442
+
443
+ // Verify the iframe src contains the hideActions parameter
444
+ const iframeSrc = getIFrameSrc(result.container);
445
+ expect(iframeSrc).toContain('hideAction');
446
+ });
140
447
  });
@@ -13,11 +13,17 @@ export interface SpotterAgentEmbedViewConfig extends ViewConfig {
13
13
  * The ID of the worksheet to use for the conversation.
14
14
  */
15
15
  worksheetId: string;
16
+
17
+ /**
18
+ * Optional CSS class name to add to the container div.
19
+ */
20
+ containerClassName?: string;
16
21
  }
17
22
 
18
23
  /**
19
24
  * Configuration for conversation options.
20
- * @deprecated Renamed to SpotterAgentEmbedViewConfig
25
+ * @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
26
+ * Use {@link SpotterAgentEmbedViewConfig} instead
21
27
  * @group Embed components
22
28
  */
23
29
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -110,6 +116,10 @@ export class SpotterAgentEmbed {
110
116
  }
111
117
 
112
118
  const container = document.createElement('div');
119
+ if (this.viewConfig.containerClassName) {
120
+ container.className = this.viewConfig.containerClassName;
121
+ }
122
+
113
123
  const embed = new ConversationMessage(container, {
114
124
  ...this.viewConfig,
115
125
  sessionId: data.sessionId,
@@ -125,7 +135,8 @@ export class SpotterAgentEmbed {
125
135
  /**
126
136
  * Create a conversation embed, which can be integrated inside
127
137
  * chatbots or other conversational interfaces.
128
- * @deprecated Renamed to SpotterAgentEmbed
138
+ * @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
139
+ * Use {@link SpotterAgentEmbed} instead
129
140
  * @example
130
141
  * ```js
131
142
  * import { SpotterAgentEmbed } from '@thoughtspot/visual-embed-sdk';
@@ -140,7 +151,6 @@ export class SpotterAgentEmbed {
140
151
  * document.body.appendChild(container); // or to any other element
141
152
  * ```
142
153
  * @group Embed components
143
- * @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
144
154
  */
145
155
  export class BodylessConversation extends SpotterAgentEmbed {
146
156
  constructor(viewConfig: BodylessConversationViewConfig) {
@@ -96,7 +96,8 @@ export interface SpotterEmbedViewConfig extends ViewConfig {
96
96
 
97
97
  /**
98
98
  * The configuration for the embedded spotterEmbed options.
99
- * @deprecated Renamed to SpotterEmbedViewConfig
99
+ * @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
100
+ * Use {@link SpotterEmbedViewConfig} instead
100
101
  * @group Embed components
101
102
  */
102
103
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -115,7 +116,7 @@ export interface ConversationViewConfig extends SpotterEmbedViewConfig {}
115
116
  * });
116
117
  * conversation.render();
117
118
  * ```
118
- * @version SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
119
+ * @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
119
120
  */
120
121
  export class SpotterEmbed extends TsEmbed {
121
122
  constructor(container: HTMLElement, protected viewConfig: SpotterEmbedViewConfig) {
@@ -182,7 +183,8 @@ export class SpotterEmbed extends TsEmbed {
182
183
 
183
184
  /**
184
185
  * Embed ThoughtSpot AI Conversation.
185
- * @deprecated Renamed to SpotterEmbed
186
+ * @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
187
+ * Use {@link SpotterEmbed} instead
186
188
  * @group Embed components
187
189
  * @example
188
190
  * ```js
@@ -24,13 +24,8 @@ import { getAuthPromise } from './base';
24
24
  import { TsEmbed, V1Embed } from './ts-embed';
25
25
  import { addPreviewStylesIfNotPresent } from '../utils/global-styles';
26
26
  import { TriggerPayload, TriggerResponse } from './hostEventClient/contracts';
27
+ import { logger } from '../utils/logger';
27
28
 
28
- const liveboardHeightWhitelistedRoutes = [
29
- '/embed/viz/',
30
- '/embed/insights/viz/',
31
- '/tsl-editor/PINBOARD_ANSWER_BOOK/',
32
- '/import-tsl/PINBOARD_ANSWER_BOOK/',
33
- ];
34
29
 
35
30
  /**
36
31
  * The configuration for the embedded Liveboard or visualization page view.
@@ -429,11 +424,16 @@ export class LiveboardEmbed extends V1Embed {
429
424
 
430
425
  private defaultHeight = 500;
431
426
 
432
- // eslint-disable-next-line no-useless-constructor
427
+
433
428
  constructor(domSelector: DOMSelector, viewConfig: LiveboardViewConfig) {
434
429
  viewConfig.embedComponentType = 'LiveboardEmbed';
435
430
  super(domSelector, viewConfig);
436
431
  if (this.viewConfig.fullHeight === true) {
432
+ if (this.viewConfig.vizId) {
433
+ logger.warn('Full height is currently only supported for Liveboard embeds.' +
434
+ 'Using full height with vizId might lead to unexpected behavior.');
435
+ }
436
+
437
437
  this.on(EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard);
438
438
  this.on(EmbedEvent.EmbedHeight, this.updateIFrameHeight);
439
439
  this.on(EmbedEvent.EmbedIframeCenter, this.embedIframeCenter);
@@ -592,11 +592,26 @@ export class LiveboardEmbed extends V1Embed {
592
592
  };
593
593
 
594
594
  private setIframeHeightForNonEmbedLiveboard = (data: MessagePayload) => {
595
- const routePath = data.data.currentPath;
596
- if (liveboardHeightWhitelistedRoutes.some((path) => routePath.startsWith(path))) {
595
+ const { height: frameHeight } = this.viewConfig.frameParams || {};
596
+
597
+ const liveboardRelatedRoutes = [
598
+ '/pinboard/',
599
+ '/insights/pinboard/',
600
+ '/schedules/',
601
+ '/embed/viz/',
602
+ '/embed/insights/viz/',
603
+ '/liveboard/',
604
+ '/insights/liveboard/',
605
+ '/tsl-editor/PINBOARD_ANSWER_BOOK/',
606
+ '/import-tsl/PINBOARD_ANSWER_BOOK/',
607
+ ];
608
+
609
+ if (liveboardRelatedRoutes.some((path) => data.data.currentPath.startsWith(path))) {
610
+ // Ignore the height reset of the frame, if the navigation is
611
+ // only within the liveboard page.
597
612
  return;
598
613
  }
599
- this.setIFrameHeight(this.defaultHeight);
614
+ this.setIFrameHeight(frameHeight || this.defaultHeight);
600
615
  };
601
616
 
602
617
  private setActiveTab(data: { tabId: string }) {
@@ -58,6 +58,7 @@ import { HiddenActionItemByDefaultForSearchEmbed } from './search';
58
58
  import { processTrigger } from '../utils/processTrigger';
59
59
  import { UIPassthroughEvent } from './hostEventClient/contracts';
60
60
  import * as sessionInfoService from '../utils/sessionInfoService';
61
+ import * as authToken from '../authToken';
61
62
 
62
63
  jest.mock('../utils/processTrigger');
63
64
 
@@ -2576,4 +2577,133 @@ describe('Unit test case for ts embed', () => {
2576
2577
  expect(iframeAfterInit).not.toBe(null);
2577
2578
  });
2578
2579
  });
2580
+
2581
+ describe('AutoLogin behavior in updateAuthToken', () => {
2582
+ const mockPort = { postMessage: jest.fn() };
2583
+ const mockEmbedEventPayload = { type: EmbedEvent.AuthExpire, data: {} };
2584
+
2585
+ beforeEach(() => {
2586
+ jest.clearAllMocks();
2587
+ document.body.innerHTML = getDocumentBody();
2588
+ mockPort.postMessage.mockClear();
2589
+ jest.spyOn(authToken, 'getAuthenticationToken').mockResolvedValue('test-token');
2590
+
2591
+ jest.spyOn(baseInstance, 'handleAuth').mockImplementation(() => Promise.resolve(true));
2592
+ jest.spyOn(baseInstance, 'notifyAuthFailure').mockImplementation(() => {});
2593
+ });
2594
+
2595
+ const renderAndTriggerAuthExpire = async () => {
2596
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2597
+ await searchEmbed.render();
2598
+ await executeAfterWait(() => {
2599
+ const iframe = getIFrameEl();
2600
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2601
+ });
2602
+ };
2603
+
2604
+ test('Cookieless with autoLogin undefined should default to true', async () => {
2605
+ init({
2606
+ thoughtSpotHost: 'tshost',
2607
+ authType: AuthType.TrustedAuthTokenCookieless,
2608
+ // autoLogin undefined
2609
+ });
2610
+
2611
+ await renderAndTriggerAuthExpire();
2612
+
2613
+ await executeAfterWait(() => {
2614
+ expect(authToken.getAuthenticationToken).toHaveBeenCalled();
2615
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
2616
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
2617
+ type: EmbedEvent.AuthExpire,
2618
+ data: { authToken: 'test-token' },
2619
+ });
2620
+ });
2621
+ });
2622
+
2623
+ test('Cookieless with autoLogin false should not get auth token', async () => {
2624
+ init({
2625
+ thoughtSpotHost: 'tshost',
2626
+ authType: AuthType.TrustedAuthTokenCookieless,
2627
+ autoLogin: false,
2628
+ });
2629
+
2630
+ await renderAndTriggerAuthExpire();
2631
+
2632
+ await executeAfterWait(() => {
2633
+ expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
2634
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
2635
+ expect(mockPort.postMessage).not.toHaveBeenCalled();
2636
+ });
2637
+ });
2638
+
2639
+ test('Cookieless with autoLogin true should get auth token', async () => {
2640
+ init({
2641
+ thoughtSpotHost: 'tshost',
2642
+ authType: AuthType.TrustedAuthTokenCookieless,
2643
+ autoLogin: true,
2644
+ });
2645
+
2646
+ await renderAndTriggerAuthExpire();
2647
+
2648
+ await executeAfterWait(() => {
2649
+ expect(authToken.getAuthenticationToken).toHaveBeenCalled();
2650
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
2651
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
2652
+ type: EmbedEvent.AuthExpire,
2653
+ data: { authToken: 'test-token' },
2654
+ });
2655
+ });
2656
+ });
2657
+
2658
+ test('Other authType with autoLogin undefined should default to false', async () => {
2659
+ init({
2660
+ thoughtSpotHost: 'tshost',
2661
+ authType: AuthType.None,
2662
+ // autoLogin undefined
2663
+ });
2664
+
2665
+ await renderAndTriggerAuthExpire();
2666
+
2667
+ await executeAfterWait(() => {
2668
+ expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
2669
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
2670
+ });
2671
+ });
2672
+
2673
+ test('Other authType with autoLogin true should call handleAuth', async () => {
2674
+ init({
2675
+ thoughtSpotHost: 'tshost',
2676
+ authType: AuthType.None,
2677
+ autoLogin: true,
2678
+ });
2679
+
2680
+ await renderAndTriggerAuthExpire();
2681
+
2682
+ await executeAfterWait(() => {
2683
+ expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
2684
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(2);
2685
+ });
2686
+ });
2687
+
2688
+ test('Other authType with autoLogin false should not call handleAuth', async () => {
2689
+ init({
2690
+ thoughtSpotHost: 'tshost',
2691
+ authType: AuthType.None,
2692
+ autoLogin: false,
2693
+ });
2694
+
2695
+ await renderAndTriggerAuthExpire();
2696
+
2697
+ await executeAfterWait(() => {
2698
+ expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
2699
+ expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
2700
+ });
2701
+ });
2702
+
2703
+ afterEach(() => {
2704
+ expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
2705
+ authInstance.AuthFailureType.EXPIRY
2706
+ );
2707
+ });
2708
+ });
2579
2709
  });
@@ -409,11 +409,13 @@ export class TsEmbed {
409
409
  * @param responder
410
410
  */
411
411
  private updateAuthToken = async (_: any, responder: any) => {
412
- const { autoLogin = false, authType } = this.embedConfig; // Set autoLogin default to false
413
- if (authType === AuthType.TrustedAuthTokenCookieless) {
414
- let authToken = '';
412
+ const { authType } = this.embedConfig;
413
+ let { autoLogin } = this.embedConfig;
414
+ // Default autoLogin: true for cookieless if undefined/null, otherwise false
415
+ autoLogin = autoLogin ?? (authType === AuthType.TrustedAuthTokenCookieless);
416
+ if (autoLogin && authType === AuthType.TrustedAuthTokenCookieless) {
415
417
  try {
416
- authToken = await getAuthenticationToken(this.embedConfig);
418
+ const authToken = await getAuthenticationToken(this.embedConfig);
417
419
  responder({
418
420
  type: EmbedEvent.AuthExpire,
419
421
  data: { authToken },
package/src/index.ts CHANGED
@@ -9,7 +9,12 @@
9
9
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
10
10
  */
11
11
  import {
12
- AppEmbed, Page, AppViewConfig, HomePageSearchBarMode,
12
+ AppEmbed,
13
+ Page,
14
+ AppViewConfig,
15
+ HomePageSearchBarMode,
16
+ PrimaryNavbarVersion,
17
+ HomePage,
13
18
  } from './embed/app';
14
19
  import {
15
20
  init,
@@ -23,8 +28,8 @@ import {
23
28
  import { PinboardEmbed, LiveboardViewConfig, LiveboardEmbed } from './embed/liveboard';
24
29
  import { SearchEmbed, SearchViewConfig } from './embed/search';
25
30
  import { SearchBarEmbed, SearchBarViewConfig } from './embed/search-bar';
26
- import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, SpotterAgentEmbed as BodylessConversation, SpotterAgentEmbedViewConfig as BodylessConversationViewConfig} from './embed/bodyless-conversation';
27
- import { SpotterEmbed, SpotterEmbedViewConfig, SpotterEmbed as ConversationEmbed, SpotterEmbedViewConfig as ConversationViewConfig } from './embed/conversation';
31
+ import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, BodylessConversation, BodylessConversationViewConfig} from './embed/bodyless-conversation';
32
+ import { SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed, ConversationViewConfig } from './embed/conversation';
28
33
  import {
29
34
  AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter,
30
35
  } from './auth';
@@ -133,6 +138,8 @@ export {
133
138
  uploadMixpanelEvent,
134
139
  MIXPANEL_EVENT,
135
140
  HomePageSearchBarMode,
141
+ PrimaryNavbarVersion,
142
+ HomePage,
136
143
  VizPoint,
137
144
  CustomActionPayload,
138
145
  UIPassthroughEvent,
@@ -12,6 +12,7 @@ export {
12
12
  SpotterEmbed,
13
13
  ConversationEmbed,
14
14
  PreRenderedConversationEmbed,
15
+ SpotterAgentEmbed,
15
16
  useEmbedRef,
16
17
  useInit,
17
18
  } from './index';