@thoughtspot/visual-embed-sdk 1.35.12 → 1.35.14

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 (132) hide show
  1. package/cjs/package.json +1 -2
  2. package/cjs/src/auth.d.ts +2 -1
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +3 -1
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/embed/app.d.ts.map +1 -1
  7. package/cjs/src/embed/app.js +2 -0
  8. package/cjs/src/embed/app.js.map +1 -1
  9. package/cjs/src/embed/conversation.d.ts +44 -0
  10. package/cjs/src/embed/conversation.d.ts.map +1 -1
  11. package/cjs/src/embed/conversation.js +10 -1
  12. package/cjs/src/embed/conversation.js.map +1 -1
  13. package/cjs/src/embed/conversation.spec.js +36 -0
  14. package/cjs/src/embed/conversation.spec.js.map +1 -1
  15. package/cjs/src/embed/hostEventClient/contracts.d.ts +3 -3
  16. package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  17. package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  18. package/cjs/src/embed/hostEventClient/host-event-client.js +6 -1
  19. package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
  20. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  21. package/cjs/src/embed/liveboard.js +8 -2
  22. package/cjs/src/embed/liveboard.js.map +1 -1
  23. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  24. package/cjs/src/embed/search-bar.js +4 -2
  25. package/cjs/src/embed/search-bar.js.map +1 -1
  26. package/cjs/src/embed/search.d.ts.map +1 -1
  27. package/cjs/src/embed/search.js +4 -2
  28. package/cjs/src/embed/search.js.map +1 -1
  29. package/cjs/src/embed/search.spec.js +56 -3
  30. package/cjs/src/embed/search.spec.js.map +1 -1
  31. package/cjs/src/embed/ts-embed.d.ts +6 -0
  32. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  33. package/cjs/src/embed/ts-embed.js +38 -13
  34. package/cjs/src/embed/ts-embed.js.map +1 -1
  35. package/cjs/src/embed/ts-embed.spec.js +132 -130
  36. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  37. package/cjs/src/types.d.ts +43 -17
  38. package/cjs/src/types.d.ts.map +1 -1
  39. package/cjs/src/types.js +35 -7
  40. package/cjs/src/types.js.map +1 -1
  41. package/cjs/src/utils/processData.d.ts.map +1 -1
  42. package/cjs/src/utils/processData.js +9 -2
  43. package/cjs/src/utils/processData.js.map +1 -1
  44. package/cjs/src/utils/processData.spec.js +51 -0
  45. package/cjs/src/utils/processData.spec.js.map +1 -1
  46. package/dist/index-B3hd6DTM.js +7370 -0
  47. package/dist/index-vxW97_xb.js +7370 -0
  48. package/dist/src/auth.d.ts +2 -1
  49. package/dist/src/auth.d.ts.map +1 -1
  50. package/dist/src/embed/app.d.ts.map +1 -1
  51. package/dist/src/embed/conversation.d.ts +44 -0
  52. package/dist/src/embed/conversation.d.ts.map +1 -1
  53. package/dist/src/embed/hostEventClient/contracts.d.ts +3 -3
  54. package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  55. package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  56. package/dist/src/embed/liveboard.d.ts.map +1 -1
  57. package/dist/src/embed/search-bar.d.ts.map +1 -1
  58. package/dist/src/embed/search.d.ts.map +1 -1
  59. package/dist/src/embed/ts-embed.d.ts +6 -0
  60. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  61. package/dist/src/types.d.ts +43 -17
  62. package/dist/src/types.d.ts.map +1 -1
  63. package/dist/src/utils/processData.d.ts.map +1 -1
  64. package/dist/tsembed-react.es.js +122 -34
  65. package/dist/tsembed-react.js +121 -33
  66. package/dist/tsembed.es.js +122 -34
  67. package/dist/tsembed.js +121 -33
  68. package/dist/visual-embed-sdk-react-full.d.ts +92 -21
  69. package/dist/visual-embed-sdk-react.d.ts +92 -21
  70. package/dist/visual-embed-sdk.d.ts +92 -21
  71. package/lib/package.json +1 -2
  72. package/lib/src/auth.d.ts +2 -1
  73. package/lib/src/auth.d.ts.map +1 -1
  74. package/lib/src/auth.js +3 -1
  75. package/lib/src/auth.js.map +1 -1
  76. package/lib/src/embed/app.d.ts.map +1 -1
  77. package/lib/src/embed/app.js +2 -0
  78. package/lib/src/embed/app.js.map +1 -1
  79. package/lib/src/embed/conversation.d.ts +44 -0
  80. package/lib/src/embed/conversation.d.ts.map +1 -1
  81. package/lib/src/embed/conversation.js +10 -1
  82. package/lib/src/embed/conversation.js.map +1 -1
  83. package/lib/src/embed/conversation.spec.js +36 -0
  84. package/lib/src/embed/conversation.spec.js.map +1 -1
  85. package/lib/src/embed/hostEventClient/contracts.d.ts +3 -3
  86. package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  87. package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  88. package/lib/src/embed/hostEventClient/host-event-client.js +6 -1
  89. package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
  90. package/lib/src/embed/liveboard.d.ts.map +1 -1
  91. package/lib/src/embed/liveboard.js +8 -2
  92. package/lib/src/embed/liveboard.js.map +1 -1
  93. package/lib/src/embed/search-bar.d.ts.map +1 -1
  94. package/lib/src/embed/search-bar.js +4 -2
  95. package/lib/src/embed/search-bar.js.map +1 -1
  96. package/lib/src/embed/search.d.ts.map +1 -1
  97. package/lib/src/embed/search.js +4 -2
  98. package/lib/src/embed/search.js.map +1 -1
  99. package/lib/src/embed/search.spec.js +56 -3
  100. package/lib/src/embed/search.spec.js.map +1 -1
  101. package/lib/src/embed/ts-embed.d.ts +6 -0
  102. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  103. package/lib/src/embed/ts-embed.js +38 -13
  104. package/lib/src/embed/ts-embed.js.map +1 -1
  105. package/lib/src/embed/ts-embed.spec.js +133 -131
  106. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  107. package/lib/src/types.d.ts +43 -17
  108. package/lib/src/types.d.ts.map +1 -1
  109. package/lib/src/types.js +35 -7
  110. package/lib/src/types.js.map +1 -1
  111. package/lib/src/utils/processData.d.ts.map +1 -1
  112. package/lib/src/utils/processData.js +9 -2
  113. package/lib/src/utils/processData.js.map +1 -1
  114. package/lib/src/utils/processData.spec.js +51 -0
  115. package/lib/src/utils/processData.spec.js.map +1 -1
  116. package/lib/src/visual-embed-sdk.d.ts +92 -21
  117. package/package.json +1 -2
  118. package/src/auth.ts +3 -1
  119. package/src/embed/app.ts +2 -0
  120. package/src/embed/conversation.spec.ts +52 -3
  121. package/src/embed/conversation.ts +60 -1
  122. package/src/embed/hostEventClient/contracts.ts +3 -3
  123. package/src/embed/hostEventClient/host-event-client.ts +7 -1
  124. package/src/embed/liveboard.ts +9 -4
  125. package/src/embed/search-bar.tsx +6 -4
  126. package/src/embed/search.spec.ts +71 -3
  127. package/src/embed/search.ts +6 -5
  128. package/src/embed/ts-embed.spec.ts +153 -180
  129. package/src/embed/ts-embed.ts +46 -30
  130. package/src/types.ts +44 -15
  131. package/src/utils/processData.spec.ts +63 -0
  132. package/src/utils/processData.ts +12 -2
@@ -270,7 +270,45 @@ describe('Unit test case for ts embed', () => {
270
270
  });
271
271
  });
272
272
  });
273
+
274
+ test('check for new authToken based on getAuthToken function', async () => {
275
+ init({
276
+ thoughtSpotHost: 'tshost',
277
+ customizations: customisations,
278
+ authType: AuthType.TrustedAuthToken,
279
+ getAuthToken: () => Promise.resolve('test_auth_token2'),
280
+ autoLogin: true,
281
+ });
282
+
283
+ const mockEmbedEventPayload = {
284
+ type: EmbedEvent.AuthExpire,
285
+ data: {},
286
+ };
287
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
288
+ jest.spyOn(baseInstance, 'notifyAuthFailure');
289
+ jest.spyOn(baseInstance, 'handleAuth');
290
+
291
+ searchEmbed.render();
292
+ const mockPort: any = {
293
+ postMessage: jest.fn(),
294
+ };
295
+ await executeAfterWait(() => {
296
+ const iframe = getIFrameEl();
297
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
298
+ });
299
+ await executeAfterWait(() => {
300
+ expect(baseInstance.notifyAuthFailure).toBeCalledWith(
301
+ authInstance.AuthFailureType.EXPIRY,
302
+ );
303
+ expect(mockPort.postMessage).not.toHaveBeenCalledWith({
304
+ type: EmbedEvent.AuthExpire,
305
+ data: { authToken: 'test_auth_token2' },
306
+ });
307
+ expect(baseInstance.handleAuth).toHaveBeenCalled();
308
+ });
309
+ });
273
310
  });
311
+
274
312
  describe('Called Embed event status for start and end', () => {
275
313
  beforeAll(() => {
276
314
  init({
@@ -1665,68 +1703,6 @@ describe('Unit test case for ts embed', () => {
1665
1703
  });
1666
1704
  });
1667
1705
 
1668
- it('AppEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1669
- const appEmbed = new AppEmbed(getRootEl(), {
1670
- ...defaultViewConfig,
1671
- enableFlipTooltipToContextMenu: true,
1672
- } as AppViewConfig);
1673
-
1674
- appEmbed.render();
1675
- await executeAfterWait(() => {
1676
- expectUrlMatchesWithParams(
1677
- getIFrameSrc(),
1678
- `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&flipTooltipToContextMenuEnabled=true${defaultParams}${defaultParamsPost}#/home`,
1679
- );
1680
- });
1681
- });
1682
-
1683
- it('AppEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1684
- const appEmbed = new AppEmbed(getRootEl(), {
1685
- ...defaultViewConfig,
1686
- enableFlipTooltipToContextMenu: false,
1687
- } as AppViewConfig);
1688
-
1689
- appEmbed.render();
1690
- await executeAfterWait(() => {
1691
- expectUrlMatchesWithParams(
1692
- getIFrameSrc(),
1693
- `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
1694
- );
1695
- });
1696
- });
1697
-
1698
- it('LiveboardEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1699
- const appEmbed = new LiveboardEmbed(getRootEl(), {
1700
- ...defaultViewConfig,
1701
- liveboardId,
1702
- enableFlipTooltipToContextMenu: true,
1703
- } as LiveboardViewConfig);
1704
-
1705
- appEmbed.render();
1706
- await executeAfterWait(() => {
1707
- expectUrlMatchesWithParams(
1708
- getIFrameSrc(),
1709
- `http://${thoughtSpotHost}/?embedApp=true&flipTooltipToContextMenuEnabled=true${defaultParams}#/embed/viz/${liveboardId}`,
1710
- );
1711
- });
1712
- });
1713
-
1714
- it('LiveboardEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1715
- const appEmbed = new LiveboardEmbed(getRootEl(), {
1716
- ...defaultViewConfig,
1717
- liveboardId,
1718
- enableFlipTooltipToContextMenu: false,
1719
- } as LiveboardViewConfig);
1720
-
1721
- appEmbed.render();
1722
- await executeAfterWait(() => {
1723
- expectUrlMatchesWithParams(
1724
- getIFrameSrc(),
1725
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}#/embed/viz/${liveboardId}`,
1726
- );
1727
- });
1728
- });
1729
-
1730
1706
  it('Should not add contextMenuEnabledOnWhichClick flag to the iframe src when it is not passed', async () => {
1731
1707
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
1732
1708
  ...defaultViewConfig,
@@ -1878,124 +1854,6 @@ describe('Unit test case for ts embed', () => {
1878
1854
  );
1879
1855
  });
1880
1856
  });
1881
-
1882
- it('SageViewConfig: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1883
- const defaultConfig: SageViewConfig = {
1884
- disableWorksheetChange: false,
1885
- hideWorksheetSelector: false,
1886
- hideSageAnswerHeader: false,
1887
- hideAutocompleteSuggestions: false,
1888
- hideSampleQuestions: false,
1889
- isProductTour: false,
1890
- dataPanelV2: false,
1891
- };
1892
- const appEmbed = new SageEmbed(getRootEl(), {
1893
- ...defaultConfig,
1894
- enableFlipTooltipToContextMenu: true,
1895
- } as SageViewConfig);
1896
-
1897
- appEmbed.render();
1898
- await executeAfterWait(() => {
1899
- expectUrlMatch(
1900
- getIFrameSrc(),
1901
- `http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D&flipTooltipToContextMenuEnabled=true#/embed/eureka`,
1902
- );
1903
- });
1904
- });
1905
-
1906
- it('SageViewConfig: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1907
- const defaultConfig: SageViewConfig = {
1908
- disableWorksheetChange: false,
1909
- hideWorksheetSelector: false,
1910
- hideSageAnswerHeader: false,
1911
- hideAutocompleteSuggestions: false,
1912
- hideSampleQuestions: false,
1913
- isProductTour: false,
1914
- dataPanelV2: false,
1915
- };
1916
- const appEmbed = new SageEmbed(getRootEl(), {
1917
- ...defaultConfig,
1918
- enableFlipTooltipToContextMenu: false,
1919
- } as SageViewConfig);
1920
-
1921
- appEmbed.render();
1922
- await executeAfterWait(() => {
1923
- expectUrlMatch(
1924
- getIFrameSrc(),
1925
- `http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
1926
- );
1927
- });
1928
- });
1929
-
1930
- it('ConversationEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1931
- const appEmbed = new ConversationEmbed(getRootEl(), {
1932
- worksheetId: 'worksheetId',
1933
- searchOptions: {
1934
- searchQuery: 'searchQuery',
1935
- },
1936
- enableFlipTooltipToContextMenu: true,
1937
- } as ConversationViewConfig);
1938
-
1939
- appEmbed.render();
1940
- await executeAfterWait(() => {
1941
- expectUrlMatchesWithParams(
1942
- getIFrameSrc(),
1943
- `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&flipTooltipToContextMenuEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
1944
- );
1945
- });
1946
- });
1947
-
1948
- it('ConversationEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when flag is false', async () => {
1949
- const appEmbed = new ConversationEmbed(getRootEl(), {
1950
- worksheetId: 'worksheetId',
1951
- searchOptions: {
1952
- searchQuery: 'searchQuery',
1953
- },
1954
- enableFlipTooltipToContextMenu: false,
1955
- } as ConversationViewConfig);
1956
-
1957
- appEmbed.render();
1958
- await executeAfterWait(() => {
1959
- expectUrlMatchesWithParams(
1960
- getIFrameSrc(),
1961
- `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
1962
- );
1963
- });
1964
- });
1965
-
1966
- it('SearchEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1967
- const dataSources = ['data-source-1'];
1968
- const appEmbed = new SearchEmbed(getRootEl(), {
1969
- ...defaultViewConfig,
1970
- dataSources,
1971
- enableFlipTooltipToContextMenu: true,
1972
- } as SearchViewConfig);
1973
-
1974
- appEmbed.render();
1975
- await executeAfterWait(() => {
1976
- expectUrlMatchesWithParams(
1977
- getIFrameSrc(),
1978
- `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&useLastSelectedSources=false&flipTooltipToContextMenuEnabled=true#/embed/answer`,
1979
- );
1980
- });
1981
- });
1982
-
1983
- it('SearchEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1984
- const dataSources = ['data-source-1'];
1985
- const appEmbed = new SearchEmbed(getRootEl(), {
1986
- ...defaultViewConfig,
1987
- dataSources,
1988
- enableFlipTooltipToContextMenu: false,
1989
- } as SearchViewConfig);
1990
-
1991
- appEmbed.render();
1992
- await executeAfterWait(() => {
1993
- expectUrlMatchesWithParams(
1994
- getIFrameSrc(),
1995
- `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&useLastSelectedSources=false#/embed/answer`,
1996
- );
1997
- });
1998
- });
1999
1857
  });
2000
1858
 
2001
1859
  describe('When destroyed', () => {
@@ -2315,4 +2173,119 @@ describe('Unit test case for ts embed', () => {
2315
2173
  (logger.error as any).mockClear();
2316
2174
  });
2317
2175
  });
2176
+
2177
+ describe('IdleSessionTimeout embedEvent for TrustedAuthTokenCookieless authType with autoLogin true', () => {
2178
+ beforeAll(() => {
2179
+ jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
2180
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
2181
+ init({
2182
+ thoughtSpotHost: 'tshost',
2183
+ customizations: customisations,
2184
+ authType: AuthType.TrustedAuthTokenCookieless,
2185
+ getAuthToken: () => Promise.resolve('test_auth_token2'),
2186
+ autoLogin: true,
2187
+ });
2188
+ });
2189
+
2190
+ test('should handle idle session timeout and send updated auth token', async () => {
2191
+ const mockEmbedEventPayload = {
2192
+ type: EmbedEvent.IdleSessionTimeout,
2193
+ data: {},
2194
+ };
2195
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2196
+ jest.spyOn(baseInstance, 'handleAuth');
2197
+ jest.spyOn(baseInstance, 'notifyAuthFailure');
2198
+
2199
+ searchEmbed.render();
2200
+ const mockPort: any = {
2201
+ postMessage: jest.fn(),
2202
+ };
2203
+ await executeAfterWait(() => {
2204
+ const iframe = getIFrameEl();
2205
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2206
+ });
2207
+ await executeAfterWait(() => {
2208
+ expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2209
+ authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2210
+ );
2211
+ expect(baseInstance.handleAuth).toHaveBeenCalled();
2212
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
2213
+ type: EmbedEvent.IdleSessionTimeout,
2214
+ data: { authToken: 'test_auth_token2' },
2215
+ });
2216
+ });
2217
+ });
2218
+
2219
+ test('should handle idle session timeout and show login failure message if token fetch fails', async () => {
2220
+ init({
2221
+ thoughtSpotHost: 'tshost',
2222
+ customizations: customisations,
2223
+ authType: AuthType.TrustedAuthTokenCookieless,
2224
+ getAuthToken: () => Promise.reject(),
2225
+ autoLogin: true,
2226
+ });
2227
+
2228
+ const mockEmbedEventPayload = {
2229
+ type: EmbedEvent.IdleSessionTimeout,
2230
+ data: {},
2231
+ };
2232
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2233
+ jest.spyOn(baseInstance, 'notifyAuthFailure');
2234
+ searchEmbed.render();
2235
+ const mockPort: any = {
2236
+ postMessage: jest.fn(),
2237
+ };
2238
+ const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
2239
+ await executeAfterWait(() => {
2240
+ const iframe = getIFrameEl();
2241
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2242
+ });
2243
+ await executeAfterWait(() => {
2244
+ expect(getRootEl().innerHTML).toContain('Not logged in');
2245
+ expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2246
+ authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2247
+ );
2248
+ expect(loggerSpy).toHaveBeenCalledTimes(1);
2249
+ });
2250
+
2251
+ jest.spyOn(authService, 'verifyTokenService').mockClear();
2252
+ jest.spyOn(baseInstance, 'notifyAuthFailure').mockClear();
2253
+ });
2254
+
2255
+ test('should handle idle session timeout and show login failure message if handleAuth fails', async () => {
2256
+ init({
2257
+ thoughtSpotHost: 'tshost',
2258
+ customizations: customisations,
2259
+ authType: AuthType.TrustedAuthTokenCookieless,
2260
+ getAuthToken: () => Promise.resolve('test_auth_token2'),
2261
+ autoLogin: true,
2262
+ });
2263
+
2264
+ const mockEmbedEventPayload = {
2265
+ type: EmbedEvent.IdleSessionTimeout,
2266
+ data: {},
2267
+ };
2268
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
2269
+ jest.spyOn(baseInstance, 'notifyAuthFailure');
2270
+ jest.spyOn(authInstance, 'authenticate').mockResolvedValue(false);
2271
+ searchEmbed.render();
2272
+ const mockPort: any = {
2273
+ postMessage: jest.fn(),
2274
+ };
2275
+ const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
2276
+ await executeAfterWait(() => {
2277
+ const iframe = getIFrameEl();
2278
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
2279
+ });
2280
+ await executeAfterWait(() => {
2281
+ expect(baseInstance.notifyAuthFailure).toBeCalledWith(
2282
+ authInstance.AuthFailureType.IDLE_SESSION_TIMEOUT,
2283
+ );
2284
+ expect(loggerSpy).toHaveBeenCalledTimes(0);
2285
+ });
2286
+
2287
+ jest.spyOn(authService, 'verifyTokenService').mockClear();
2288
+ jest.spyOn(baseInstance, 'notifyAuthFailure').mockClear();
2289
+ });
2290
+ });
2318
2291
  });
@@ -139,8 +139,8 @@ export class TsEmbed {
139
139
  protected thoughtSpotHost: string;
140
140
 
141
141
  /*
142
- * This is the base to access ThoughtSpot V2.
143
- */
142
+ * This is the base to access ThoughtSpot V2.
143
+ */
144
144
  protected thoughtSpotV2Base: string;
145
145
 
146
146
  /**
@@ -350,7 +350,7 @@ export class TsEmbed {
350
350
  ? this.viewConfig?.hiddenHomeLeftNavItems
351
351
  : [],
352
352
  customVariablesForThirdPartyTools:
353
- this.embedConfig.customVariablesForThirdPartyTools || {},
353
+ this.embedConfig.customVariablesForThirdPartyTools || {},
354
354
  };
355
355
  }
356
356
 
@@ -401,12 +401,37 @@ export class TsEmbed {
401
401
  notifyAuthFailure(AuthFailureType.EXPIRY);
402
402
  };
403
403
 
404
+ /**
405
+ * Auto Login and send updated authToken to the iFrame to avoid user session logout
406
+ * @param _
407
+ * @param responder
408
+ */
409
+ private idleSessionTimeout = (_: any, responder: any) => {
410
+ handleAuth().then(async () => {
411
+ let authToken = '';
412
+ try {
413
+ authToken = await getAuthenticationToken(this.embedConfig);
414
+ responder({
415
+ type: EmbedEvent.IdleSessionTimeout,
416
+ data: { authToken },
417
+ });
418
+ } catch (e) {
419
+ logger.error(`${ERROR_MESSAGE.INVALID_TOKEN_ERROR} Error : ${e?.message}`);
420
+ processAuthFailure(e, this.isPreRendered ? this.preRenderWrapper : this.el);
421
+ }
422
+ }).catch((e) => {
423
+ logger.error(`Auto Login failed, Error : ${e?.message}`);
424
+ });
425
+ notifyAuthFailure(AuthFailureType.IDLE_SESSION_TIMEOUT);
426
+ };
427
+
404
428
  /**
405
429
  * Register APP_INIT event and sendback init payload
406
430
  */
407
431
  private registerAppInit = () => {
408
432
  this.on(EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true);
409
433
  this.on(EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true);
434
+ this.on(EmbedEvent.IdleSessionTimeout, this.idleSessionTimeout, { start: false }, true);
410
435
  };
411
436
 
412
437
  /**
@@ -414,7 +439,7 @@ export class TsEmbed {
414
439
  * @param query
415
440
  */
416
441
  protected getEmbedBasePath(query: string): string {
417
- let queryString = (query.startsWith('?')) ? query : `?${query}`;
442
+ let queryString = query.startsWith('?') ? query : `?${query}`;
418
443
  if (this.shouldEncodeUrlQueryParams) {
419
444
  queryString = `?base64UrlEncodedFlags=${getEncodedQueryParamsString(
420
445
  queryString.substr(1),
@@ -432,9 +457,7 @@ export class TsEmbed {
432
457
  * @param queryParams
433
458
  * @returns queryParams
434
459
  */
435
- protected getBaseQueryParams(
436
- queryParams: Record<any, any> = {},
437
- ) {
460
+ protected getBaseQueryParams(queryParams: Record<any, any> = {}) {
438
461
  let hostAppUrl = window?.location?.host || '';
439
462
 
440
463
  // The below check is needed because TS Cloud firewall, blocks
@@ -442,14 +465,15 @@ export class TsEmbed {
442
465
  if (hostAppUrl.includes('localhost') || hostAppUrl.includes('127.0.0.1')) {
443
466
  hostAppUrl = 'local-host';
444
467
  }
468
+ const blockNonEmbedFullAppAccess = this.embedConfig.blockNonEmbedFullAppAccess ?? true;
445
469
  queryParams[Param.EmbedApp] = true;
446
470
  queryParams[Param.HostAppUrl] = encodeURIComponent(hostAppUrl);
447
471
  queryParams[Param.ViewPortHeight] = window.innerHeight;
448
472
  queryParams[Param.ViewPortWidth] = window.innerWidth;
449
473
  queryParams[Param.Version] = version;
450
474
  queryParams[Param.AuthType] = this.embedConfig.authType;
451
- queryParams[Param.blockNonEmbedFullAppAccess] = this.embedConfig.blockNonEmbedFullAppAccess
452
- ?? true;
475
+ queryParams[Param.blockNonEmbedFullAppAccess] = blockNonEmbedFullAppAccess;
476
+ queryParams[Param.AutoLogin] = this.embedConfig.autoLogin;
453
477
  if (this.embedConfig.disableLoginRedirect === true || this.embedConfig.autoLogin === true) {
454
478
  queryParams[Param.DisableLoginRedirect] = true;
455
479
  }
@@ -488,7 +512,6 @@ export class TsEmbed {
488
512
  insertInToSlide,
489
513
  disableRedirectionLinksInNewTab,
490
514
  overrideOrgId,
491
- enableFlipTooltipToContextMenu = false,
492
515
  } = this.viewConfig;
493
516
 
494
517
  const { additionalFlags: additionalFlagsFromInit } = this.embedConfig;
@@ -498,10 +521,6 @@ export class TsEmbed {
498
521
  ...additionalFlagsFromView,
499
522
  };
500
523
 
501
- if (enableFlipTooltipToContextMenu) {
502
- queryParams[Param.EnableFlipTooltipToContextMenu] = enableFlipTooltipToContextMenu;
503
- }
504
-
505
524
  if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
506
525
  this.handleError('You cannot have both hidden actions and visible actions');
507
526
  return queryParams;
@@ -541,8 +560,8 @@ export class TsEmbed {
541
560
  queryParams[Param.ContextMenuTrigger] = 'both';
542
561
  }
543
562
 
544
- const spriteUrl = customizations?.iconSpriteUrl
545
- || this.embedConfig.customizations?.iconSpriteUrl;
563
+ const embedCustomizations = this.embedConfig.customizations;
564
+ const spriteUrl = customizations?.iconSpriteUrl || embedCustomizations?.iconSpriteUrl;
546
565
  if (spriteUrl) {
547
566
  queryParams[Param.IconSpriteUrl] = spriteUrl.replace('https://', '');
548
567
  }
@@ -627,11 +646,8 @@ export class TsEmbed {
627
646
  // @ts-ignore
628
647
  iFrame.allow = 'clipboard-read; clipboard-write; fullscreen;';
629
648
 
630
- const {
631
- height: frameHeight,
632
- width: frameWidth,
633
- ...restParams
634
- } = this.viewConfig.frameParams || {};
649
+ const frameParams = this.viewConfig.frameParams;
650
+ const { height: frameHeight, width: frameWidth, ...restParams } = frameParams || {};
635
651
  const width = getCssDimension(frameWidth || DEFAULT_EMBED_WIDTH);
636
652
  const height = getCssDimension(frameHeight || DEFAULT_EMBED_HEIGHT);
637
653
  setAttributes(iFrame, restParams);
@@ -753,8 +769,8 @@ export class TsEmbed {
753
769
 
754
770
  protected connectPreRendered(): boolean {
755
771
  const preRenderIds = this.getPreRenderIds();
756
- this.preRenderWrapper = this.preRenderWrapper
757
- || document.getElementById(preRenderIds.wrapper);
772
+ const preRenderWrapperElement = document.getElementById(preRenderIds.wrapper);
773
+ this.preRenderWrapper = this.preRenderWrapper || preRenderWrapperElement;
758
774
 
759
775
  this.preRenderChild = this.preRenderChild || document.getElementById(preRenderIds.child);
760
776
 
@@ -1033,7 +1049,7 @@ export class TsEmbed {
1033
1049
  */
1034
1050
  public async trigger<HostEventT extends HostEvent, PayloadT>(
1035
1051
  messageType: HostEventT,
1036
- data: TriggerPayload<PayloadT, HostEventT> = ({} as any),
1052
+ data: TriggerPayload<PayloadT, HostEventT> = {} as any,
1037
1053
  ): Promise<TriggerResponse<PayloadT, HostEventT>> {
1038
1054
  uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_TRIGGER}-${messageType}`);
1039
1055
 
@@ -1182,11 +1198,11 @@ export class TsEmbed {
1182
1198
  ) {
1183
1199
  logger.warn(
1184
1200
  `${viewConfig.embedComponentType || 'Component'} was pre-rendered with `
1185
- + `"${key}" as "${JSON.stringify(preRenderedObject.viewConfig[key])}" `
1186
- + `but a different value "${JSON.stringify(viewConfig[key])}" `
1187
- + 'was passed to the Embed component. '
1188
- + 'The new value provided is ignored, the value provided during '
1189
- + 'preRender is used.',
1201
+ + `"${key}" as "${JSON.stringify(preRenderedObject.viewConfig[key])}" `
1202
+ + `but a different value "${JSON.stringify(viewConfig[key])}" `
1203
+ + 'was passed to the Embed component. '
1204
+ + 'The new value provided is ignored, the value provided during '
1205
+ + 'preRender is used.',
1190
1206
  );
1191
1207
  }
1192
1208
  });
@@ -1351,7 +1367,7 @@ export class V1Embed extends TsEmbed {
1351
1367
  const filterQuery = getFilterQuery(runtimeFilters || []);
1352
1368
  queryString = [filterQuery, queryString].filter(Boolean).join('&');
1353
1369
  }
1354
- return (this.viewConfig.enableV2Shell_experimental)
1370
+ return this.viewConfig.enableV2Shell_experimental
1355
1371
  ? this.getEmbedBasePath(queryString)
1356
1372
  : this.getV1EmbedBasePath(queryString);
1357
1373
  }
package/src/types.ts CHANGED
@@ -535,7 +535,12 @@ export interface EmbedConfig {
535
535
  suppressErrorAlerts?: boolean;
536
536
 
537
537
  /**
538
- * Log level for the SDK.
538
+ * Suppress or show specific types of logs in the console output.
539
+ * For example, `LogLevel.ERROR` shows only Visual Embed SDK and
540
+ * ThoughtSpot application errors and suppresses
541
+ * other logs such as warnings, information alerts,
542
+ * and debug messages in the console output.
543
+ *
539
544
  * @default LogLevel.ERROR
540
545
  * @example
541
546
  * ```js
@@ -1119,13 +1124,6 @@ export interface ViewConfig {
1119
1124
  * @version SDK: 1.35.0 | ThoughtSpot: 10.5.0.cl
1120
1125
  */
1121
1126
  overrideOrgId?: number;
1122
- /**
1123
- * Flag to enhance the visual effects of charts
1124
- * This feature is a beta release for 10.6
1125
- * @default false
1126
- * @version SDK: 1.36.0 | ThoughtSpot: 10.6.0.cl
1127
- */
1128
- enableFlipTooltipToContextMenu?: boolean;
1129
1127
  }
1130
1128
 
1131
1129
  /**
@@ -1594,6 +1592,13 @@ export enum EmbedEvent {
1594
1592
  * @hidden
1595
1593
  */
1596
1594
  AuthFailure = 'ThoughtspotAuthFailure',
1595
+
1596
+ /**
1597
+ * ThoughtSpot failed to re validate the auth session.
1598
+ * @hidden
1599
+ */
1600
+ IdleSessionTimeout = 'IdleSessionTimeout',
1601
+
1597
1602
  /**
1598
1603
  * ThoughtSpot failed to validate the auth session.
1599
1604
  * @hidden
@@ -2317,6 +2322,19 @@ export enum EmbedEvent {
2317
2322
  * @version SDK: 1.35.12 | ThoughtSpot: 10.7.0.cl
2318
2323
  */
2319
2324
  TableVizRendered = 'TableVizRendered',
2325
+ /**
2326
+ * Emitted when the liveboard is created from pin modal or liveboard list page.
2327
+ * You can use this event as a hook to trigger
2328
+ * other events on liveboard creation.
2329
+ *
2330
+ * ```js
2331
+ * liveboardEmbed.on(EmbedEvent.CreateLiveboard, (payload) => {
2332
+ * console.log('payload', payload);
2333
+ * })
2334
+ *```
2335
+ * @version SDK : 1.36.0 | ThoughtSpot : 10.8.0.cl
2336
+ */
2337
+ CreateLiveboard = 'createLiveboard',
2320
2338
  }
2321
2339
 
2322
2340
  /**
@@ -3323,6 +3341,7 @@ export enum Param {
3323
3341
  HideResult = 'hideResult',
3324
3342
  UseLastSelectedDataSource = 'useLastSelectedSources',
3325
3343
  Tag = 'tag',
3344
+ AutoLogin = 'autoLogin',
3326
3345
  searchTokenString = 'searchTokenString',
3327
3346
  executeSearch = 'executeSearch',
3328
3347
  fullHeight = 'isFullHeightPinboard',
@@ -3405,10 +3424,10 @@ export enum Param {
3405
3424
  SpotterEnabled = 'isSpotterExperienceEnabled',
3406
3425
  IsUnifiedSearchExperienceEnabled = 'isUnifiedSearchExperienceEnabled',
3407
3426
  OverrideOrgId = 'orgId',
3408
- EnableFlipTooltipToContextMenu = 'flipTooltipToContextMenuEnabled',
3409
3427
  OauthPollingInterval = 'oAuthPollingInterval',
3410
3428
  IsForceRedirect = 'isForceRedirect',
3411
3429
  DataSourceId = 'dataSourceId',
3430
+ ShowSpotterLimitations = 'showSpotterLimitations',
3412
3431
  }
3413
3432
 
3414
3433
  /**
@@ -4685,9 +4704,17 @@ export interface CustomActionPayload {
4685
4704
  vizId?: string;
4686
4705
  }
4687
4706
 
4707
+ /**
4708
+ * Enum options to show or suppress Visual Embed SDK and
4709
+ * ThoughtSpot application logs in the console output.
4710
+ * This attribute doesn't support suppressing
4711
+ * browser warnings or errors.
4712
+ */
4713
+
4688
4714
  export enum LogLevel {
4689
4715
  /**
4690
- * No logs will be logged in the console.
4716
+ * No application or SDK-related logs will be logged
4717
+ * in the console output.
4691
4718
  * @example
4692
4719
  * ```js
4693
4720
  * init({
@@ -4699,7 +4726,7 @@ export enum LogLevel {
4699
4726
  */
4700
4727
  SILENT = 'SILENT',
4701
4728
  /**
4702
- * Only ERROR logs will be logged in the console.
4729
+ * Log only errors in the console output.
4703
4730
  * @example
4704
4731
  * ```js
4705
4732
  * init({
@@ -4711,7 +4738,7 @@ export enum LogLevel {
4711
4738
  */
4712
4739
  ERROR = 'ERROR',
4713
4740
  /**
4714
- * Only WARN and ERROR logs will be logged in the console.
4741
+ * Log only warnings and errors in the console output.
4715
4742
  * @example
4716
4743
  * ```js
4717
4744
  * init({
@@ -4723,7 +4750,8 @@ export enum LogLevel {
4723
4750
  */
4724
4751
  WARN = 'WARN',
4725
4752
  /**
4726
- * Only INFO, WARN, and ERROR logs will be logged in the console.
4753
+ * Log only the information alerts, warnings, and errors
4754
+ * in the console output.
4727
4755
  * @example
4728
4756
  * ```js
4729
4757
  * init({
@@ -4736,7 +4764,8 @@ export enum LogLevel {
4736
4764
  INFO = 'INFO',
4737
4765
 
4738
4766
  /**
4739
- * Only DEBUG, INFO, WARN, and ERROR logs will be logged in the console.
4767
+ * Log debug messages, warnings, information alerts,
4768
+ * and errors in the console output.
4740
4769
  * @example
4741
4770
  * ```js
4742
4771
  * init({
@@ -4748,7 +4777,7 @@ export enum LogLevel {
4748
4777
  */
4749
4778
  DEBUG = 'DEBUG',
4750
4779
  /**
4751
- * All logs will be logged in the console.
4780
+ * All logs will be logged in the browser console.
4752
4781
  * @example
4753
4782
  * ```js
4754
4783
  * init({