@thoughtspot/visual-embed-sdk 1.10.0 → 1.10.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 (76) hide show
  1. package/dist/src/auth.d.ts +18 -5
  2. package/dist/src/embed/base.d.ts +36 -6
  3. package/dist/src/embed/pinboard.d.ts +91 -0
  4. package/dist/src/index.d.ts +3 -2
  5. package/dist/src/types.d.ts +24 -0
  6. package/dist/src/utils/authService.d.ts +1 -0
  7. package/dist/src/utils/plugin.d.ts +0 -0
  8. package/dist/src/utils/processData.d.ts +1 -1
  9. package/dist/src/utils.d.ts +1 -0
  10. package/dist/src/v1/api.d.ts +19 -0
  11. package/dist/tsembed.es.js +544 -35
  12. package/dist/tsembed.js +542 -34
  13. package/lib/package.json +2 -1
  14. package/lib/src/auth.d.ts +18 -5
  15. package/lib/src/auth.js +51 -12
  16. package/lib/src/auth.js.map +1 -1
  17. package/lib/src/auth.spec.js +69 -11
  18. package/lib/src/auth.spec.js.map +1 -1
  19. package/lib/src/embed/base.d.ts +36 -6
  20. package/lib/src/embed/base.js +79 -11
  21. package/lib/src/embed/base.js.map +1 -1
  22. package/lib/src/embed/base.spec.js +51 -3
  23. package/lib/src/embed/base.spec.js.map +1 -1
  24. package/lib/src/embed/embed.spec.js +1 -1
  25. package/lib/src/embed/embed.spec.js.map +1 -1
  26. package/lib/src/embed/pinboard.d.ts +91 -0
  27. package/lib/src/embed/pinboard.js +110 -0
  28. package/lib/src/embed/pinboard.js.map +1 -0
  29. package/lib/src/embed/ts-embed.js +9 -10
  30. package/lib/src/embed/ts-embed.js.map +1 -1
  31. package/lib/src/embed/ts-embed.spec.js +16 -6
  32. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  33. package/lib/src/index.d.ts +3 -2
  34. package/lib/src/index.js +3 -2
  35. package/lib/src/index.js.map +1 -1
  36. package/lib/src/test/test-utils.js +1 -1
  37. package/lib/src/test/test-utils.js.map +1 -1
  38. package/lib/src/types.d.ts +24 -0
  39. package/lib/src/types.js +10 -0
  40. package/lib/src/types.js.map +1 -1
  41. package/lib/src/utils/authService.d.ts +1 -0
  42. package/lib/src/utils/authService.js +23 -3
  43. package/lib/src/utils/authService.js.map +1 -1
  44. package/lib/src/utils/authService.spec.js +21 -5
  45. package/lib/src/utils/authService.spec.js.map +1 -1
  46. package/lib/src/utils/plugin.d.ts +0 -0
  47. package/lib/src/utils/plugin.js +1 -0
  48. package/lib/src/utils/plugin.js.map +1 -0
  49. package/lib/src/utils/processData.d.ts +1 -1
  50. package/lib/src/utils/processData.js +37 -3
  51. package/lib/src/utils/processData.js.map +1 -1
  52. package/lib/src/utils/processData.spec.js +106 -4
  53. package/lib/src/utils/processData.spec.js.map +1 -1
  54. package/lib/src/utils.d.ts +1 -0
  55. package/lib/src/utils.js +4 -0
  56. package/lib/src/utils.js.map +1 -1
  57. package/lib/src/utils.spec.js +14 -1
  58. package/lib/src/utils.spec.js.map +1 -1
  59. package/lib/src/visual-embed-sdk.d.ts +124 -8
  60. package/package.json +2 -1
  61. package/src/auth.spec.ts +90 -11
  62. package/src/auth.ts +74 -16
  63. package/src/embed/base.spec.ts +58 -4
  64. package/src/embed/base.ts +98 -17
  65. package/src/embed/embed.spec.ts +1 -1
  66. package/src/embed/ts-embed.spec.ts +19 -9
  67. package/src/embed/ts-embed.ts +15 -12
  68. package/src/index.ts +5 -1
  69. package/src/test/test-utils.ts +1 -1
  70. package/src/types.ts +26 -0
  71. package/src/utils/authService.spec.ts +31 -5
  72. package/src/utils/authService.ts +29 -3
  73. package/src/utils/processData.spec.ts +139 -4
  74. package/src/utils/processData.ts +54 -4
  75. package/src/utils.spec.ts +26 -0
  76. package/src/utils.ts +5 -0
@@ -1,9 +1,20 @@
1
1
  import * as processDataInstance from './processData';
2
2
  import * as answerServiceInstance from './answerService';
3
3
  import * as auth from '../auth';
4
- import { EmbedEvent, OperationType } from '../types';
4
+ import * as base from '../embed/base';
5
+ import { EmbedEvent, OperationType, AuthType } from '../types';
5
6
 
6
7
  describe('Unit test for process data', () => {
8
+ beforeAll(() => {
9
+ base.init({
10
+ thoughtSpotHost: '',
11
+ authType: AuthType.None,
12
+ });
13
+ });
14
+ afterEach(() => {
15
+ jest.resetAllMocks();
16
+ });
17
+
7
18
  const thoughtSpotHost = 'http://localhost';
8
19
  test('processDataInstance, when operation is GetChartWithData', () => {
9
20
  const answerService = {};
@@ -34,10 +45,11 @@ describe('Unit test for process data', () => {
34
45
  'processCustomAction',
35
46
  ).mockImplementation(async () => ({}));
36
47
  expect(
37
- processDataInstance.getProcessData(
48
+ processDataInstance.processEventData(
38
49
  EmbedEvent.CustomAction,
39
50
  processedData,
40
51
  thoughtSpotHost,
52
+ null,
41
53
  ),
42
54
  ).toStrictEqual(processedData);
43
55
  });
@@ -52,10 +64,11 @@ describe('Unit test for process data', () => {
52
64
  answerServiceInstance,
53
65
  'getAnswerServiceInstance',
54
66
  ).mockImplementation(async () => ({}));
55
- processDataInstance.getProcessData(
67
+ processDataInstance.processEventData(
56
68
  EmbedEvent.Data,
57
69
  processedData,
58
70
  thoughtSpotHost,
71
+ null,
59
72
  );
60
73
  expect(processDataInstance.processCustomAction).not.toBeCalled();
61
74
  });
@@ -68,12 +81,134 @@ describe('Unit test for process data', () => {
68
81
  };
69
82
  const e = { type: EmbedEvent.AuthInit, data: sessionInfo };
70
83
  jest.spyOn(auth, 'initSession').mockReturnValue(null);
71
- expect(processDataInstance.getProcessData(e.type, e, '')).toEqual({
84
+ jest.spyOn(base, 'notifyAuthSuccess');
85
+ expect(
86
+ processDataInstance.processEventData(e.type, e, '', null),
87
+ ).toEqual({
72
88
  type: e.type,
73
89
  data: {
74
90
  userGUID: sessionInfo.userGUID,
75
91
  },
76
92
  });
77
93
  expect(auth.initSession).toBeCalledWith(sessionInfo);
94
+ expect(base.notifyAuthSuccess).toBeCalled();
95
+ });
96
+
97
+ test('AuthExpire autoLogin false', () => {
98
+ const e = { type: EmbedEvent.AuthExpire };
99
+ jest.spyOn(base, 'notifyAuthFailure');
100
+ jest.spyOn(base, 'handleAuth');
101
+ jest.spyOn(base, 'getEmbedConfig').mockReturnValue({
102
+ autoLogin: false,
103
+ });
104
+ expect(
105
+ processDataInstance.processEventData(e.type, e, '', null),
106
+ ).toEqual({
107
+ type: e.type,
108
+ });
109
+ expect(base.notifyAuthFailure).toBeCalledWith(
110
+ auth.AuthFailureType.EXPIRY,
111
+ );
112
+ expect(base.handleAuth).not.toHaveBeenCalled();
113
+ });
114
+
115
+ test('AuthExpire autoLogin true', () => {
116
+ const e = { type: EmbedEvent.AuthExpire };
117
+ jest.spyOn(base, 'notifyAuthFailure');
118
+ jest.spyOn(base, 'handleAuth').mockResolvedValue(true);
119
+ jest.spyOn(base, 'getEmbedConfig').mockReturnValue({
120
+ autoLogin: true,
121
+ });
122
+ expect(
123
+ processDataInstance.processEventData(e.type, e, '', null),
124
+ ).toEqual({
125
+ type: e.type,
126
+ });
127
+ expect(base.notifyAuthFailure).toBeCalledWith(
128
+ auth.AuthFailureType.EXPIRY,
129
+ );
130
+ expect(base.handleAuth).toBeCalled();
131
+ });
132
+
133
+ test('NoCookieAccess no suppress alert', () => {
134
+ const e = { type: EmbedEvent.NoCookieAccess };
135
+ jest.spyOn(base, 'notifyAuthFailure');
136
+ jest.spyOn(base, 'getEmbedConfig').mockReturnValue({
137
+ loginFailedMessage: 'Hello',
138
+ suppressNoCookieAccessAlert: false,
139
+ });
140
+ jest.spyOn(window, 'alert').mockImplementation(() => undefined);
141
+ const el: any = {};
142
+ expect(processDataInstance.processEventData(e.type, e, '', el)).toEqual(
143
+ {
144
+ type: e.type,
145
+ },
146
+ );
147
+ expect(base.notifyAuthFailure).toBeCalledWith(
148
+ auth.AuthFailureType.NO_COOKIE_ACCESS,
149
+ );
150
+ expect(window.alert).toBeCalled();
151
+ expect(el.innerHTML).toBe('Hello');
152
+ });
153
+
154
+ test('NoCookieAccess suppressAlert=true', () => {
155
+ const e = { type: EmbedEvent.NoCookieAccess };
156
+ jest.spyOn(base, 'notifyAuthFailure');
157
+ jest.spyOn(base, 'getEmbedConfig').mockReturnValue({
158
+ loginFailedMessage: 'Hello',
159
+ suppressNoCookieAccessAlert: true,
160
+ });
161
+ jest.spyOn(window, 'alert').mockReset();
162
+ jest.spyOn(window, 'alert').mockImplementation(() => undefined);
163
+ const el: any = {};
164
+ expect(processDataInstance.processEventData(e.type, e, '', el)).toEqual(
165
+ {
166
+ type: e.type,
167
+ },
168
+ );
169
+ expect(base.notifyAuthFailure).toBeCalledWith(
170
+ auth.AuthFailureType.NO_COOKIE_ACCESS,
171
+ );
172
+ expect(window.alert).not.toBeCalled();
173
+ expect(el.innerHTML).toBe('Hello');
174
+ });
175
+
176
+ test('process authFailure', () => {
177
+ const e = { type: EmbedEvent.AuthFailure };
178
+ jest.spyOn(base, 'notifyAuthFailure');
179
+ jest.spyOn(base, 'getEmbedConfig').mockReturnValue({
180
+ loginFailedMessage: 'Hello',
181
+ });
182
+ const el: any = {};
183
+ expect(processDataInstance.processEventData(e.type, e, '', el)).toEqual(
184
+ {
185
+ type: e.type,
186
+ },
187
+ );
188
+ expect(base.notifyAuthFailure).toBeCalledWith(
189
+ auth.AuthFailureType.OTHER,
190
+ );
191
+ expect(el.innerHTML).toBe('Hello');
192
+ });
193
+
194
+ test('process authLogout', () => {
195
+ base.init({
196
+ loginFailedMessage: 'Hello',
197
+ autoLogin: true,
198
+ thoughtSpotHost: '',
199
+ authType: AuthType.None,
200
+ });
201
+ jest.spyOn(base, 'getEmbedConfig').mockRestore();
202
+ const e = { type: EmbedEvent.AuthLogout };
203
+ jest.spyOn(base, 'notifyLogout');
204
+ const el: any = {};
205
+ expect(processDataInstance.processEventData(e.type, e, '', el)).toEqual(
206
+ {
207
+ type: e.type,
208
+ },
209
+ );
210
+ expect(base.notifyLogout).toBeCalled();
211
+ expect(el.innerHTML).toBe('Hello');
212
+ expect(base.getEmbedConfig().autoLogin).toBe(false);
78
213
  });
79
214
  });
@@ -1,5 +1,12 @@
1
- import { getEmbedConfig, handleAuth } from '../embed/base';
2
- import { initSession } from '../auth';
1
+ import {
2
+ disableAutoLogin,
3
+ getEmbedConfig,
4
+ handleAuth,
5
+ notifyAuthFailure,
6
+ notifyAuthSuccess,
7
+ notifyLogout,
8
+ } from '../embed/base';
9
+ import { AuthFailureType, initSession } from '../auth';
3
10
  import { EmbedEvent, OperationType } from '../types';
4
11
  import { getAnswerServiceInstance } from './answerService';
5
12
 
@@ -28,6 +35,7 @@ export function processCustomAction(e: any, thoughtSpotHost: string) {
28
35
  function processAuthInit(e: any) {
29
36
  // Store user session details sent by app.
30
37
  initSession(e.data);
38
+ notifyAuthSuccess();
31
39
 
32
40
  // Expose only allowed details (eg: userGUID) back to SDK users.
33
41
  return {
@@ -43,14 +51,50 @@ function processAuthExpire(e: any) {
43
51
  if (autoLogin) {
44
52
  handleAuth();
45
53
  }
54
+ notifyAuthFailure(AuthFailureType.EXPIRY);
46
55
  return e;
47
56
  }
48
57
 
49
- export function getProcessData(
58
+ function processNoCookieAccess(e: any, containerEl: Element) {
59
+ const {
60
+ loginFailedMessage,
61
+ suppressNoCookieAccessAlert,
62
+ } = getEmbedConfig();
63
+ if (!suppressNoCookieAccessAlert) {
64
+ // eslint-disable-next-line no-alert
65
+ alert(
66
+ 'Third party cookie access is blocked on this browser, please allow third party cookies for this to work properly. \nYou can use `suppressNoCookieAccessAlert` to suppress this message.',
67
+ );
68
+ }
69
+ // eslint-disable-next-line no-param-reassign
70
+ containerEl.innerHTML = loginFailedMessage;
71
+ notifyAuthFailure(AuthFailureType.NO_COOKIE_ACCESS);
72
+ return e;
73
+ }
74
+
75
+ function processAuthFailure(e: any, containerEl: Element) {
76
+ const { loginFailedMessage } = getEmbedConfig();
77
+ // eslint-disable-next-line no-param-reassign
78
+ containerEl.innerHTML = loginFailedMessage;
79
+ notifyAuthFailure(AuthFailureType.OTHER);
80
+ return e;
81
+ }
82
+
83
+ function processAuthLogout(e: any, containerEl: Element) {
84
+ const { loginFailedMessage } = getEmbedConfig();
85
+ // eslint-disable-next-line no-param-reassign
86
+ containerEl.innerHTML = loginFailedMessage;
87
+ disableAutoLogin();
88
+ notifyLogout();
89
+ return e;
90
+ }
91
+
92
+ export function processEventData(
50
93
  type: EmbedEvent,
51
94
  e: any,
52
95
  thoughtSpotHost: string,
53
- ) {
96
+ containerEl: Element,
97
+ ): any {
54
98
  switch (type) {
55
99
  case EmbedEvent.CustomAction:
56
100
  return processCustomAction(e, thoughtSpotHost);
@@ -58,6 +102,12 @@ export function getProcessData(
58
102
  return processAuthInit(e);
59
103
  case EmbedEvent.AuthExpire:
60
104
  return processAuthExpire(e);
105
+ case EmbedEvent.NoCookieAccess:
106
+ return processNoCookieAccess(e, containerEl);
107
+ case EmbedEvent.AuthFailure:
108
+ return processAuthFailure(e, containerEl);
109
+ case EmbedEvent.AuthLogout:
110
+ return processAuthLogout(e, containerEl);
61
111
  default:
62
112
  }
63
113
  return e;
package/src/utils.spec.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  getCssDimension,
9
9
  getEncodedQueryParamsString,
10
10
  appendToUrlHash,
11
+ getRedirectUrl,
11
12
  } from './utils';
12
13
  import { RuntimeFilterOp } from './types';
13
14
 
@@ -80,6 +81,31 @@ describe('unit test for utils', () => {
80
81
  );
81
82
  });
82
83
 
84
+ describe('getRedirectURL', () => {
85
+ test('Should return correct value when path is undefined', () => {
86
+ expect(getRedirectUrl('http://myhost:3000', 'hashFrag')).toBe(
87
+ 'http://myhost:3000#hashFrag',
88
+ );
89
+ expect(getRedirectUrl('http://xyz.com/#foo', 'bar')).toBe(
90
+ 'http://xyz.com/#foobar',
91
+ );
92
+ });
93
+
94
+ test('Should return correct value when path is set', () => {
95
+ Object.defineProperty(window.location, 'origin', {
96
+ get: () => 'http://myhost:3000',
97
+ });
98
+
99
+ expect(
100
+ getRedirectUrl('http://myhost:3000/', 'hashFrag', '/bar'),
101
+ ).toBe('http://myhost:3000/bar#hashFrag');
102
+
103
+ expect(
104
+ getRedirectUrl('http://myhost:3000/#/foo', 'hashFrag', '#/bar'),
105
+ ).toBe('http://myhost:3000/#/barhashFrag');
106
+ });
107
+ });
108
+
83
109
  test('getEncodedQueryParamsString', () => {
84
110
  expect(getEncodedQueryParamsString('')).toBe('');
85
111
  expect(getEncodedQueryParamsString('test')).toBe('dGVzdA');
package/src/utils.ts CHANGED
@@ -121,6 +121,11 @@ export const appendToUrlHash = (url: string, stringToAppend: string) => {
121
121
  return outputUrl;
122
122
  };
123
123
 
124
+ export function getRedirectUrl(url: string, stringToAppend: string, path = '') {
125
+ const targetUrl = path ? new URL(path, window.location.origin).href : url;
126
+ return appendToUrlHash(targetUrl, stringToAppend);
127
+ }
128
+
124
129
  export const getEncodedQueryParamsString = (queryString: string) => {
125
130
  if (!queryString) {
126
131
  return queryString;