@thoughtspot/visual-embed-sdk 1.28.0-alpha.1 → 1.28.0-alpha.3

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 (207) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/auth.d.ts +16 -1
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +5 -1
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/auth.spec.d.ts.map +1 -1
  7. package/cjs/src/auth.spec.js +9 -0
  8. package/cjs/src/auth.spec.js.map +1 -1
  9. package/cjs/src/embed/app.d.ts +18 -4
  10. package/cjs/src/embed/app.d.ts.map +1 -1
  11. package/cjs/src/embed/app.js +2 -2
  12. package/cjs/src/embed/app.js.map +1 -1
  13. package/cjs/src/embed/app.spec.js +19 -1
  14. package/cjs/src/embed/app.spec.js.map +1 -1
  15. package/cjs/src/embed/base.d.ts.map +1 -1
  16. package/cjs/src/embed/base.js +0 -3
  17. package/cjs/src/embed/base.js.map +1 -1
  18. package/cjs/src/embed/embed.spec.js +0 -15
  19. package/cjs/src/embed/embed.spec.js.map +1 -1
  20. package/cjs/src/embed/liveboard.d.ts +7 -1
  21. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  22. package/cjs/src/embed/liveboard.js +2 -2
  23. package/cjs/src/embed/liveboard.js.map +1 -1
  24. package/cjs/src/embed/liveboard.spec.js +20 -1
  25. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  26. package/cjs/src/embed/pinboard.spec.js +20 -1
  27. package/cjs/src/embed/pinboard.spec.js.map +1 -1
  28. package/cjs/src/embed/sage.d.ts +1 -1
  29. package/cjs/src/embed/sage.d.ts.map +1 -1
  30. package/cjs/src/embed/sage.js +2 -2
  31. package/cjs/src/embed/sage.js.map +1 -1
  32. package/cjs/src/embed/search-bar.d.ts +1 -1
  33. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  34. package/cjs/src/embed/search-bar.js +2 -2
  35. package/cjs/src/embed/search-bar.js.map +1 -1
  36. package/cjs/src/embed/search.d.ts +1 -1
  37. package/cjs/src/embed/search.d.ts.map +1 -1
  38. package/cjs/src/embed/search.js +3 -3
  39. package/cjs/src/embed/search.js.map +1 -1
  40. package/cjs/src/embed/search.spec.js +25 -1
  41. package/cjs/src/embed/search.spec.js.map +1 -1
  42. package/cjs/src/embed/ts-embed-trigger.spec.d.ts +2 -0
  43. package/cjs/src/embed/ts-embed-trigger.spec.d.ts.map +1 -0
  44. package/cjs/src/embed/ts-embed-trigger.spec.js +34 -0
  45. package/cjs/src/embed/ts-embed-trigger.spec.js.map +1 -0
  46. package/cjs/src/embed/ts-embed.d.ts +1 -1
  47. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  48. package/cjs/src/embed/ts-embed.js +14 -11
  49. package/cjs/src/embed/ts-embed.js.map +1 -1
  50. package/cjs/src/embed/ts-embed.spec.js +47 -17
  51. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  52. package/cjs/src/index.d.ts +2 -1
  53. package/cjs/src/index.d.ts.map +1 -1
  54. package/cjs/src/index.js +3 -1
  55. package/cjs/src/index.js.map +1 -1
  56. package/cjs/src/react/index.spec.js +1 -1
  57. package/cjs/src/react/index.spec.js.map +1 -1
  58. package/cjs/src/test/test-utils.d.ts +1 -0
  59. package/cjs/src/test/test-utils.d.ts.map +1 -1
  60. package/cjs/src/test/test-utils.js +10 -1
  61. package/cjs/src/test/test-utils.js.map +1 -1
  62. package/cjs/src/tokenizedFetch.d.ts +9 -0
  63. package/cjs/src/tokenizedFetch.d.ts.map +1 -1
  64. package/cjs/src/tokenizedFetch.js +9 -0
  65. package/cjs/src/tokenizedFetch.js.map +1 -1
  66. package/cjs/src/types.d.ts +178 -37
  67. package/cjs/src/types.d.ts.map +1 -1
  68. package/cjs/src/types.js +138 -21
  69. package/cjs/src/types.js.map +1 -1
  70. package/cjs/src/utils/authService/authService.d.ts.map +1 -1
  71. package/cjs/src/utils/authService/authService.js +9 -3
  72. package/cjs/src/utils/authService/authService.js.map +1 -1
  73. package/cjs/src/utils/authService/authService.spec.js +22 -0
  74. package/cjs/src/utils/authService/authService.spec.js.map +1 -1
  75. package/dist/src/auth.d.ts +16 -1
  76. package/dist/src/auth.d.ts.map +1 -1
  77. package/dist/src/auth.spec.d.ts.map +1 -1
  78. package/dist/src/embed/app.d.ts +18 -4
  79. package/dist/src/embed/app.d.ts.map +1 -1
  80. package/dist/src/embed/base.d.ts.map +1 -1
  81. package/dist/src/embed/liveboard.d.ts +7 -1
  82. package/dist/src/embed/liveboard.d.ts.map +1 -1
  83. package/dist/src/embed/sage.d.ts +1 -1
  84. package/dist/src/embed/sage.d.ts.map +1 -1
  85. package/dist/src/embed/search-bar.d.ts +1 -1
  86. package/dist/src/embed/search-bar.d.ts.map +1 -1
  87. package/dist/src/embed/search.d.ts +1 -1
  88. package/dist/src/embed/search.d.ts.map +1 -1
  89. package/dist/src/embed/ts-embed-trigger.spec.d.ts +2 -0
  90. package/dist/src/embed/ts-embed-trigger.spec.d.ts.map +1 -0
  91. package/dist/src/embed/ts-embed.d.ts +1 -1
  92. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  93. package/dist/src/index.d.ts +2 -1
  94. package/dist/src/index.d.ts.map +1 -1
  95. package/dist/src/test/test-utils.d.ts +1 -0
  96. package/dist/src/test/test-utils.d.ts.map +1 -1
  97. package/dist/src/tokenizedFetch.d.ts +9 -0
  98. package/dist/src/tokenizedFetch.d.ts.map +1 -1
  99. package/dist/src/types.d.ts +178 -37
  100. package/dist/src/types.d.ts.map +1 -1
  101. package/dist/src/utils/authService/authService.d.ts.map +1 -1
  102. package/dist/tsembed-react.es.js +186 -48
  103. package/dist/tsembed-react.js +186 -48
  104. package/dist/tsembed.es.js +187 -52
  105. package/dist/tsembed.js +187 -51
  106. package/dist/visual-embed-sdk-react-full.d.ts +235 -48
  107. package/dist/visual-embed-sdk-react.d.ts +235 -48
  108. package/dist/visual-embed-sdk.d.ts +235 -48
  109. package/lib/package.json +1 -1
  110. package/lib/src/auth.d.ts +16 -1
  111. package/lib/src/auth.d.ts.map +1 -1
  112. package/lib/src/auth.js +5 -1
  113. package/lib/src/auth.js.map +1 -1
  114. package/lib/src/auth.spec.d.ts.map +1 -1
  115. package/lib/src/auth.spec.js +9 -0
  116. package/lib/src/auth.spec.js.map +1 -1
  117. package/lib/src/embed/app.d.ts +18 -4
  118. package/lib/src/embed/app.d.ts.map +1 -1
  119. package/lib/src/embed/app.js +2 -2
  120. package/lib/src/embed/app.js.map +1 -1
  121. package/lib/src/embed/app.spec.js +19 -1
  122. package/lib/src/embed/app.spec.js.map +1 -1
  123. package/lib/src/embed/base.d.ts.map +1 -1
  124. package/lib/src/embed/base.js +0 -3
  125. package/lib/src/embed/base.js.map +1 -1
  126. package/lib/src/embed/embed.spec.js +2 -17
  127. package/lib/src/embed/embed.spec.js.map +1 -1
  128. package/lib/src/embed/liveboard.d.ts +7 -1
  129. package/lib/src/embed/liveboard.d.ts.map +1 -1
  130. package/lib/src/embed/liveboard.js +2 -2
  131. package/lib/src/embed/liveboard.js.map +1 -1
  132. package/lib/src/embed/liveboard.spec.js +20 -1
  133. package/lib/src/embed/liveboard.spec.js.map +1 -1
  134. package/lib/src/embed/pinboard.spec.js +20 -1
  135. package/lib/src/embed/pinboard.spec.js.map +1 -1
  136. package/lib/src/embed/sage.d.ts +1 -1
  137. package/lib/src/embed/sage.d.ts.map +1 -1
  138. package/lib/src/embed/sage.js +2 -2
  139. package/lib/src/embed/sage.js.map +1 -1
  140. package/lib/src/embed/search-bar.d.ts +1 -1
  141. package/lib/src/embed/search-bar.d.ts.map +1 -1
  142. package/lib/src/embed/search-bar.js +2 -2
  143. package/lib/src/embed/search-bar.js.map +1 -1
  144. package/lib/src/embed/search.d.ts +1 -1
  145. package/lib/src/embed/search.d.ts.map +1 -1
  146. package/lib/src/embed/search.js +3 -3
  147. package/lib/src/embed/search.js.map +1 -1
  148. package/lib/src/embed/search.spec.js +25 -1
  149. package/lib/src/embed/search.spec.js.map +1 -1
  150. package/lib/src/embed/ts-embed-trigger.spec.d.ts +2 -0
  151. package/lib/src/embed/ts-embed-trigger.spec.d.ts.map +1 -0
  152. package/lib/src/embed/ts-embed-trigger.spec.js +32 -0
  153. package/lib/src/embed/ts-embed-trigger.spec.js.map +1 -0
  154. package/lib/src/embed/ts-embed.d.ts +1 -1
  155. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  156. package/lib/src/embed/ts-embed.js +14 -11
  157. package/lib/src/embed/ts-embed.js.map +1 -1
  158. package/lib/src/embed/ts-embed.spec.js +41 -11
  159. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  160. package/lib/src/index.d.ts +2 -1
  161. package/lib/src/index.d.ts.map +1 -1
  162. package/lib/src/index.js +2 -1
  163. package/lib/src/index.js.map +1 -1
  164. package/lib/src/react/index.spec.js +1 -1
  165. package/lib/src/react/index.spec.js.map +1 -1
  166. package/lib/src/test/test-utils.d.ts +1 -0
  167. package/lib/src/test/test-utils.d.ts.map +1 -1
  168. package/lib/src/test/test-utils.js +8 -0
  169. package/lib/src/test/test-utils.js.map +1 -1
  170. package/lib/src/tokenizedFetch.d.ts +9 -0
  171. package/lib/src/tokenizedFetch.d.ts.map +1 -1
  172. package/lib/src/tokenizedFetch.js +9 -0
  173. package/lib/src/tokenizedFetch.js.map +1 -1
  174. package/lib/src/types.d.ts +178 -37
  175. package/lib/src/types.d.ts.map +1 -1
  176. package/lib/src/types.js +138 -21
  177. package/lib/src/types.js.map +1 -1
  178. package/lib/src/utils/authService/authService.d.ts.map +1 -1
  179. package/lib/src/utils/authService/authService.js +9 -3
  180. package/lib/src/utils/authService/authService.js.map +1 -1
  181. package/lib/src/utils/authService/authService.spec.js +22 -0
  182. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  183. package/lib/src/visual-embed-sdk.d.ts +238 -48
  184. package/package.json +1 -1
  185. package/src/auth.spec.ts +10 -0
  186. package/src/auth.ts +21 -2
  187. package/src/embed/app.spec.ts +24 -1
  188. package/src/embed/app.ts +19 -5
  189. package/src/embed/base.ts +1 -5
  190. package/src/embed/embed.spec.ts +0 -18
  191. package/src/embed/liveboard.spec.ts +24 -1
  192. package/src/embed/liveboard.ts +8 -2
  193. package/src/embed/pinboard.spec.ts +24 -1
  194. package/src/embed/sage.ts +2 -2
  195. package/src/embed/search-bar.tsx +2 -2
  196. package/src/embed/search.spec.ts +29 -1
  197. package/src/embed/search.ts +3 -3
  198. package/src/embed/ts-embed-trigger.spec.ts +39 -0
  199. package/src/embed/ts-embed.spec.ts +49 -16
  200. package/src/embed/ts-embed.ts +21 -16
  201. package/src/index.ts +2 -0
  202. package/src/react/index.spec.tsx +1 -0
  203. package/src/test/test-utils.ts +9 -0
  204. package/src/tokenizedFetch.ts +9 -0
  205. package/src/types.ts +179 -34
  206. package/src/utils/authService/authService.spec.ts +27 -0
  207. package/src/utils/authService/authService.ts +14 -13
@@ -213,6 +213,7 @@ describe('App embed tests', () => {
213
213
  values: [1000],
214
214
  },
215
215
  ],
216
+ excludeRuntimeFiltersfromURL: false,
216
217
  } as AppViewConfig);
217
218
 
218
219
  appEmbed.render();
@@ -224,7 +225,7 @@ describe('App embed tests', () => {
224
225
  });
225
226
  });
226
227
 
227
- test('should not apply runtime filters if excludeRuntimeFiltersfromURL is true', async () => {
228
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
228
229
  const appEmbed = new AppEmbed(getRootEl(), {
229
230
  ...defaultViewConfig,
230
231
  showPrimaryNavbar: true,
@@ -247,6 +248,28 @@ describe('App embed tests', () => {
247
248
  });
248
249
  });
249
250
 
251
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is undefined', async () => {
252
+ const appEmbed = new AppEmbed(getRootEl(), {
253
+ ...defaultViewConfig,
254
+ showPrimaryNavbar: true,
255
+ runtimeFilters: [
256
+ {
257
+ columnName: 'sales',
258
+ operator: RuntimeFilterOp.EQ,
259
+ values: [1000],
260
+ },
261
+ ],
262
+ } as AppViewConfig);
263
+
264
+ appEmbed.render();
265
+ await executeAfterWait(() => {
266
+ expectUrlMatchesWithParams(
267
+ getIFrameSrc(),
268
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=false&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
269
+ );
270
+ });
271
+ });
272
+
250
273
  test('should disable and hide actions', async () => {
251
274
  const appEmbed = new AppEmbed(getRootEl(), {
252
275
  ...defaultViewConfig,
package/src/embed/app.ts CHANGED
@@ -69,8 +69,12 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
69
69
  * nav-bars are visible, this flag will only hide the homepage left nav-bar.
70
70
  * The showPrimaryNavbar flag takes precedence over the hideHomepageLeftNav.
71
71
  *
72
+ * **Note**: This option does not apply to the classic homepage.
73
+ * To access the updated modular homepage, set
74
+ * `modularHomeExperience` to `true` (available in Early Access from 9.12 forward).
75
+ *
72
76
  * @default false
73
- * @version SDK: 1.27.0 | Thoughtspot: 9.8.0.cl
77
+ * @version SDK: 1.27.9 | Thoughtspot: 9.12.0.cl
74
78
  */
75
79
  hideHomepageLeftNav?: boolean;
76
80
  /**
@@ -81,11 +85,21 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
81
85
  /**
82
86
  * Control the visibility of the application switcher button on the nav-bar.
83
87
  * By default, the application switcher is shown.
88
+ *
89
+ * **Note**: This option does not apply to the classic homepage.
90
+ * To access the updated modular homepage, set
91
+ * `modularHomeExperience` to `true` (available in Early Access from 9.12 forward).
92
+ *
84
93
  */
85
94
  hideApplicationSwitcher?: boolean;
86
95
  /**
87
96
  * Control the visibility of the Org switcher button on the nav-bar.
88
97
  * By default, the Org switcher button is shown.
98
+ *
99
+ * **Note**: This option does not apply to the classic homepage.
100
+ * To access the updated modular homepage, set
101
+ * `modularHomeExperience` to `true` (available in Early Access from 9.12 forward).
102
+ *
89
103
  */
90
104
  hideOrgSwitcher?: boolean;
91
105
  /**
@@ -172,10 +186,10 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
172
186
  */
173
187
  showLiveboardDescription?: boolean;
174
188
  /**
175
- * Flag to control new Modular Home experience
189
+ * Flag to control new Modular Home experience.
176
190
  *
177
191
  * @default false
178
- * @version SDK: 1.27.0 | Thoughtspot: 9.8.0.cl
192
+ * @version SDK: 1.27.9 | Thoughtspot: 9.12.0.cl
179
193
  */
180
194
  modularHomeExperience?: boolean;
181
195
  /**
@@ -414,10 +428,10 @@ export class AppEmbed extends V1Embed {
414
428
  * @param renderOptions An object containing the page ID
415
429
  * to be embedded.
416
430
  */
417
- public render(): AppEmbed {
431
+ public async render(): Promise<AppEmbed> {
418
432
  super.render();
419
433
  const src = this.getIFrameSrc();
420
- this.renderV1Embed(src);
434
+ await this.renderV1Embed(src);
421
435
 
422
436
  return this;
423
437
  }
package/src/embed/base.ts CHANGED
@@ -133,10 +133,6 @@ function sanity(embedConfig: EmbedConfig) {
133
133
  throw new Error('ThoughtSpot host not provided');
134
134
  }
135
135
  if (embedConfig.authType === AuthType.TrustedAuthToken) {
136
- if (!embedConfig.username) {
137
- throw new Error('Username not provided with Trusted auth');
138
- }
139
-
140
136
  if (!embedConfig.authEndpoint && typeof embedConfig.getAuthToken !== 'function') {
141
137
  throw new Error('Trusted auth should provide either authEndpoint or getAuthToken');
142
138
  }
@@ -253,7 +249,7 @@ export const renderInQueue = (fn: (next?: (val?: any) => void) => Promise<any>):
253
249
  return renderQueue;
254
250
  }
255
251
  // Sending an empty function to keep it consistent with the above usage.
256
- return fn(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
252
+ return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
257
253
  };
258
254
 
259
255
  /**
@@ -50,24 +50,6 @@ describe('test view config', () => {
50
50
  expect(iframe.style.height).toBe(`${height}px`);
51
51
  });
52
52
  });
53
-
54
- test('trying to register event handler after render should throw error', async () => {
55
- spyOn(logger, 'error');
56
- const onErrorSpy = jest.fn();
57
- const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
58
- searchEmbed
59
- .on(EmbedEvent.Error, onErrorSpy)
60
- .render()
61
- .on(EmbedEvent.Load, () => null);
62
- await executeAfterWait(() => {
63
- expect(onErrorSpy).toHaveBeenCalledWith(
64
- {
65
- error: 'Please register event handlers before calling render',
66
- },
67
- expect.any(Function),
68
- );
69
- }, EVENT_WAIT_TIME);
70
- });
71
53
  });
72
54
 
73
55
  describe('Custom CSS Url', () => {
@@ -182,6 +182,7 @@ describe('Liveboard/viz embed tests', () => {
182
182
  values: [1000],
183
183
  },
184
184
  ],
185
+ excludeRuntimeFiltersfromURL: false,
185
186
  } as LiveboardViewConfig);
186
187
  liveboardEmbed.render();
187
188
  await executeAfterWait(() => {
@@ -208,7 +209,29 @@ describe('Liveboard/viz embed tests', () => {
208
209
  });
209
210
  });
210
211
 
211
- test('should not apply runtime filters if excludeRuntimeFiltersfromURL is true', async () => {
212
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
213
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
214
+ ...defaultViewConfig,
215
+ liveboardId,
216
+ vizId,
217
+ runtimeFilters: [
218
+ {
219
+ columnName: 'sales',
220
+ operator: RuntimeFilterOp.EQ,
221
+ values: [1000],
222
+ },
223
+ ],
224
+ } as LiveboardViewConfig);
225
+ liveboardEmbed.render();
226
+ await executeAfterWait(() => {
227
+ expectUrlMatchesWithParams(
228
+ getIFrameSrc(),
229
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${liveboardId}/${vizId}`,
230
+ );
231
+ });
232
+ });
233
+
234
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is undefined', async () => {
212
235
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
213
236
  ...defaultViewConfig,
214
237
  liveboardId,
@@ -32,6 +32,12 @@ export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageMod
32
32
  /**
33
33
  * If set to true, the embedded object container dynamically resizes
34
34
  * according to the height of the Liveboard.
35
+ * **Note**: Using fullHeight loads all visualizations on the
36
+ * Liveboard simultaneously, which results in multiple warehouse
37
+ * queries and potentially a longer wait for the topmost
38
+ * visualizations to display on the screen.
39
+ * Setting `fullHeight` to `false` fetches visualizations
40
+ * incrementally as users scroll the page to view the charts and tables.
35
41
  *
36
42
  * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 7.2.1
37
43
  */
@@ -362,11 +368,11 @@ export class LiveboardEmbed extends V1Embed {
362
368
  * @param renderOptions An object specifying the Liveboard ID,
363
369
  * visualization ID and the runtime filters.
364
370
  */
365
- public render(): LiveboardEmbed {
371
+ public async render(): Promise<LiveboardEmbed> {
366
372
  super.render();
367
373
 
368
374
  const src = this.getIFrameSrc();
369
- this.renderV1Embed(src);
375
+ await this.renderV1Embed(src);
370
376
 
371
377
  return this;
372
378
  }
@@ -169,6 +169,7 @@ describe('Pinboard/viz embed tests', () => {
169
169
  values: [1000],
170
170
  },
171
171
  ],
172
+ excludeRuntimeFiltersfromURL: false,
172
173
  } as LiveboardViewConfig);
173
174
  pinboardEmbed.render();
174
175
  await executeAfterWait(() => {
@@ -179,7 +180,7 @@ describe('Pinboard/viz embed tests', () => {
179
180
  });
180
181
  });
181
182
 
182
- test('should not apply runtime filters if excludeRuntimeFiltersfromURL is true', async () => {
183
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
183
184
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
184
185
  ...defaultViewConfig,
185
186
  pinboardId,
@@ -202,6 +203,28 @@ describe('Pinboard/viz embed tests', () => {
202
203
  });
203
204
  });
204
205
 
206
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is undefined', async () => {
207
+ const liveboardEmbed = new PinboardEmbed(getRootEl(), {
208
+ ...defaultViewConfig,
209
+ pinboardId,
210
+ vizId,
211
+ runtimeFilters: [
212
+ {
213
+ columnName: 'sales',
214
+ operator: RuntimeFilterOp.EQ,
215
+ values: [1000],
216
+ },
217
+ ],
218
+ } as LiveboardViewConfig);
219
+ liveboardEmbed.render();
220
+ await executeAfterWait(() => {
221
+ expectUrlMatchesWithParams(
222
+ getIFrameSrc(),
223
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${pinboardId}/${vizId}`,
224
+ );
225
+ });
226
+ });
227
+
205
228
  test('should register event handler to adjust iframe height', async () => {
206
229
  const pinboardEmbed = new PinboardEmbed(getRootEl(), {
207
230
  ...defaultViewConfig,
package/src/embed/sage.ts CHANGED
@@ -237,11 +237,11 @@ export class SageEmbed extends V1Embed {
237
237
  *
238
238
  * @returns {SageEmbed} Eureka/Sage embed
239
239
  */
240
- public render(): SageEmbed {
240
+ public async render(): Promise<SageEmbed> {
241
241
  super.render();
242
242
 
243
243
  const src = this.getIFrameSrc();
244
- this.renderV1Embed(src);
244
+ await this.renderV1Embed(src);
245
245
 
246
246
  return this;
247
247
  }
@@ -130,11 +130,11 @@ export class SearchBarEmbed extends TsEmbed {
130
130
  /**
131
131
  * Render the embedded ThoughtSpot search
132
132
  */
133
- public render(): SearchBarEmbed {
133
+ public async render(): Promise<SearchBarEmbed> {
134
134
  super.render();
135
135
 
136
136
  const src = this.getIFrameSrc();
137
- this.renderIFrame(src);
137
+ await this.renderIFrame(src);
138
138
  return this;
139
139
  }
140
140
  }
@@ -178,6 +178,7 @@ describe('Search embed tests', () => {
178
178
  values: ['berkeley'],
179
179
  },
180
180
  ],
181
+ excludeRuntimeFiltersfromURL: false,
181
182
  });
182
183
  searchEmbed.render();
183
184
  await executeAfterWait(() => {
@@ -188,7 +189,7 @@ describe('Search embed tests', () => {
188
189
  });
189
190
  });
190
191
 
191
- test('should not add runtime filters if excludeRuntimeFiltersfromURL is true', async () => {
192
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
192
193
  const dataSources = ['data-source-1'];
193
194
  const searchOptions = {
194
195
  searchTokenString: '[commit date][revenue]',
@@ -216,6 +217,33 @@ describe('Search embed tests', () => {
216
217
  });
217
218
  });
218
219
 
220
+ test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is undefined', async () => {
221
+ const dataSources = ['data-source-1'];
222
+ const searchOptions = {
223
+ searchTokenString: '[commit date][revenue]',
224
+ };
225
+ const searchEmbed = new SearchEmbed(getRootEl(), {
226
+ ...defaultViewConfig,
227
+ hideDataSources: true,
228
+ dataSources,
229
+ searchOptions,
230
+ runtimeFilters: [
231
+ {
232
+ columnName: 'city',
233
+ operator: RuntimeFilterOp.EQ,
234
+ values: ['berkeley'],
235
+ },
236
+ ],
237
+ });
238
+ searchEmbed.render();
239
+ await executeAfterWait(() => {
240
+ expectUrlMatchesWithParams(
241
+ getIFrameSrc(),
242
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&searchTokenString=%5Bcommit%20date%5D%5Brevenue%5D&dataSourceMode=hide&useLastSelectedSources=false${prefixParams}#/embed/answer`,
243
+ );
244
+ });
245
+ });
246
+
219
247
  test('Should add dataSource', async () => {
220
248
  const dataSource = 'data-source-1';
221
249
  const searchOptions = {
@@ -196,7 +196,7 @@ export class SearchEmbed extends TsEmbed {
196
196
  runtimeFilters,
197
197
  dataSource,
198
198
  dataSources,
199
- excludeRuntimeFiltersfromURL,
199
+ excludeRuntimeFiltersfromURL = true,
200
200
  hideSearchBar,
201
201
  dataPanelV2 = false,
202
202
  useLastSelectedSources = false,
@@ -281,12 +281,12 @@ export class SearchEmbed extends TsEmbed {
281
281
  /**
282
282
  * Render the embedded ThoughtSpot search
283
283
  */
284
- public render(): SearchEmbed {
284
+ public async render(): Promise<SearchEmbed> {
285
285
  super.render();
286
286
  const { answerId } = this.viewConfig;
287
287
 
288
288
  const src = this.getIFrameSrc();
289
- this.renderIFrame(src);
289
+ await this.renderIFrame(src);
290
290
  getAuthPromise().then(() => {
291
291
  if (
292
292
  checkReleaseVersionInBeta(
@@ -0,0 +1,39 @@
1
+ import {
2
+ init, AuthType, LiveboardEmbed, HostEvent,
3
+ } from '../index';
4
+ import {
5
+ executeAfterWait,
6
+ getDocumentBody,
7
+ getIFrameEl,
8
+ getRootEl,
9
+ } from '../test/test-utils';
10
+
11
+ describe('Trigger', () => {
12
+ beforeEach(() => {
13
+ document.body.innerHTML = getDocumentBody();
14
+ });
15
+ test('should trigger the event', async (done) => {
16
+ init({
17
+ thoughtSpotHost: 'https://tshost',
18
+ authType: AuthType.None,
19
+ });
20
+ const lb = new LiveboardEmbed(getRootEl(), {
21
+ frameParams: {
22
+ width: '100%',
23
+ height: '100%',
24
+ },
25
+ liveboardId: '123',
26
+ });
27
+ const val = await lb.render();
28
+ const iframe = getIFrameEl();
29
+ jest.spyOn(iframe.contentWindow, 'postMessage');
30
+ executeAfterWait(() => {
31
+ lb.trigger(HostEvent.DownloadAsCsv, { vizId: 'testId' });
32
+ expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(expect.objectContaining({
33
+ type: HostEvent.DownloadAsCsv,
34
+ data: { vizId: 'testId' },
35
+ }), 'https://tshost', expect.anything());
36
+ done();
37
+ });
38
+ });
39
+ });
@@ -11,7 +11,7 @@ import {
11
11
  LiveboardEmbed,
12
12
  } from '../index';
13
13
  import {
14
- Action, HomeLeftNavItem, RuntimeFilter, RuntimeFilterOp, HomepageModule,
14
+ Action, HomeLeftNavItem, RuntimeFilter, RuntimeFilterOp, HomepageModule, HostEvent,
15
15
  } from '../types';
16
16
  import {
17
17
  executeAfterWait,
@@ -24,6 +24,7 @@ import {
24
24
  waitFor,
25
25
  expectUrlMatchesWithParams,
26
26
  mockMessageChannel,
27
+ createRootEleForEmbed,
27
28
  } from '../test/test-utils';
28
29
  import * as config from '../config';
29
30
  import * as tsEmbedInstance from './ts-embed';
@@ -47,15 +48,6 @@ const tabId2 = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
47
48
  const thoughtSpotHost = 'tshost';
48
49
  const defaultParamsPost = '';
49
50
 
50
- const createRootEleForEmbed = () => {
51
- const rootEle = document.createElement('div');
52
- rootEle.id = 'myRoot';
53
- const tsEmbedDiv = document.createElement('div');
54
- tsEmbedDiv.id = 'tsEmbedDiv';
55
- rootEle.appendChild(tsEmbedDiv);
56
- document.body.appendChild(rootEle);
57
- };
58
-
59
51
  beforeAll(() => {
60
52
  spyOn(window, 'alert');
61
53
  });
@@ -317,6 +309,46 @@ describe('Unit test case for ts embed', () => {
317
309
  });
318
310
  });
319
311
 
312
+ test('Runtime filters from view Config should be part of app_init payload when excludeRuntimeFiltersfromURL is undefined', async () => {
313
+ const mockEmbedEventPayload = {
314
+ type: EmbedEvent.APP_INIT,
315
+ data: {},
316
+ };
317
+ const mockRuntimeFilters: RuntimeFilter[] = [
318
+ {
319
+ columnName: 'color',
320
+ operator: RuntimeFilterOp.EQ,
321
+ values: ['blue'],
322
+ },
323
+ ];
324
+
325
+ const searchEmbed = new SearchEmbed(getRootEl(), {
326
+ ...defaultViewConfig,
327
+ excludeRuntimeFiltersfromURL: true,
328
+ runtimeFilters: mockRuntimeFilters,
329
+ });
330
+ searchEmbed.render();
331
+ const mockPort: any = {
332
+ postMessage: jest.fn(),
333
+ };
334
+ await executeAfterWait(() => {
335
+ const iframe = getIFrameEl();
336
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
337
+ });
338
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
339
+ type: EmbedEvent.APP_INIT,
340
+ data: {
341
+ customisations,
342
+ authToken: '',
343
+ runtimeFilterParams: 'col1=color&op1=EQ&val1=blue',
344
+ hiddenHomeLeftNavItems: [],
345
+ hiddenHomepageModules: [],
346
+ hostConfig: undefined,
347
+ reorderedHomepageModules: [],
348
+ },
349
+ });
350
+ });
351
+
320
352
  test('Runtime filters from view Config should not be part of app_init payload when excludeRuntimeFiltersfromURL is false', async () => {
321
353
  const mockEmbedEventPayload = {
322
354
  type: EmbedEvent.APP_INIT,
@@ -364,7 +396,7 @@ describe('Unit test case for ts embed', () => {
364
396
  };
365
397
  const mockedHiddenHomeLeftNavItems: HomeLeftNavItem[] = [
366
398
  HomeLeftNavItem.Home,
367
- HomeLeftNavItem.Documentation,
399
+ HomeLeftNavItem.MonitorSubscription,
368
400
  ];
369
401
 
370
402
  const searchEmbed = new AppEmbed(getRootEl(), {
@@ -386,7 +418,8 @@ describe('Unit test case for ts embed', () => {
386
418
  authToken: '',
387
419
  hostConfig: undefined,
388
420
  runtimeFilterParams: null,
389
- hiddenHomeLeftNavItems: [HomeLeftNavItem.Home, HomeLeftNavItem.Documentation],
421
+ hiddenHomeLeftNavItems:
422
+ [HomeLeftNavItem.Home, HomeLeftNavItem.MonitorSubscription],
390
423
  hiddenHomepageModules: [],
391
424
  reorderedHomepageModules: [],
392
425
  },
@@ -1176,7 +1209,7 @@ describe('Unit test case for ts embed', () => {
1176
1209
  expectUrlMatchesWithParams(
1177
1210
  getIFrameSrc(),
1178
1211
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1179
- + `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`,
1212
+ + `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`,
1180
1213
  );
1181
1214
  });
1182
1215
 
@@ -1192,7 +1225,7 @@ describe('Unit test case for ts embed', () => {
1192
1225
  expectUrlMatchesWithParams(
1193
1226
  getIFrameSrc(),
1194
1227
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1195
- + `&showAlerts=true${defaultParamsPost}#/home`,
1228
+ + `&showAlerts=true${defaultParamsPost}#/home`,
1196
1229
  );
1197
1230
  });
1198
1231
  it('Sets the locale param', async () => {
@@ -1207,7 +1240,7 @@ describe('Unit test case for ts embed', () => {
1207
1240
  expectUrlMatchesWithParams(
1208
1241
  getIFrameSrc(),
1209
1242
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1210
- + `&locale=ja-JP${defaultParamsPost}#/home`,
1243
+ + `&locale=ja-JP${defaultParamsPost}#/home`,
1211
1244
  );
1212
1245
  });
1213
1246
  it('Sets the iconSprite url', async () => {
@@ -1224,7 +1257,7 @@ describe('Unit test case for ts embed', () => {
1224
1257
  expectUrlMatchesWithParams(
1225
1258
  getIFrameSrc(),
1226
1259
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
1227
- + `&iconSprite=iconSprite.com${defaultParamsPost}#/home`,
1260
+ + `&iconSprite=iconSprite.com${defaultParamsPost}#/home`,
1228
1261
  );
1229
1262
  });
1230
1263
 
@@ -170,7 +170,7 @@ export class TsEmbed {
170
170
  this.thoughtSpotV2Base = getV2BasePath(this.embedConfig);
171
171
  this.eventHandlerMap = new Map();
172
172
  this.isError = false;
173
- this.viewConfig = viewConfig;
173
+ this.viewConfig = { excludeRuntimeFiltersfromURL: true, ...viewConfig };
174
174
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
175
175
  this.registerAppInit();
176
176
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
@@ -518,10 +518,7 @@ export class TsEmbed {
518
518
  const queryParams = this.shouldEncodeUrlQueryParams
519
519
  ? `?base64UrlEncodedFlags=${getEncodedQueryParamsString(queryString)}`
520
520
  : `?${queryString}`;
521
- let host = this.thoughtSpotHost;
522
- if (!isUndefined(this.embedConfig.enableReactShell)) {
523
- host = this.embedConfig.enableReactShell as boolean ? '/v2' : '/v1';
524
- }
521
+ const host = this.thoughtSpotHost;
525
522
  const path = `${host}/${queryParams}#`;
526
523
  return path;
527
524
  }
@@ -968,6 +965,16 @@ export class TsEmbed {
968
965
  */
969
966
  public trigger(messageType: HostEvent, data: any = {}): Promise<any> {
970
967
  uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_TRIGGER}-${messageType}`);
968
+
969
+ if (!this.isRendered) {
970
+ this.handleError('Please call render before triggering events');
971
+ return null;
972
+ }
973
+
974
+ if (!messageType) {
975
+ this.handleError('Host event type is undefined');
976
+ return null;
977
+ }
971
978
  return processTrigger(this.iFrame, messageType, this.thoughtSpotHost, data);
972
979
  }
973
980
 
@@ -978,7 +985,7 @@ export class TsEmbed {
978
985
  *
979
986
  * @param args
980
987
  */
981
- public render(): TsEmbed {
988
+ public async render(): Promise<TsEmbed> {
982
989
  this.isRendered = true;
983
990
 
984
991
  return this;
@@ -1090,11 +1097,11 @@ export class TsEmbed {
1090
1097
  ) {
1091
1098
  logger.warn(
1092
1099
  `${viewConfig.embedComponentType || 'Component'} was pre-rendered with `
1093
- + `"${key}" as "${JSON.stringify(preRenderedObject.viewConfig[key])}" `
1094
- + `but a different value "${JSON.stringify(viewConfig[key])}" `
1095
- + 'was passed to the Embed component. '
1096
- + 'The new value provided is ignored, the value provided during '
1097
- + 'preRender is used.',
1100
+ + `"${key}" as "${JSON.stringify(preRenderedObject.viewConfig[key])}" `
1101
+ + `but a different value "${JSON.stringify(viewConfig[key])}" `
1102
+ + 'was passed to the Embed component. '
1103
+ + 'The new value provided is ignored, the value provided during '
1104
+ + 'preRender is used.',
1098
1105
  );
1099
1106
  }
1100
1107
  });
@@ -1164,8 +1171,8 @@ export class TsEmbed {
1164
1171
  const elBoundingClient = this.el.getBoundingClientRect();
1165
1172
 
1166
1173
  setStyleProperties(this.preRenderWrapper, {
1167
- top: `${elBoundingClient.y}px`,
1168
- left: `${elBoundingClient.x}px`,
1174
+ top: `${elBoundingClient.y + window.scrollY}px`,
1175
+ left: `${elBoundingClient.x + window.scrollX}px`,
1169
1176
  width: `${elBoundingClient.width}px`,
1170
1177
  height: `${elBoundingClient.height}px`,
1171
1178
  });
@@ -1186,8 +1193,6 @@ export class TsEmbed {
1186
1193
  pointerEvents: 'none',
1187
1194
  zIndex: '-1000',
1188
1195
  position: 'absolute ',
1189
- top: '0',
1190
- left: '0',
1191
1196
  };
1192
1197
  setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
1193
1198
 
@@ -1238,7 +1243,7 @@ export class V1Embed extends TsEmbed {
1238
1243
 
1239
1244
  constructor(domSelector: DOMSelector, viewConfig: ViewConfig) {
1240
1245
  super(domSelector, viewConfig);
1241
- this.viewConfig = viewConfig;
1246
+ this.viewConfig = { excludeRuntimeFiltersfromURL: true, ...viewConfig };
1242
1247
  }
1243
1248
 
1244
1249
  /**
package/src/index.ts CHANGED
@@ -54,6 +54,7 @@ import { SageEmbed, SageViewConfig } from './embed/sage';
54
54
  import { AnswerService, SessionInterface, UnderlyingDataPoint } from './utils/graphql/answerService/answerService';
55
55
  import { getEmbedConfig } from './embed/embedConfig';
56
56
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from './mixpanel-service';
57
+ import { tokenizedFetch } from './tokenizedFetch';
57
58
 
58
59
  export {
59
60
  init,
@@ -65,6 +66,7 @@ export {
65
66
  exportTMLInput,
66
67
  getEmbedConfig as getInitConfig,
67
68
  getSessionInfo,
69
+ tokenizedFetch,
68
70
  SearchEmbed,
69
71
  SearchBarEmbed,
70
72
  PinboardEmbed,
@@ -135,6 +135,7 @@ describe('React Components', () => {
135
135
  values: [100],
136
136
  },
137
137
  ]}
138
+ excludeRuntimeFiltersfromURL={false}
138
139
  />,
139
140
  );
140
141
 
@@ -116,3 +116,12 @@ export const expectUrlMatch = (source: string, target: string) => {
116
116
  const targetUrl = new URL(target);
117
117
  expect(sourceUrl.hash).toBe(targetUrl.hash);
118
118
  };
119
+
120
+ export const createRootEleForEmbed = () => {
121
+ const rootEle = document.createElement('div');
122
+ rootEle.id = 'myRoot';
123
+ const tsEmbedDiv = document.createElement('div');
124
+ tsEmbedDiv.id = 'tsEmbedDiv';
125
+ rootEle.appendChild(tsEmbedDiv);
126
+ document.body.appendChild(rootEle);
127
+ };