@thoughtspot/visual-embed-sdk 1.13.0-alpha.2 → 1.13.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.
- package/CHANGELOG.md +31 -6
- package/README.md +1 -1
- package/dist/src/auth.d.ts +4 -1
- package/dist/src/auth.spec.d.ts +1 -0
- package/dist/src/embed/app.d.ts +5 -0
- package/dist/src/embed/liveboard.d.ts +12 -1
- package/dist/src/embed/search.d.ts +5 -0
- package/dist/src/embed/searchEmbed-basic-auth.spec.d.ts +1 -0
- package/dist/src/embed/ts-embed.d.ts +12 -3
- package/dist/src/errors.d.ts +2 -0
- package/dist/src/test/test-utils.d.ts +6 -0
- package/dist/src/types.d.ts +211 -4
- package/dist/src/utils/processTrigger.d.ts +1 -1
- package/dist/src/utils.d.ts +3 -1
- package/dist/tsembed.es.js +292 -24
- package/dist/tsembed.js +292 -24
- package/lib/package.json +4 -2
- package/lib/src/auth.d.ts +4 -1
- package/lib/src/auth.js +11 -2
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.d.ts +1 -0
- package/lib/src/auth.spec.js +13 -1
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/config.spec.js +7 -0
- package/lib/src/config.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +5 -0
- package/lib/src/embed/app.js +1 -1
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +18 -6
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/embed.spec.js +2 -0
- package/lib/src/embed/embed.spec.js.map +1 -1
- package/lib/src/embed/events.spec.js +3 -1
- package/lib/src/embed/events.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +12 -1
- package/lib/src/embed/liveboard.js +22 -4
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +33 -6
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/pinboard.spec.js +7 -5
- package/lib/src/embed/pinboard.spec.js.map +1 -1
- package/lib/src/embed/search.d.ts +5 -0
- package/lib/src/embed/search.js +10 -2
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/search.spec.js +9 -1
- package/lib/src/embed/search.spec.js.map +1 -1
- package/lib/src/embed/searchEmbed-basic-auth.spec.d.ts +1 -0
- package/lib/src/embed/searchEmbed-basic-auth.spec.js +96 -0
- package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -0
- package/lib/src/embed/ts-embed.d.ts +12 -3
- package/lib/src/embed/ts-embed.js +29 -10
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +38 -5
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts +2 -0
- package/lib/src/errors.js +2 -0
- package/lib/src/errors.js.map +1 -1
- package/lib/src/react/index.js +3 -2
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +6 -4
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/test/test-utils.d.ts +6 -0
- package/lib/src/test/test-utils.js +15 -0
- package/lib/src/test/test-utils.js.map +1 -1
- package/lib/src/types.d.ts +211 -4
- package/lib/src/types.js +176 -0
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/processTrigger.d.ts +1 -1
- package/lib/src/utils/processTrigger.js +28 -8
- package/lib/src/utils/processTrigger.js.map +1 -1
- package/lib/src/utils/processTrigger.spec.js +11 -1
- package/lib/src/utils/processTrigger.spec.js.map +1 -1
- package/lib/src/utils.d.ts +3 -1
- package/lib/src/utils.js +20 -0
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +22 -1
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +240 -9
- package/package.json +4 -2
- package/src/auth.spec.ts +20 -1
- package/src/auth.ts +12 -2
- package/src/config.spec.ts +11 -0
- package/src/embed/app.spec.ts +22 -3
- package/src/embed/app.ts +6 -0
- package/src/embed/embed.spec.ts +2 -0
- package/src/embed/events.spec.ts +3 -0
- package/src/embed/liveboard.spec.ts +46 -6
- package/src/embed/liveboard.ts +34 -2
- package/src/embed/pinboard.spec.ts +8 -6
- package/src/embed/search.spec.ts +11 -1
- package/src/embed/search.ts +20 -1
- package/src/embed/searchEmbed-basic-auth.spec.ts +115 -0
- package/src/embed/ts-embed.spec.ts +51 -5
- package/src/embed/ts-embed.ts +40 -12
- package/src/errors.ts +3 -0
- package/src/react/index.spec.tsx +7 -2
- package/src/react/index.tsx +3 -2
- package/src/test/test-utils.ts +16 -0
- package/src/types.ts +209 -0
- package/src/utils/processTrigger.spec.ts +11 -1
- package/src/utils/processTrigger.ts +36 -12
- package/src/utils.spec.ts +29 -0
- package/src/utils.ts +34 -1
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { LiveboardEmbed, LiveboardViewConfig } from './liveboard';
|
|
2
2
|
import { init } from '../index';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Action,
|
|
5
|
+
AuthType,
|
|
6
|
+
EmbedEvent,
|
|
7
|
+
HostEvent,
|
|
8
|
+
RuntimeFilterOp,
|
|
9
|
+
} from '../types';
|
|
4
10
|
import {
|
|
5
11
|
executeAfterWait,
|
|
6
12
|
getDocumentBody,
|
|
@@ -8,6 +14,7 @@ import {
|
|
|
8
14
|
getRootEl,
|
|
9
15
|
} from '../test/test-utils';
|
|
10
16
|
import { version } from '../../package.json';
|
|
17
|
+
import * as processTriggerInstance from '../utils/processTrigger';
|
|
11
18
|
|
|
12
19
|
const defaultViewConfig = {
|
|
13
20
|
frameParams: {
|
|
@@ -16,10 +23,14 @@ const defaultViewConfig = {
|
|
|
16
23
|
},
|
|
17
24
|
};
|
|
18
25
|
const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
|
|
26
|
+
const activeTabId = '502693ba-9818-4e71-8ecd-d1a194e46861';
|
|
19
27
|
const vizId = '6e73f724-660e-11eb-ae93-0242ac130002';
|
|
20
28
|
const thoughtSpotHost = 'tshost';
|
|
21
|
-
const
|
|
29
|
+
const defaultParamsSansHideAction = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
|
|
30
|
+
const defaultParams = `${defaultParamsSansHideAction}&hideAction=[%22${Action.ReportError}%22]`;
|
|
22
31
|
const prefixParams = '&isLiveboardEmbed=true&isPinboardV2Enabled=false';
|
|
32
|
+
const prefixParamsVizEmbed =
|
|
33
|
+
'&isLiveboardEmbed=true&isVizEmbed=true&isPinboardV2Enabled=false';
|
|
23
34
|
|
|
24
35
|
beforeAll(() => {
|
|
25
36
|
init({
|
|
@@ -60,7 +71,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
60
71
|
liveboardEmbed.render();
|
|
61
72
|
await executeAfterWait(() => {
|
|
62
73
|
expect(getIFrameSrc()).toBe(
|
|
63
|
-
`http://${thoughtSpotHost}/?embedApp=true${
|
|
74
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParamsSansHideAction}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied&hideAction=[%22${Action.ReportError}%22]${prefixParams}#/embed/viz/${liveboardId}`,
|
|
64
75
|
);
|
|
65
76
|
});
|
|
66
77
|
});
|
|
@@ -78,7 +89,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
78
89
|
liveboardEmbed.render();
|
|
79
90
|
await executeAfterWait(() => {
|
|
80
91
|
expect(getIFrameSrc()).toBe(
|
|
81
|
-
`http://${thoughtSpotHost}/?embedApp=true${
|
|
92
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParamsSansHideAction}&hideAction=[%22${Action.ReportError}%22,%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${liveboardId}`,
|
|
82
93
|
);
|
|
83
94
|
});
|
|
84
95
|
});
|
|
@@ -152,7 +163,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
152
163
|
liveboardEmbed.render();
|
|
153
164
|
await executeAfterWait(() => {
|
|
154
165
|
expect(getIFrameSrc()).toBe(
|
|
155
|
-
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${
|
|
166
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${liveboardId}/${vizId}`,
|
|
156
167
|
);
|
|
157
168
|
});
|
|
158
169
|
});
|
|
@@ -173,7 +184,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
173
184
|
liveboardEmbed.render();
|
|
174
185
|
await executeAfterWait(() => {
|
|
175
186
|
expect(getIFrameSrc()).toBe(
|
|
176
|
-
`http://${thoughtSpotHost}/?embedApp=true&col1=sales&op1=EQ&val1=1000${defaultParams}${
|
|
187
|
+
`http://${thoughtSpotHost}/?embedApp=true&col1=sales&op1=EQ&val1=1000${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${liveboardId}/${vizId}`,
|
|
177
188
|
);
|
|
178
189
|
});
|
|
179
190
|
});
|
|
@@ -209,4 +220,33 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
209
220
|
);
|
|
210
221
|
});
|
|
211
222
|
});
|
|
223
|
+
test('should process the trigger, for vizEmbed', async () => {
|
|
224
|
+
const mockProcessTrigger = spyOn(
|
|
225
|
+
processTriggerInstance,
|
|
226
|
+
'processTrigger',
|
|
227
|
+
);
|
|
228
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
229
|
+
enableVizTransformations: true,
|
|
230
|
+
...defaultViewConfig,
|
|
231
|
+
vizId: '1234',
|
|
232
|
+
liveboardId,
|
|
233
|
+
} as LiveboardViewConfig);
|
|
234
|
+
liveboardEmbed.render();
|
|
235
|
+
const result = await liveboardEmbed.trigger(HostEvent.Pin);
|
|
236
|
+
expect(mockProcessTrigger).toBeCalled();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('should render active tab when activeTab present', async () => {
|
|
240
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
241
|
+
liveboardId,
|
|
242
|
+
activeTabId,
|
|
243
|
+
liveboardV2: true,
|
|
244
|
+
} as LiveboardViewConfig);
|
|
245
|
+
liveboardEmbed.render();
|
|
246
|
+
await executeAfterWait(() => {
|
|
247
|
+
expect(getIFrameSrc()).toBe(
|
|
248
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&isLiveboardEmbed=true&isPinboardV2Enabled=true#/embed/viz/${liveboardId}/tab/${activeTabId}`,
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
212
252
|
});
|
package/src/embed/liveboard.ts
CHANGED
|
@@ -82,6 +82,11 @@ export interface LiveboardViewConfig extends ViewConfig {
|
|
|
82
82
|
* @hidden
|
|
83
83
|
*/
|
|
84
84
|
liveboardV2?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Tab Id of the Liveboard that is supposed to be active
|
|
87
|
+
* @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
|
|
88
|
+
*/
|
|
89
|
+
activeTabId?: string;
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
/**
|
|
@@ -110,6 +115,8 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
110
115
|
defaultHeight,
|
|
111
116
|
visibleVizs,
|
|
112
117
|
liveboardV2 = false,
|
|
118
|
+
vizId,
|
|
119
|
+
activeTabId,
|
|
113
120
|
} = this.viewConfig;
|
|
114
121
|
|
|
115
122
|
const preventLiveboardFilterRemoval =
|
|
@@ -134,6 +141,9 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
134
141
|
params[Param.visibleVizs] = visibleVizs;
|
|
135
142
|
}
|
|
136
143
|
params[Param.livedBoardEmbed] = true;
|
|
144
|
+
if (vizId) {
|
|
145
|
+
params[Param.vizEmbed] = true;
|
|
146
|
+
}
|
|
137
147
|
params[Param.LiveboardV2Enabled] = liveboardV2;
|
|
138
148
|
const queryParams = getQueryParamString(params, true);
|
|
139
149
|
|
|
@@ -152,6 +162,7 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
152
162
|
liveboardId: string,
|
|
153
163
|
vizId?: string,
|
|
154
164
|
runtimeFilters?: RuntimeFilter[],
|
|
165
|
+
activeTabId?: string,
|
|
155
166
|
) {
|
|
156
167
|
const filterQuery = getFilterQuery(runtimeFilters || []);
|
|
157
168
|
const queryParams = this.getEmbedParams();
|
|
@@ -164,6 +175,9 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
164
175
|
false,
|
|
165
176
|
false,
|
|
166
177
|
)}/viz/${liveboardId}`;
|
|
178
|
+
if (activeTabId) {
|
|
179
|
+
url = `${url}/tab/${activeTabId}`;
|
|
180
|
+
}
|
|
167
181
|
if (vizId) {
|
|
168
182
|
url = `${url}/${vizId}`;
|
|
169
183
|
}
|
|
@@ -194,13 +208,26 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
194
208
|
}
|
|
195
209
|
};
|
|
196
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Triggers an event to the embedded app
|
|
213
|
+
* @param messageType The event type
|
|
214
|
+
* @param data The payload to send with the message
|
|
215
|
+
*/
|
|
216
|
+
public trigger(messageType: HostEvent, data: any = {}): Promise<any> {
|
|
217
|
+
const dataWithVizId = data;
|
|
218
|
+
if (this.viewConfig.vizId) {
|
|
219
|
+
dataWithVizId.vizId = this.viewConfig.vizId;
|
|
220
|
+
}
|
|
221
|
+
return super.trigger(messageType, dataWithVizId);
|
|
222
|
+
}
|
|
223
|
+
|
|
197
224
|
/**
|
|
198
225
|
* Render an embedded ThoughtSpot Liveboard or visualization
|
|
199
226
|
* @param renderOptions An object specifying the Liveboard ID,
|
|
200
227
|
* visualization ID and the runtime filters.
|
|
201
228
|
*/
|
|
202
229
|
public render(): LiveboardEmbed {
|
|
203
|
-
const { vizId, runtimeFilters } = this.viewConfig;
|
|
230
|
+
const { vizId, activeTabId, runtimeFilters } = this.viewConfig;
|
|
204
231
|
const liveboardId =
|
|
205
232
|
this.viewConfig.liveboardId ?? this.viewConfig.pinboardId;
|
|
206
233
|
|
|
@@ -219,7 +246,12 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
219
246
|
|
|
220
247
|
super.render();
|
|
221
248
|
|
|
222
|
-
const src = this.getIFrameSrc(
|
|
249
|
+
const src = this.getIFrameSrc(
|
|
250
|
+
liveboardId,
|
|
251
|
+
vizId,
|
|
252
|
+
runtimeFilters,
|
|
253
|
+
activeTabId,
|
|
254
|
+
);
|
|
223
255
|
this.renderV1Embed(src);
|
|
224
256
|
|
|
225
257
|
return this;
|
|
@@ -18,9 +18,11 @@ const defaultViewConfig = {
|
|
|
18
18
|
const pinboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
|
|
19
19
|
const vizId = '6e73f724-660e-11eb-ae93-0242ac130002';
|
|
20
20
|
const thoughtSpotHost = 'tshost';
|
|
21
|
-
const
|
|
21
|
+
const defaultParamsWithoutHideActions = `&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
|
|
22
|
+
const defaultParams = `${defaultParamsWithoutHideActions}&hideAction=[%22${Action.ReportError}%22]`;
|
|
22
23
|
const prefixParams = '&isLiveboardEmbed=true&isPinboardV2Enabled=false';
|
|
23
|
-
|
|
24
|
+
const prefixParamsVizEmbed =
|
|
25
|
+
'&isLiveboardEmbed=true&isVizEmbed=true&isPinboardV2Enabled=false';
|
|
24
26
|
beforeAll(() => {
|
|
25
27
|
init({
|
|
26
28
|
thoughtSpotHost,
|
|
@@ -60,7 +62,7 @@ describe('Pinboard/viz embed tests', () => {
|
|
|
60
62
|
pinboardEmbed.render();
|
|
61
63
|
await executeAfterWait(() => {
|
|
62
64
|
expect(getIFrameSrc()).toBe(
|
|
63
|
-
`http://${thoughtSpotHost}/?embedApp=true${
|
|
65
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParamsWithoutHideActions}&disableAction=[%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]&disableHint=Action%20denied&hideAction=[%22${Action.ReportError}%22]${prefixParams}#/embed/viz/${pinboardId}`,
|
|
64
66
|
);
|
|
65
67
|
});
|
|
66
68
|
});
|
|
@@ -78,7 +80,7 @@ describe('Pinboard/viz embed tests', () => {
|
|
|
78
80
|
pinboardEmbed.render();
|
|
79
81
|
await executeAfterWait(() => {
|
|
80
82
|
expect(getIFrameSrc()).toBe(
|
|
81
|
-
`http://${thoughtSpotHost}/?embedApp=true${
|
|
83
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParamsWithoutHideActions}&hideAction=[%22${Action.ReportError}%22,%22${Action.DownloadAsCsv}%22,%22${Action.DownloadAsPdf}%22,%22${Action.DownloadAsXlsx}%22]${prefixParams}#/embed/viz/${pinboardId}`,
|
|
82
84
|
);
|
|
83
85
|
});
|
|
84
86
|
});
|
|
@@ -152,7 +154,7 @@ describe('Pinboard/viz embed tests', () => {
|
|
|
152
154
|
pinboardEmbed.render();
|
|
153
155
|
await executeAfterWait(() => {
|
|
154
156
|
expect(getIFrameSrc()).toBe(
|
|
155
|
-
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${
|
|
157
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${pinboardId}/${vizId}`,
|
|
156
158
|
);
|
|
157
159
|
});
|
|
158
160
|
});
|
|
@@ -173,7 +175,7 @@ describe('Pinboard/viz embed tests', () => {
|
|
|
173
175
|
pinboardEmbed.render();
|
|
174
176
|
await executeAfterWait(() => {
|
|
175
177
|
expect(getIFrameSrc()).toBe(
|
|
176
|
-
`http://${thoughtSpotHost}/?embedApp=true&col1=sales&op1=EQ&val1=1000${defaultParams}${
|
|
178
|
+
`http://${thoughtSpotHost}/?embedApp=true&col1=sales&op1=EQ&val1=1000${defaultParams}${prefixParamsVizEmbed}#/embed/viz/${pinboardId}/${vizId}`,
|
|
177
179
|
);
|
|
178
180
|
});
|
|
179
181
|
});
|
package/src/embed/search.spec.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SearchEmbed, HiddenActionItemByDefaultForSearchEmbed } from './search';
|
|
2
|
+
import * as authInstance from '../auth';
|
|
2
3
|
import { init } from '../index';
|
|
3
4
|
import { Action, AuthType } from '../types';
|
|
4
5
|
import {
|
|
@@ -20,7 +21,10 @@ const answerId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
|
|
|
20
21
|
const thoughtSpotHost = 'tshost';
|
|
21
22
|
const defaultParams = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
|
|
22
23
|
const hideBydefault = `&hideAction=${fixedEncodeURI(
|
|
23
|
-
JSON.stringify(
|
|
24
|
+
JSON.stringify([
|
|
25
|
+
Action.ReportError,
|
|
26
|
+
...HiddenActionItemByDefaultForSearchEmbed,
|
|
27
|
+
]),
|
|
24
28
|
)}`;
|
|
25
29
|
const defaultParamsWithHiddenActions = defaultParams + hideBydefault;
|
|
26
30
|
const prefixParams = '&isSearchEmbed=true';
|
|
@@ -30,11 +34,15 @@ beforeAll(() => {
|
|
|
30
34
|
thoughtSpotHost,
|
|
31
35
|
authType: AuthType.None,
|
|
32
36
|
});
|
|
37
|
+
spyOn(window, 'alert');
|
|
33
38
|
});
|
|
34
39
|
|
|
35
40
|
describe('Search embed tests', () => {
|
|
36
41
|
beforeEach(() => {
|
|
37
42
|
document.body.innerHTML = getDocumentBody();
|
|
43
|
+
jest.spyOn(authInstance, 'getReleaseVersion').mockReturnValue(
|
|
44
|
+
'7.4.0.sw',
|
|
45
|
+
);
|
|
38
46
|
});
|
|
39
47
|
|
|
40
48
|
test('should render', async () => {
|
|
@@ -197,6 +205,7 @@ describe('Search embed tests', () => {
|
|
|
197
205
|
searchEmbed.render();
|
|
198
206
|
const hideActionUrl = fixedEncodeURI(
|
|
199
207
|
JSON.stringify([
|
|
208
|
+
Action.ReportError,
|
|
200
209
|
...hiddenActionsForSearch,
|
|
201
210
|
...HiddenActionItemByDefaultForSearchEmbed,
|
|
202
211
|
]),
|
|
@@ -220,6 +229,7 @@ describe('Search embed tests', () => {
|
|
|
220
229
|
searchEmbed.render();
|
|
221
230
|
const hideActionUrl = fixedEncodeURI(
|
|
222
231
|
JSON.stringify([
|
|
232
|
+
Action.ReportError,
|
|
223
233
|
...hiddenActionsForSearch,
|
|
224
234
|
...HiddenActionItemByDefaultForSearchEmbed,
|
|
225
235
|
]),
|
package/src/embed/search.ts
CHANGED
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { DataSourceVisualMode, DOMSelector, Param, Action } from '../types';
|
|
11
|
-
import { getQueryParamString } from '../utils';
|
|
11
|
+
import { getQueryParamString, checkReleaseVersionInBeta } from '../utils';
|
|
12
12
|
import { ViewConfig, TsEmbed } from './ts-embed';
|
|
13
13
|
import { version } from '../../package.json';
|
|
14
|
+
import { ERROR_MESSAGE } from '../errors';
|
|
15
|
+
import { getAuthPromise, getEmbedConfig } from './base';
|
|
16
|
+
import { getReleaseVersion } from '../auth';
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Configuration for search options
|
|
@@ -49,8 +52,13 @@ export interface SearchViewConfig extends ViewConfig {
|
|
|
49
52
|
* using raw answer data.
|
|
50
53
|
*/
|
|
51
54
|
hideResults?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* If set to true, expands all the data sources panel.
|
|
57
|
+
*/
|
|
58
|
+
expandAllDataSource?: boolean;
|
|
52
59
|
/**
|
|
53
60
|
* If set to true, the Search Assist feature is enabled.
|
|
61
|
+
* @version SDK: 1.13.0 | ThoughtSpot: 8.5.0.cl
|
|
54
62
|
*/
|
|
55
63
|
enableSearchAssist?: boolean;
|
|
56
64
|
/**
|
|
@@ -126,6 +134,7 @@ export class SearchEmbed extends TsEmbed {
|
|
|
126
134
|
private getIFrameSrc(answerId: string, dataSources?: string[]) {
|
|
127
135
|
const {
|
|
128
136
|
hideResults,
|
|
137
|
+
expandAllDataSource,
|
|
129
138
|
enableSearchAssist,
|
|
130
139
|
forceTable,
|
|
131
140
|
searchOptions,
|
|
@@ -184,6 +193,16 @@ export class SearchEmbed extends TsEmbed {
|
|
|
184
193
|
|
|
185
194
|
const src = this.getIFrameSrc(answerId, dataSources);
|
|
186
195
|
this.renderIFrame(src, this.viewConfig.frameParams);
|
|
196
|
+
getAuthPromise().then(() => {
|
|
197
|
+
if (
|
|
198
|
+
checkReleaseVersionInBeta(
|
|
199
|
+
getReleaseVersion(),
|
|
200
|
+
getEmbedConfig().suppressSearchEmbedBetaWarning,
|
|
201
|
+
)
|
|
202
|
+
) {
|
|
203
|
+
alert(ERROR_MESSAGE.SEARCHEMBED_BETA_WRANING_MESSAGE);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
187
206
|
return this;
|
|
188
207
|
}
|
|
189
208
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { SearchEmbed } from './search';
|
|
2
|
+
import * as baseInstance from './base';
|
|
3
|
+
import * as authService from '../utils/authService';
|
|
4
|
+
import * as authInstance from '../auth';
|
|
5
|
+
import * as config from '../config';
|
|
6
|
+
|
|
7
|
+
import { init } from '../index';
|
|
8
|
+
import { AuthType } from '../types';
|
|
9
|
+
import { getDocumentBody, getRootEl } from '../test/test-utils';
|
|
10
|
+
import { mockSessionInfo } from '../auth.spec';
|
|
11
|
+
import { ERROR_MESSAGE } from '../errors';
|
|
12
|
+
|
|
13
|
+
const thoughtSpotHost = 'tshost';
|
|
14
|
+
init({
|
|
15
|
+
thoughtSpotHost,
|
|
16
|
+
authType: AuthType.Basic,
|
|
17
|
+
username: 'tsadmin',
|
|
18
|
+
password: 'admin',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('Search embed tests when authType is Basic', () => {
|
|
22
|
+
function setupVersion(version: string) {
|
|
23
|
+
jest.spyOn(window, 'addEventListener').mockImplementationOnce(
|
|
24
|
+
(event, handler, options) => {
|
|
25
|
+
handler({
|
|
26
|
+
data: {
|
|
27
|
+
type: 'xyz',
|
|
28
|
+
},
|
|
29
|
+
ports: [3000],
|
|
30
|
+
source: null,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(
|
|
35
|
+
async () => ({
|
|
36
|
+
json: () => ({
|
|
37
|
+
...mockSessionInfo,
|
|
38
|
+
releaseVersion: version,
|
|
39
|
+
}),
|
|
40
|
+
status: 200,
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
jest.spyOn(authInstance, 'getReleaseVersion').mockReturnValue(version);
|
|
44
|
+
}
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
document.body.innerHTML = getDocumentBody();
|
|
47
|
+
jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValue(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
afterEach(() => {
|
|
51
|
+
jest.clearAllMocks();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('when releaseVersion is empty', async () => {
|
|
55
|
+
setupVersion('');
|
|
56
|
+
const mockAlert = spyOn(window, 'alert');
|
|
57
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
58
|
+
await searchEmbed.render();
|
|
59
|
+
expect(mockAlert).not.toBeCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("when releaseVersion is '7.0.1.cl' ", async () => {
|
|
63
|
+
setupVersion('7.0.1.cl');
|
|
64
|
+
const mockAlert = jest.spyOn(window, 'alert');
|
|
65
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
66
|
+
await searchEmbed.render();
|
|
67
|
+
expect(mockAlert).not.toBeCalled();
|
|
68
|
+
});
|
|
69
|
+
test('when releaseVersion is above 8.4.0.sw', async () => {
|
|
70
|
+
setupVersion('8.4.0.sw');
|
|
71
|
+
const mockAlert = jest.spyOn(window, 'alert');
|
|
72
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
73
|
+
await searchEmbed.render();
|
|
74
|
+
expect(mockAlert).not.toBeCalled();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('releaseVersion is above 8.4.0.sw', async () => {
|
|
78
|
+
setupVersion('8.8.0.sw');
|
|
79
|
+
jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
|
|
80
|
+
() => 'http://tshost',
|
|
81
|
+
);
|
|
82
|
+
const mockAlert = jest.spyOn(window, 'alert');
|
|
83
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
84
|
+
await searchEmbed.render();
|
|
85
|
+
expect(mockAlert).not.toBeCalled();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('Alert should not appear when suppressSearchEmbedBetaWarning is true and releaseVersion is ts7.dec.cl', async () => {
|
|
89
|
+
setupVersion('ts7.dec.cl');
|
|
90
|
+
jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
|
|
91
|
+
() => 'http://tshost',
|
|
92
|
+
);
|
|
93
|
+
jest.spyOn(baseInstance, 'getEmbedConfig').mockReturnValue({
|
|
94
|
+
suppressSearchEmbedBetaWarning: true,
|
|
95
|
+
});
|
|
96
|
+
const mockAlert = jest.spyOn(window, 'alert');
|
|
97
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
98
|
+
await searchEmbed.render();
|
|
99
|
+
expect(mockAlert).not.toBeCalled();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('Alert should not appear when suppressSearchEmbedBetaWarning is true and releaseVersion is 8.4.0.sw', async () => {
|
|
103
|
+
setupVersion('8.4.0.sw');
|
|
104
|
+
jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
|
|
105
|
+
() => 'http://tshost',
|
|
106
|
+
);
|
|
107
|
+
jest.spyOn(baseInstance, 'getEmbedConfig').mockReturnValue({
|
|
108
|
+
suppressSearchEmbedBetaWarning: true,
|
|
109
|
+
});
|
|
110
|
+
const mockAlert = jest.spyOn(window, 'alert');
|
|
111
|
+
const searchEmbed = new SearchEmbed(getRootEl(), {});
|
|
112
|
+
await searchEmbed.render();
|
|
113
|
+
expect(mockAlert).not.toBeCalled();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -34,9 +34,20 @@ const defaultViewConfig = {
|
|
|
34
34
|
const pinboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
|
|
35
35
|
const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
|
|
36
36
|
const thoughtSpotHost = 'tshost';
|
|
37
|
-
const defaultParamsForPinboardEmbed = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}`;
|
|
37
|
+
const defaultParamsForPinboardEmbed = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22${Action.ReportError}%22]`;
|
|
38
38
|
const defaultParamsPost = '&isPinboardV2Enabled=false';
|
|
39
39
|
|
|
40
|
+
beforeAll(() => {
|
|
41
|
+
spyOn(window, 'alert');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const customisations = {
|
|
45
|
+
style: {
|
|
46
|
+
customCSSUrl: 'http://localhost:3000',
|
|
47
|
+
},
|
|
48
|
+
content: {},
|
|
49
|
+
};
|
|
50
|
+
|
|
40
51
|
describe('Unit test case for ts embed', () => {
|
|
41
52
|
const mockMixPanelEvent = jest.spyOn(
|
|
42
53
|
mixpanelInstance,
|
|
@@ -55,6 +66,31 @@ describe('Unit test case for ts embed', () => {
|
|
|
55
66
|
init({
|
|
56
67
|
thoughtSpotHost: 'tshost',
|
|
57
68
|
authType: AuthType.None,
|
|
69
|
+
customisations,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('verify Customisations', async () => {
|
|
74
|
+
const mockEmbedEventPayload = {
|
|
75
|
+
type: EmbedEvent.APP_INIT,
|
|
76
|
+
data: {},
|
|
77
|
+
};
|
|
78
|
+
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
79
|
+
searchEmbed.render();
|
|
80
|
+
const mockPort: any = {
|
|
81
|
+
postMessage: jest.fn(),
|
|
82
|
+
};
|
|
83
|
+
await executeAfterWait(() => {
|
|
84
|
+
const iframe = getIFrameEl();
|
|
85
|
+
postMessageToParent(
|
|
86
|
+
iframe.contentWindow,
|
|
87
|
+
mockEmbedEventPayload,
|
|
88
|
+
mockPort,
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
expect(mockPort.postMessage).toHaveBeenCalledWith({
|
|
92
|
+
type: EmbedEvent.APP_INIT,
|
|
93
|
+
data: { customisations },
|
|
58
94
|
});
|
|
59
95
|
});
|
|
60
96
|
|
|
@@ -261,7 +297,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
261
297
|
|
|
262
298
|
describe('when visible actions are set', () => {
|
|
263
299
|
test('should throw error when there are both visible and hidden actions - pinboard', async () => {
|
|
264
|
-
spyOn(console, '
|
|
300
|
+
spyOn(console, 'error');
|
|
265
301
|
const pinboardEmbed = new PinboardEmbed(getRootEl(), {
|
|
266
302
|
hiddenActions: [Action.DownloadAsCsv],
|
|
267
303
|
visibleActions: [Action.DownloadAsCsv],
|
|
@@ -270,7 +306,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
270
306
|
} as LiveboardViewConfig);
|
|
271
307
|
await pinboardEmbed.render();
|
|
272
308
|
expect(pinboardEmbed['isError']).toBe(true);
|
|
273
|
-
expect(console.
|
|
309
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
274
310
|
'You cannot have both hidden actions and visible actions',
|
|
275
311
|
);
|
|
276
312
|
});
|
|
@@ -288,7 +324,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
288
324
|
hiddenActions: Array<Action>,
|
|
289
325
|
visibleActions: Array<Action>,
|
|
290
326
|
) {
|
|
291
|
-
spyOn(console, '
|
|
327
|
+
spyOn(console, 'error');
|
|
292
328
|
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
293
329
|
hiddenActions,
|
|
294
330
|
visibleActions,
|
|
@@ -297,7 +333,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
297
333
|
} as LiveboardViewConfig);
|
|
298
334
|
await liveboardEmbed.render();
|
|
299
335
|
expect(liveboardEmbed['isError']).toBe(true);
|
|
300
|
-
expect(console.
|
|
336
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
301
337
|
'You cannot have both hidden actions and visible actions',
|
|
302
338
|
);
|
|
303
339
|
}
|
|
@@ -346,14 +382,19 @@ describe('Unit test case for ts embed', () => {
|
|
|
346
382
|
});
|
|
347
383
|
|
|
348
384
|
test('Error should be true', async () => {
|
|
385
|
+
spyOn(console, 'error');
|
|
349
386
|
const tsEmbed = new SearchEmbed(getRootEl(), {});
|
|
350
387
|
tsEmbed.render();
|
|
351
388
|
expect(tsEmbed['isError']).toBe(true);
|
|
389
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
390
|
+
'You need to init the ThoughtSpot SDK module first',
|
|
391
|
+
);
|
|
352
392
|
});
|
|
353
393
|
});
|
|
354
394
|
|
|
355
395
|
describe('V1Embed ', () => {
|
|
356
396
|
test('when isRendered is true than isError will be true', () => {
|
|
397
|
+
spyOn(console, 'error');
|
|
357
398
|
const viEmbedIns = new tsEmbedInstance.V1Embed(
|
|
358
399
|
getRootEl(),
|
|
359
400
|
defaultViewConfig,
|
|
@@ -362,11 +403,15 @@ describe('Unit test case for ts embed', () => {
|
|
|
362
403
|
viEmbedIns.render();
|
|
363
404
|
viEmbedIns.on(EmbedEvent.CustomAction, jest.fn()).render();
|
|
364
405
|
expect(viEmbedIns['isError']).toBe(true);
|
|
406
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
407
|
+
'Please register event handlers before calling render',
|
|
408
|
+
);
|
|
365
409
|
});
|
|
366
410
|
});
|
|
367
411
|
|
|
368
412
|
describe('Navigate to Page API', () => {
|
|
369
413
|
const path = 'viz/e0836cad-4fdf-42d4-bd97-567a6b2a6058';
|
|
414
|
+
|
|
370
415
|
beforeEach(() => {
|
|
371
416
|
jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
|
|
372
417
|
() => 'http://tshost',
|
|
@@ -415,6 +460,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
415
460
|
});
|
|
416
461
|
describe('Navigate to Page API - Pinboard', () => {
|
|
417
462
|
const path = 'pinboard/e0836cad-4fdf-42d4-bd97-567a6b2a6058';
|
|
463
|
+
|
|
418
464
|
beforeEach(() => {
|
|
419
465
|
jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
|
|
420
466
|
() => 'http://tshost',
|