@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.
- package/dist/src/auth.d.ts +18 -5
- package/dist/src/embed/base.d.ts +36 -6
- package/dist/src/embed/pinboard.d.ts +91 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/types.d.ts +24 -0
- package/dist/src/utils/authService.d.ts +1 -0
- package/dist/src/utils/plugin.d.ts +0 -0
- package/dist/src/utils/processData.d.ts +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/v1/api.d.ts +19 -0
- package/dist/tsembed.es.js +544 -35
- package/dist/tsembed.js +542 -34
- package/lib/package.json +2 -1
- package/lib/src/auth.d.ts +18 -5
- package/lib/src/auth.js +51 -12
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.js +69 -11
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts +36 -6
- package/lib/src/embed/base.js +79 -11
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +51 -3
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/embed.spec.js +1 -1
- package/lib/src/embed/embed.spec.js.map +1 -1
- package/lib/src/embed/pinboard.d.ts +91 -0
- package/lib/src/embed/pinboard.js +110 -0
- package/lib/src/embed/pinboard.js.map +1 -0
- package/lib/src/embed/ts-embed.js +9 -10
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +16 -6
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +3 -2
- package/lib/src/index.js +3 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/test/test-utils.js +1 -1
- package/lib/src/test/test-utils.js.map +1 -1
- package/lib/src/types.d.ts +24 -0
- package/lib/src/types.js +10 -0
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/authService.d.ts +1 -0
- package/lib/src/utils/authService.js +23 -3
- package/lib/src/utils/authService.js.map +1 -1
- package/lib/src/utils/authService.spec.js +21 -5
- package/lib/src/utils/authService.spec.js.map +1 -1
- package/lib/src/utils/plugin.d.ts +0 -0
- package/lib/src/utils/plugin.js +1 -0
- package/lib/src/utils/plugin.js.map +1 -0
- package/lib/src/utils/processData.d.ts +1 -1
- package/lib/src/utils/processData.js +37 -3
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js +106 -4
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/utils.d.ts +1 -0
- package/lib/src/utils.js +4 -0
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +14 -1
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +124 -8
- package/package.json +2 -1
- package/src/auth.spec.ts +90 -11
- package/src/auth.ts +74 -16
- package/src/embed/base.spec.ts +58 -4
- package/src/embed/base.ts +98 -17
- package/src/embed/embed.spec.ts +1 -1
- package/src/embed/ts-embed.spec.ts +19 -9
- package/src/embed/ts-embed.ts +15 -12
- package/src/index.ts +5 -1
- package/src/test/test-utils.ts +1 -1
- package/src/types.ts +26 -0
- package/src/utils/authService.spec.ts +31 -5
- package/src/utils/authService.ts +29 -3
- package/src/utils/processData.spec.ts +139 -4
- package/src/utils/processData.ts +54 -4
- package/src/utils.spec.ts +26 -0
- 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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
});
|
package/src/utils/processData.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
-
|
|
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;
|