@thoughtspot/visual-embed-sdk 1.20.1 → 1.21.0-alpha.0

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 (182) hide show
  1. package/README.md +1 -1
  2. package/dist/src/auth.d.ts +48 -3
  3. package/dist/src/auth.d.ts.map +1 -1
  4. package/dist/src/config.d.ts +1 -0
  5. package/dist/src/config.d.ts.map +1 -1
  6. package/dist/src/embed/app.d.ts +17 -5
  7. package/dist/src/embed/app.d.ts.map +1 -1
  8. package/dist/src/embed/base.d.ts +20 -9
  9. package/dist/src/embed/base.d.ts.map +1 -1
  10. package/dist/src/embed/liveboard.d.ts +17 -5
  11. package/dist/src/embed/liveboard.d.ts.map +1 -1
  12. package/dist/src/embed/search-bar.d.ts +3 -0
  13. package/dist/src/embed/search-bar.d.ts.map +1 -1
  14. package/dist/src/embed/search.d.ts +9 -5
  15. package/dist/src/embed/search.d.ts.map +1 -1
  16. package/dist/src/embed/ts-embed.d.ts +64 -6
  17. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  18. package/dist/src/errors.d.ts.map +1 -1
  19. package/dist/src/index.d.ts.map +1 -1
  20. package/dist/src/mixpanel-service.d.ts +8 -0
  21. package/dist/src/mixpanel-service.d.ts.map +1 -1
  22. package/dist/src/react/index.d.ts.map +1 -1
  23. package/dist/src/react/util.d.ts +4 -0
  24. package/dist/src/react/util.d.ts.map +1 -1
  25. package/dist/src/test/test-utils.d.ts +11 -2
  26. package/dist/src/test/test-utils.d.ts.map +1 -1
  27. package/dist/src/types.d.ts +273 -76
  28. package/dist/src/types.d.ts.map +1 -1
  29. package/dist/src/utils/answerService.d.ts +7 -0
  30. package/dist/src/utils/answerService.d.ts.map +1 -1
  31. package/dist/src/utils/authService.d.ts +30 -0
  32. package/dist/src/utils/authService.d.ts.map +1 -1
  33. package/dist/src/utils/processData.d.ts +12 -0
  34. package/dist/src/utils/processData.d.ts.map +1 -1
  35. package/dist/src/utils/processTrigger.d.ts +7 -0
  36. package/dist/src/utils/processTrigger.d.ts.map +1 -1
  37. package/dist/src/utils.d.ts +12 -0
  38. package/dist/src/utils.d.ts.map +1 -1
  39. package/dist/tsembed.es.js +667 -264
  40. package/dist/tsembed.js +659 -263
  41. package/lib/package.json +3 -8
  42. package/lib/src/auth.d.ts +48 -3
  43. package/lib/src/auth.d.ts.map +1 -1
  44. package/lib/src/auth.js +70 -25
  45. package/lib/src/auth.js.map +1 -1
  46. package/lib/src/auth.spec.js +14 -5
  47. package/lib/src/auth.spec.js.map +1 -1
  48. package/lib/src/config.d.ts +1 -0
  49. package/lib/src/config.d.ts.map +1 -1
  50. package/lib/src/config.js +5 -3
  51. package/lib/src/config.js.map +1 -1
  52. package/lib/src/config.spec.js.map +1 -1
  53. package/lib/src/embed/app.d.ts +17 -5
  54. package/lib/src/embed/app.d.ts.map +1 -1
  55. package/lib/src/embed/app.js +25 -15
  56. package/lib/src/embed/app.js.map +1 -1
  57. package/lib/src/embed/app.spec.js +12 -12
  58. package/lib/src/embed/app.spec.js.map +1 -1
  59. package/lib/src/embed/base.d.ts +20 -9
  60. package/lib/src/embed/base.d.ts.map +1 -1
  61. package/lib/src/embed/base.js +31 -15
  62. package/lib/src/embed/base.js.map +1 -1
  63. package/lib/src/embed/base.spec.js.map +1 -1
  64. package/lib/src/embed/embed.spec.js +1 -1
  65. package/lib/src/embed/embed.spec.js.map +1 -1
  66. package/lib/src/embed/liveboard.d.ts +17 -5
  67. package/lib/src/embed/liveboard.d.ts.map +1 -1
  68. package/lib/src/embed/liveboard.js +49 -37
  69. package/lib/src/embed/liveboard.js.map +1 -1
  70. package/lib/src/embed/liveboard.spec.js +37 -30
  71. package/lib/src/embed/liveboard.spec.js.map +1 -1
  72. package/lib/src/embed/pinboard.spec.js +14 -26
  73. package/lib/src/embed/pinboard.spec.js.map +1 -1
  74. package/lib/src/embed/search-bar.d.ts +3 -0
  75. package/lib/src/embed/search-bar.d.ts.map +1 -1
  76. package/lib/src/embed/search-bar.js +5 -6
  77. package/lib/src/embed/search-bar.js.map +1 -1
  78. package/lib/src/embed/search.d.ts +9 -5
  79. package/lib/src/embed/search.d.ts.map +1 -1
  80. package/lib/src/embed/search.js +18 -14
  81. package/lib/src/embed/search.js.map +1 -1
  82. package/lib/src/embed/search.spec.js +16 -19
  83. package/lib/src/embed/search.spec.js.map +1 -1
  84. package/lib/src/embed/searchEmbed-basic-auth.spec.js +4 -0
  85. package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  86. package/lib/src/embed/ts-embed.d.ts +64 -6
  87. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  88. package/lib/src/embed/ts-embed.js +147 -74
  89. package/lib/src/embed/ts-embed.js.map +1 -1
  90. package/lib/src/embed/ts-embed.spec.js +46 -24
  91. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  92. package/lib/src/errors.d.ts.map +1 -1
  93. package/lib/src/errors.js.map +1 -1
  94. package/lib/src/index.d.ts.map +1 -1
  95. package/lib/src/index.js +2 -2
  96. package/lib/src/index.js.map +1 -1
  97. package/lib/src/mixpanel-service.d.ts +8 -0
  98. package/lib/src/mixpanel-service.d.ts.map +1 -1
  99. package/lib/src/mixpanel-service.js +13 -1
  100. package/lib/src/mixpanel-service.js.map +1 -1
  101. package/lib/src/mixpanel-service.spec.js.map +1 -1
  102. package/lib/src/react/index.d.ts.map +1 -1
  103. package/lib/src/react/index.js +6 -6
  104. package/lib/src/react/index.js.map +1 -1
  105. package/lib/src/react/index.spec.js +15 -6
  106. package/lib/src/react/index.spec.js.map +1 -1
  107. package/lib/src/react/util.d.ts +4 -0
  108. package/lib/src/react/util.d.ts.map +1 -1
  109. package/lib/src/react/util.js +4 -0
  110. package/lib/src/react/util.js.map +1 -1
  111. package/lib/src/test/test-utils.d.ts +11 -2
  112. package/lib/src/test/test-utils.d.ts.map +1 -1
  113. package/lib/src/test/test-utils.js +36 -25
  114. package/lib/src/test/test-utils.js.map +1 -1
  115. package/lib/src/types.d.ts +273 -76
  116. package/lib/src/types.d.ts.map +1 -1
  117. package/lib/src/types.js +200 -54
  118. package/lib/src/types.js.map +1 -1
  119. package/lib/src/utils/answerService.d.ts +7 -0
  120. package/lib/src/utils/answerService.d.ts.map +1 -1
  121. package/lib/src/utils/answerService.js +7 -0
  122. package/lib/src/utils/answerService.js.map +1 -1
  123. package/lib/src/utils/answerService.spec.js.map +1 -1
  124. package/lib/src/utils/authService.d.ts +30 -0
  125. package/lib/src/utils/authService.d.ts.map +1 -1
  126. package/lib/src/utils/authService.js +39 -2
  127. package/lib/src/utils/authService.js.map +1 -1
  128. package/lib/src/utils/authService.spec.js.map +1 -1
  129. package/lib/src/utils/processData.d.ts +12 -0
  130. package/lib/src/utils/processData.d.ts.map +1 -1
  131. package/lib/src/utils/processData.js +33 -5
  132. package/lib/src/utils/processData.js.map +1 -1
  133. package/lib/src/utils/processData.spec.js.map +1 -1
  134. package/lib/src/utils/processTrigger.d.ts +7 -0
  135. package/lib/src/utils/processTrigger.d.ts.map +1 -1
  136. package/lib/src/utils/processTrigger.js +17 -3
  137. package/lib/src/utils/processTrigger.js.map +1 -1
  138. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  139. package/lib/src/utils.d.ts +12 -0
  140. package/lib/src/utils.d.ts.map +1 -1
  141. package/lib/src/utils.js +24 -19
  142. package/lib/src/utils.js.map +1 -1
  143. package/lib/src/utils.spec.js.map +1 -1
  144. package/lib/src/visual-embed-sdk.d.ts +437 -103
  145. package/package.json +3 -8
  146. package/src/auth.spec.ts +68 -150
  147. package/src/auth.ts +115 -109
  148. package/src/config.spec.ts +2 -4
  149. package/src/config.ts +5 -3
  150. package/src/embed/app.spec.ts +25 -14
  151. package/src/embed/app.ts +47 -35
  152. package/src/embed/base.spec.ts +3 -9
  153. package/src/embed/base.ts +51 -53
  154. package/src/embed/embed.spec.ts +5 -6
  155. package/src/embed/liveboard.spec.ts +56 -37
  156. package/src/embed/liveboard.ts +66 -64
  157. package/src/embed/pinboard.spec.ts +26 -29
  158. package/src/embed/search-bar.tsx +10 -8
  159. package/src/embed/search.spec.ts +31 -21
  160. package/src/embed/search.ts +26 -25
  161. package/src/embed/searchEmbed-basic-auth.spec.ts +22 -28
  162. package/src/embed/ts-embed.spec.ts +99 -144
  163. package/src/embed/ts-embed.ts +181 -159
  164. package/src/errors.ts +3 -6
  165. package/src/index.ts +4 -10
  166. package/src/mixpanel-service.spec.ts +1 -3
  167. package/src/mixpanel-service.ts +13 -1
  168. package/src/react/index.spec.tsx +37 -13
  169. package/src/react/index.tsx +38 -57
  170. package/src/react/util.ts +8 -4
  171. package/src/test/test-utils.ts +43 -39
  172. package/src/types.ts +270 -78
  173. package/src/utils/answerService.spec.ts +3 -5
  174. package/src/utils/answerService.ts +21 -17
  175. package/src/utils/authService.spec.ts +26 -41
  176. package/src/utils/authService.ts +47 -21
  177. package/src/utils/processData.spec.ts +26 -59
  178. package/src/utils/processData.ts +36 -14
  179. package/src/utils/processTrigger.spec.ts +1 -6
  180. package/src/utils/processTrigger.ts +18 -9
  181. package/src/utils.spec.ts +8 -12
  182. package/src/utils.ts +25 -26
package/src/auth.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import EventEmitter from 'eventemitter3';
2
2
  import { initMixpanel } from './mixpanel-service';
3
- import { AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param } from './types';
3
+ import {
4
+ AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param,
5
+ } from './types';
4
6
  import { getDOMNode, getRedirectUrl } from './utils';
5
7
  // eslint-disable-next-line import/no-cycle
6
8
  import {
@@ -25,15 +27,12 @@ const sessionInfoPromise = new Promise((resolve) => {
25
27
  });
26
28
  let releaseVersion = '';
27
29
 
28
- export const SSO_REDIRECTION_MARKER_GUID =
29
- '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
30
+ export const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
30
31
 
31
32
  export const EndPoints = {
32
33
  AUTH_VERIFICATION: '/callosum/v1/session/info',
33
- SAML_LOGIN_TEMPLATE: (targetUrl: string) =>
34
- `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
35
- OIDC_LOGIN_TEMPLATE: (targetUrl: string) =>
36
- `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
34
+ SAML_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
35
+ OIDC_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
37
36
  TOKEN_LOGIN: '/callosum/v1/session/login/token',
38
37
  BASIC_LOGIN: '/callosum/v1/session/login',
39
38
  LOGOUT: '/callosum/v1/session/logout',
@@ -42,6 +41,7 @@ export const EndPoints = {
42
41
  /**
43
42
  * Enum for auth failure types. This is the parameter passed to the listner
44
43
  * of {@link AuthStatus.FAILURE}.
44
+ *
45
45
  * @group Authentication / Init
46
46
  */
47
47
  export enum AuthFailureType {
@@ -53,6 +53,7 @@ export enum AuthFailureType {
53
53
 
54
54
  /**
55
55
  * Enum for auth status emitted by the emitter returned from {@link init}.
56
+ *
56
57
  * @group Authentication / Init
57
58
  */
58
59
  export enum AuthStatus {
@@ -76,6 +77,7 @@ export enum AuthStatus {
76
77
  * Emitted when inPopup: true in the SAMLRedirect flow.
77
78
  * And, we are waiting for popup to be triggered either programatically
78
79
  * or by the trigger button.
80
+ *
79
81
  * @version SDK: 1.19.0
80
82
  */
81
83
  WAITING_FOR_POPUP = 'WAITING_FOR_POPUP',
@@ -83,28 +85,37 @@ export enum AuthStatus {
83
85
 
84
86
  /**
85
87
  * Event emitter returned from {@link init}.
88
+ *
86
89
  * @group Authentication / Init
87
90
  */
88
91
  export interface AuthEventEmitter {
89
92
  /**
90
- * Registed a listener on Auth failure.
93
+ * Register a listener on Auth failure.
94
+ *
95
+ * @param event
96
+ * @param listener
97
+ */
98
+ on(event: AuthStatus.FAILURE, listener: (failureType: AuthFailureType) => void): this;
99
+ /**
100
+ * Register a listener on Auth SDK success.
101
+ *
91
102
  * @param event
92
103
  * @param listener
93
104
  */
94
105
  on(
95
- event: AuthStatus.FAILURE,
96
- listener: (failureType: AuthFailureType) => void,
97
- ): this;
98
- on(
99
- event:
100
- | AuthStatus.SDK_SUCCESS
101
- | AuthStatus.LOGOUT
102
- | AuthStatus.WAITING_FOR_POPUP,
106
+ event: AuthStatus.SDK_SUCCESS | AuthStatus.LOGOUT | AuthStatus.WAITING_FOR_POPUP,
103
107
  listener: () => void,
104
108
  ): this;
105
109
  on(event: AuthStatus.SUCCESS, listener: (sessionInfo: any) => void): this;
110
+ once(event: AuthStatus.FAILURE, listener: (failureType: AuthFailureType) => void): this;
111
+ once(
112
+ event: AuthStatus.SDK_SUCCESS | AuthStatus.LOGOUT | AuthStatus.WAITING_FOR_POPUP,
113
+ listener: () => void,
114
+ ): this;
115
+ once(event: AuthStatus.SUCCESS, listener: (sessionInfo: any) => void): this;
106
116
  /**
107
117
  * Trigger an event on the emitter returned from init.
118
+ *
108
119
  * @param {@link AuthEvent}
109
120
  */
110
121
  emit(event: AuthEvent): void;
@@ -112,6 +123,7 @@ export interface AuthEventEmitter {
112
123
 
113
124
  /**
114
125
  * Events which can be triggered on the emitter returned from {@link init}.
126
+ *
115
127
  * @group Authentication / Init
116
128
  */
117
129
  export enum AuthEvent {
@@ -124,16 +136,24 @@ export enum AuthEvent {
124
136
 
125
137
  let authEE: EventEmitter<AuthStatus | AuthEvent>;
126
138
 
139
+ /**
140
+ *
141
+ */
127
142
  export function getAuthEE(): EventEmitter<AuthStatus | AuthEvent> {
128
143
  return authEE;
129
144
  }
130
145
 
131
- export function setAuthEE(
132
- eventEmitter: EventEmitter<AuthStatus | AuthEvent>,
133
- ): void {
146
+ /**
147
+ *
148
+ * @param eventEmitter
149
+ */
150
+ export function setAuthEE(eventEmitter: EventEmitter<AuthStatus | AuthEvent>): void {
134
151
  authEE = eventEmitter;
135
152
  }
136
153
 
154
+ /**
155
+ *
156
+ */
137
157
  export function notifyAuthSDKSuccess(): void {
138
158
  if (!authEE) {
139
159
  console.error('SDK not initialized');
@@ -142,6 +162,9 @@ export function notifyAuthSDKSuccess(): void {
142
162
  authEE.emit(AuthStatus.SDK_SUCCESS);
143
163
  }
144
164
 
165
+ /**
166
+ *
167
+ */
145
168
  export function notifyAuthSuccess(): void {
146
169
  if (!authEE) {
147
170
  console.error('SDK not initialized');
@@ -150,6 +173,10 @@ export function notifyAuthSuccess(): void {
150
173
  authEE.emit(AuthStatus.SUCCESS, sessionInfo);
151
174
  }
152
175
 
176
+ /**
177
+ *
178
+ * @param failureType
179
+ */
153
180
  export function notifyAuthFailure(failureType: AuthFailureType): void {
154
181
  if (!authEE) {
155
182
  console.error('SDK not initialized');
@@ -158,6 +185,9 @@ export function notifyAuthFailure(failureType: AuthFailureType): void {
158
185
  authEE.emit(AuthStatus.FAILURE, failureType);
159
186
  }
160
187
 
188
+ /**
189
+ *
190
+ */
161
191
  export function notifyLogout(): void {
162
192
  if (!authEE) {
163
193
  console.error('SDK not initialized');
@@ -168,6 +198,7 @@ export function notifyLogout(): void {
168
198
 
169
199
  /**
170
200
  * Check if we are logged into the ThoughtSpot cluster
201
+ *
171
202
  * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
172
203
  */
173
204
  async function isLoggedIn(thoughtSpotHost: string): Promise<boolean> {
@@ -191,24 +222,32 @@ export function getReleaseVersion() {
191
222
  }
192
223
 
193
224
  /**
194
- * Return a promise that resolves with the session information when authentication is
195
- * successful. And info is available.
225
+ * Return a promise that resolves with the session information when
226
+ * authentication is successful. And info is available.
227
+ *
196
228
  * @group Global methods
197
229
  */
198
230
  export function getSessionInfo(): Promise<any> {
199
231
  return sessionInfoPromise;
200
232
  }
201
233
 
234
+ /**
235
+ *
236
+ * @param sessionDetails
237
+ */
202
238
  export function initSession(sessionDetails: any) {
203
239
  sessionInfo = sessionDetails;
204
240
  initMixpanel(sessionInfo);
205
241
  sessionInfoResolver(sessionInfo);
206
242
  }
207
243
 
208
- const DUPLICATE_TOKEN_ERR =
209
- 'Duplicate token, please issue a new token every time getAuthToken callback is called.' +
210
- 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
244
+ const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
245
+ + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
211
246
  let prevAuthToken: string = null;
247
+ /**
248
+ *
249
+ * @param authtoken
250
+ */
212
251
  function alertForDuplicateToken(authtoken: string) {
213
252
  if (prevAuthToken === authtoken) {
214
253
  // eslint-disable-next-line no-alert
@@ -230,18 +269,14 @@ function isAtSSORedirectUrl(): boolean {
230
269
  */
231
270
  function removeSSORedirectUrlMarker(): void {
232
271
  // Note (sunny): This will leave a # around even if it was not in the URL
233
- // to begin with. Trying to remove the hash by changing window.location will reload
234
- // the page which we don't want. We'll live with adding an unnecessary hash to the
235
- // parent page URL until we find any use case where that creates an issue.
236
- window.location.hash = window.location.hash.replace(
237
- SSO_REDIRECTION_MARKER_GUID,
238
- '',
239
- );
272
+ // to begin with. Trying to remove the hash by changing window.location will
273
+ // reload the page which we don't want. We'll live with adding an
274
+ // unnecessary hash to the parent page URL until we find any use case where
275
+ // that creates an issue.
276
+ window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
240
277
  }
241
278
 
242
- export const getAuthenticaionToken = async (
243
- embedConfig: EmbedConfig,
244
- ): Promise<any> => {
279
+ export const getAuthenticaionToken = async (embedConfig: EmbedConfig): Promise<any> => {
245
280
  const { authEndpoint, getAuthToken } = embedConfig;
246
281
  let authToken = null;
247
282
  if (getAuthToken) {
@@ -256,40 +291,30 @@ export const getAuthenticaionToken = async (
256
291
 
257
292
  /**
258
293
  * Perform token based authentication
294
+ *
259
295
  * @param embedConfig The embed configuration
260
296
  */
261
- export const doTokenAuth = async (
262
- embedConfig: EmbedConfig,
263
- ): Promise<boolean> => {
297
+ export const doTokenAuth = async (embedConfig: EmbedConfig): Promise<boolean> => {
264
298
  const {
265
- thoughtSpotHost,
266
- username,
267
- authEndpoint,
268
- getAuthToken,
299
+ thoughtSpotHost, username, authEndpoint, getAuthToken,
269
300
  } = embedConfig;
270
301
  if (!authEndpoint && !getAuthToken) {
271
- throw new Error(
272
- 'Either auth endpoint or getAuthToken function must be provided',
273
- );
302
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
274
303
  }
275
304
  loggedInStatus = await isLoggedIn(thoughtSpotHost);
276
305
  if (!loggedInStatus) {
277
306
  const authToken = await getAuthenticaionToken(embedConfig);
278
307
  let resp;
279
308
  try {
280
- resp = await fetchAuthPostService(
281
- thoughtSpotHost,
282
- username,
283
- authToken,
284
- );
309
+ resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
285
310
  } catch (e) {
286
311
  resp = await fetchAuthService(thoughtSpotHost, username, authToken);
287
312
  }
288
313
  // token login issues a 302 when successful
289
314
  loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
290
315
  if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
291
- // When 3rd party cookie access is blocked, this will fail because cookies will
292
- // not be sent with the call.
316
+ // When 3rd party cookie access is blocked, this will fail because
317
+ // cookies will not be sent with the call.
293
318
  loggedInStatus = await isLoggedIn(thoughtSpotHost);
294
319
  }
295
320
  }
@@ -298,16 +323,13 @@ export const doTokenAuth = async (
298
323
 
299
324
  /**
300
325
  * Validate embedConfig parameters required for cookielessTokenAuth
326
+ *
301
327
  * @param embedConfig The embed configuration
302
328
  */
303
- export const doCookielessTokenAuth = async (
304
- embedConfig: EmbedConfig,
305
- ): Promise<boolean> => {
329
+ export const doCookielessTokenAuth = async (embedConfig: EmbedConfig): Promise<boolean> => {
306
330
  const { authEndpoint, getAuthToken } = embedConfig;
307
331
  if (!authEndpoint && !getAuthToken) {
308
- throw new Error(
309
- 'Either auth endpoint or getAuthToken function must be provided',
310
- );
332
+ throw new Error('Either auth endpoint or getAuthToken function must be provided');
311
333
  }
312
334
  return Promise.resolve(true);
313
335
  };
@@ -318,19 +340,14 @@ export const doCookielessTokenAuth = async (
318
340
  *
319
341
  * Warning: This feature is primarily intended for developer testing. It is
320
342
  * strongly advised not to use this authentication method in production.
343
+ *
321
344
  * @param embedConfig The embed configuration
322
345
  */
323
- export const doBasicAuth = async (
324
- embedConfig: EmbedConfig,
325
- ): Promise<boolean> => {
346
+ export const doBasicAuth = async (embedConfig: EmbedConfig): Promise<boolean> => {
326
347
  const { thoughtSpotHost, username, password } = embedConfig;
327
348
  const loggedIn = await isLoggedIn(thoughtSpotHost);
328
349
  if (!loggedIn) {
329
- const response = await fetchBasicAuthService(
330
- thoughtSpotHost,
331
- username,
332
- password,
333
- );
350
+ const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
334
351
  loggedInStatus = response.ok;
335
352
  if (embedConfig.detectCookieAccessSlow) {
336
353
  loggedInStatus = await isLoggedIn(thoughtSpotHost);
@@ -341,11 +358,13 @@ export const doBasicAuth = async (
341
358
  return loggedInStatus;
342
359
  };
343
360
 
344
- async function samlPopupFlow(
345
- ssoURL: string,
346
- triggerContainer: DOMSelector,
347
- triggerText: string,
348
- ) {
361
+ /**
362
+ *
363
+ * @param ssoURL
364
+ * @param triggerContainer
365
+ * @param triggerText
366
+ */
367
+ async function samlPopupFlow(ssoURL: string, triggerContainer: DOMSelector, triggerText: string) {
349
368
  const openPopup = () => {
350
369
  if (samlAuthWindow === null || samlAuthWindow.closed) {
351
370
  samlAuthWindow = window.open(
@@ -360,15 +379,13 @@ async function samlPopupFlow(
360
379
  authEE?.emit(AuthStatus.WAITING_FOR_POPUP);
361
380
  const containerEl = getDOMNode(triggerContainer);
362
381
  if (containerEl) {
363
- containerEl.innerHTML =
364
- '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
382
+ containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
365
383
  const authElem = document.getElementById('ts-auth-btn');
366
384
  authElem.textContent = triggerText;
367
385
  authElem.addEventListener('click', openPopup, { once: true });
368
386
  }
369
- samlCompletionPromise =
370
- samlCompletionPromise ||
371
- new Promise<void>((resolve, reject) => {
387
+ samlCompletionPromise = samlCompletionPromise
388
+ || new Promise<void>((resolve, reject) => {
372
389
  window.addEventListener('message', (e) => {
373
390
  if (e.data.type === EmbedEvent.SAMLComplete) {
374
391
  (e.source as Window).close();
@@ -383,12 +400,11 @@ async function samlPopupFlow(
383
400
 
384
401
  /**
385
402
  * Perform SAML authentication
403
+ *
386
404
  * @param embedConfig The embed configuration
405
+ * @param ssoEndPoint
387
406
  */
388
- const doSSOAuth = async (
389
- embedConfig: EmbedConfig,
390
- ssoEndPoint: string,
391
- ): Promise<void> => {
407
+ const doSSOAuth = async (embedConfig: EmbedConfig, ssoEndPoint: string): Promise<void> => {
392
408
  const { thoughtSpotHost } = embedConfig;
393
409
  const loggedIn = await isLoggedIn(thoughtSpotHost);
394
410
  if (loggedIn) {
@@ -409,11 +425,7 @@ const doSSOAuth = async (
409
425
 
410
426
  const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
411
427
  if (embedConfig.inPopup) {
412
- await samlPopupFlow(
413
- ssoURL,
414
- embedConfig.authTriggerContainer,
415
- embedConfig.authTriggerText,
416
- );
428
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
417
429
  loggedInStatus = true;
418
430
  return;
419
431
  }
@@ -423,20 +435,18 @@ const doSSOAuth = async (
423
435
 
424
436
  export const doSamlAuth = async (embedConfig: EmbedConfig) => {
425
437
  const { thoughtSpotHost } = embedConfig;
426
- // redirect for SSO, when the SSO authentication is done, this page will be loaded
427
- // again and the same JS will execute again.
438
+ // redirect for SSO, when the SSO authentication is done, this page will be
439
+ // loaded again and the same JS will execute again.
428
440
  const ssoRedirectUrl = embedConfig.inPopup
429
441
  ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
430
442
  : getRedirectUrl(
431
- window.location.href,
432
- SSO_REDIRECTION_MARKER_GUID,
433
- embedConfig.redirectPath,
434
- );
443
+ window.location.href,
444
+ SSO_REDIRECTION_MARKER_GUID,
445
+ embedConfig.redirectPath,
446
+ );
435
447
 
436
448
  // bring back the page to the same URL
437
- const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(
438
- encodeURIComponent(ssoRedirectUrl),
439
- )}`;
449
+ const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
440
450
 
441
451
  await doSSOAuth(embedConfig, ssoEndPoint);
442
452
  return loggedInStatus;
@@ -444,21 +454,18 @@ export const doSamlAuth = async (embedConfig: EmbedConfig) => {
444
454
 
445
455
  export const doOIDCAuth = async (embedConfig: EmbedConfig) => {
446
456
  const { thoughtSpotHost } = embedConfig;
447
- // redirect for SSO, when the SSO authentication is done, this page will be loaded
448
- // again and the same JS will execute again.
449
- const ssoRedirectUrl =
450
- embedConfig.noRedirect || embedConfig.inPopup
451
- ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
452
- : getRedirectUrl(
453
- window.location.href,
454
- SSO_REDIRECTION_MARKER_GUID,
455
- embedConfig.redirectPath,
456
- );
457
+ // redirect for SSO, when the SSO authentication is done, this page will be
458
+ // loaded again and the same JS will execute again.
459
+ const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
460
+ ? `${thoughtSpotHost}/v2/#/embed/saml-complete`
461
+ : getRedirectUrl(
462
+ window.location.href,
463
+ SSO_REDIRECTION_MARKER_GUID,
464
+ embedConfig.redirectPath,
465
+ );
457
466
 
458
467
  // bring back the page to the same URL
459
- const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(
460
- encodeURIComponent(ssoRedirectUrl),
461
- )}`;
468
+ const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
462
469
 
463
470
  await doSSOAuth(embedConfig, ssoEndPoint);
464
471
  return loggedInStatus;
@@ -473,11 +480,10 @@ export const logout = async (embedConfig: EmbedConfig): Promise<boolean> => {
473
480
 
474
481
  /**
475
482
  * Perform authentication on the ThoughtSpot cluster
483
+ *
476
484
  * @param embedConfig The embed configuration
477
485
  */
478
- export const authenticate = async (
479
- embedConfig: EmbedConfig,
480
- ): Promise<boolean> => {
486
+ export const authenticate = async (embedConfig: EmbedConfig): Promise<boolean> => {
481
487
  const { authType } = embedConfig;
482
488
  switch (authType) {
483
489
  case AuthType.SSO:
@@ -59,8 +59,7 @@ describe('getThoughtSpotHost', () => {
59
59
  expect(
60
60
  getThoughtSpotHost({
61
61
  ...embedConfig,
62
- thoughtSpotHost:
63
- 'http://1.2.3.4:8088/v2/?foo=bar&baz=42#myhash',
62
+ thoughtSpotHost: 'http://1.2.3.4:8088/v2/?foo=bar&baz=42#myhash',
64
63
  }),
65
64
  ).toBe('http://1.2.3.4:8088/v2');
66
65
  });
@@ -70,8 +69,7 @@ describe('getThoughtSpotHost', () => {
70
69
  getThoughtSpotHost({
71
70
  ...embedConfig,
72
71
  authType: AuthType.SAML,
73
- thoughtSpotHost:
74
- 'http://1.2.3.4:8088/v2/?foo=bar&baz=42#myhash',
72
+ thoughtSpotHost: 'http://1.2.3.4:8088/v2/?foo=bar&baz=42#myhash',
75
73
  }),
76
74
  ).toBe('http://1.2.3.4:8088/v2');
77
75
  });
package/src/config.ts CHANGED
@@ -23,6 +23,7 @@ const urlRegex = new RegExp(
23
23
  /**
24
24
  * Parse and construct the ThoughtSpot hostname or IP address
25
25
  * from the embed configuration object.
26
+ *
26
27
  * @param config
27
28
  */
28
29
  export const getThoughtSpotHost = (config: EmbedConfig): string => {
@@ -51,9 +52,10 @@ export const getV2BasePath = (config: EmbedConfig): string => {
51
52
 
52
53
  const tsHost = getThoughtSpotHost(config);
53
54
 
54
- // This is to handle when e2e's. Search is run on pods for comp-blink-test-pipeline
55
- // with baseUrl=https://localhost:8443.
56
- // This is to handle when the developer is developing in their local environment.
55
+ // This is to handle when e2e's. Search is run on pods for
56
+ // comp-blink-test-pipeline with baseUrl=https://localhost:8443.
57
+ // This is to handle when the developer is developing in their local
58
+ // environment.
57
59
  if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
58
60
  return '';
59
61
  }
@@ -1,6 +1,8 @@
1
1
  import { AppEmbed, AppViewConfig, Page } from './app';
2
2
  import { init } from '../index';
3
- import { Action, AuthType, HostEvent, RuntimeFilterOp } from '../types';
3
+ import {
4
+ Action, AuthType, HostEvent, RuntimeFilterOp,
5
+ } from '../types';
4
6
  import {
5
7
  executeAfterWait,
6
8
  getDocumentBody,
@@ -11,6 +13,7 @@ import {
11
13
  defaultParams,
12
14
  defaultParamsForPinboardEmbed,
13
15
  defaultParamsWithoutHiddenActions,
16
+ expectUrlMatchesWithParams,
14
17
  } from '../test/test-utils';
15
18
  import { version } from '../../package.json';
16
19
  import * as config from '../config';
@@ -44,7 +47,8 @@ describe('App embed tests', () => {
44
47
  const appEmbed = new AppEmbed(getRootEl(), defaultViewConfig);
45
48
  appEmbed.render();
46
49
  await executeAfterWait(() => {
47
- expect(getIFrameSrc()).toBe(
50
+ expectUrlMatchesWithParams(
51
+ getIFrameSrc(),
48
52
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
49
53
  );
50
54
  });
@@ -57,7 +61,8 @@ describe('App embed tests', () => {
57
61
  } as AppViewConfig);
58
62
  appEmbed.render();
59
63
  await executeAfterWait(() => {
60
- expect(getIFrameSrc()).toBe(
64
+ expectUrlMatchesWithParams(
65
+ getIFrameSrc(),
61
66
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=false&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
62
67
  );
63
68
  });
@@ -70,7 +75,8 @@ describe('App embed tests', () => {
70
75
  } as AppViewConfig);
71
76
  appEmbed.render();
72
77
  await executeAfterWait(() => {
73
- expect(getIFrameSrc()).toBe(
78
+ expectUrlMatchesWithParams(
79
+ getIFrameSrc(),
74
80
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=true${defaultParams}${defaultParamsPost}#/home`,
75
81
  );
76
82
  });
@@ -101,7 +107,8 @@ describe('App embed tests', () => {
101
107
  appEmbed.render();
102
108
 
103
109
  await executeAfterWait(() => {
104
- expect(getIFrameSrc()).toBe(
110
+ expectUrlMatchesWithParams(
111
+ getIFrameSrc(),
105
112
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/${route}`,
106
113
  );
107
114
  cleanUp();
@@ -117,7 +124,8 @@ describe('App embed tests', () => {
117
124
  } as AppViewConfig);
118
125
  appEmbed.render();
119
126
  await executeAfterWait(() => {
120
- expect(getIFrameSrc()).toBe(
127
+ expectUrlMatchesWithParams(
128
+ getIFrameSrc(),
121
129
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/foo/bar`,
122
130
  );
123
131
  });
@@ -138,7 +146,8 @@ describe('App embed tests', () => {
138
146
 
139
147
  appEmbed.render();
140
148
  await executeAfterWait(() => {
141
- expect(getIFrameSrc()).toBe(
149
+ expectUrlMatchesWithParams(
150
+ getIFrameSrc(),
142
151
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=false&profileAndHelpInNavBarHidden=false&col1=sales&op1=EQ&val1=1000${defaultParams}${defaultParamsPost}#/home`,
143
152
  );
144
153
  });
@@ -155,7 +164,8 @@ describe('App embed tests', () => {
155
164
 
156
165
  appEmbed.render();
157
166
  await executeAfterWait(() => {
158
- expect(getIFrameSrc()).toBe(
167
+ expectUrlMatchesWithParams(
168
+ getIFrameSrc(),
159
169
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=false&profileAndHelpInNavBarHidden=false&${defaultParamsWithoutHiddenActions}&disableAction=[%22save%22,%22update%22]&disableHint=Access%20denied&hideAction=[%22${Action.ReportError}%22,%22download%22]${defaultParamsPost}#/home`,
160
170
  );
161
171
  });
@@ -170,7 +180,8 @@ describe('App embed tests', () => {
170
180
 
171
181
  appEmbed.render();
172
182
  await executeAfterWait(() => {
173
- expect(getIFrameSrc()).toBe(
183
+ expectUrlMatchesWithParams(
184
+ getIFrameSrc(),
174
185
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}&tag=Finance${defaultParamsPost}#/home`,
175
186
  );
176
187
  });
@@ -184,7 +195,8 @@ describe('App embed tests', () => {
184
195
 
185
196
  appEmbed.render();
186
197
  await executeAfterWait(() => {
187
- expect(getIFrameSrc()).toBe(
198
+ expectUrlMatchesWithParams(
199
+ getIFrameSrc(),
188
200
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&enableSearchAssist=true${defaultParams}${defaultParamsPost}#/home`,
189
201
  );
190
202
  });
@@ -193,9 +205,7 @@ describe('App embed tests', () => {
193
205
  describe('Navigate to Page API', () => {
194
206
  const path = 'pinboard/e0836cad-4fdf-42d4-bd97-567a6b2a6058';
195
207
  beforeEach(() => {
196
- jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
197
- () => 'http://tshost',
198
- );
208
+ jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(() => 'http://tshost');
199
209
  });
200
210
 
201
211
  test('when app is AppEmbed after navigateToPage function call, new path should be set to iframe', async () => {
@@ -207,7 +217,8 @@ describe('App embed tests', () => {
207
217
  });
208
218
  await appEmbed.render();
209
219
  appEmbed.navigateToPage(path);
210
- expect(getIFrameSrc()).toBe(
220
+ expectUrlMatchesWithParams(
221
+ getIFrameSrc(),
211
222
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}${defaultParamsPost}#/${path}`,
212
223
  );
213
224
  });