@thoughtspot/visual-embed-sdk 1.46.5 → 1.47.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/cjs/package.json +1 -1
- package/cjs/src/embed/app.d.ts +0 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +1 -2
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +0 -10
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +1 -1
- package/cjs/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.js +7 -1
- package/cjs/src/embed/hostEventClient/utils.js.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.spec.js +80 -5
- package/cjs/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +12 -4
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +28 -67
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.d.ts +0 -1
- package/cjs/src/errors.d.ts.map +1 -1
- package/cjs/src/errors.js +0 -1
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +1 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +2 -4
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +2 -2
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +1 -3
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.d.ts +1 -36
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +1 -34
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/types.d.ts +41 -75
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +17 -47
- package/cjs/src/types.js.map +1 -1
- package/dist/{index-ChNydfIz.js → index-Bm2Hck8q.js} +1 -1
- package/dist/src/embed/app.d.ts +0 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +1 -1
- package/dist/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/dist/src/errors.d.ts +0 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +2 -2
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +1 -36
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +41 -75
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +59 -199
- package/dist/tsembed-react.js +47 -189
- package/dist/tsembed.es.js +74 -180
- package/dist/tsembed.js +30800 -30907
- package/dist/visual-embed-sdk-react-full.d.ts +44 -270
- package/dist/visual-embed-sdk-react.d.ts +44 -270
- package/dist/visual-embed-sdk.d.ts +42 -240
- package/lib/package.json +1 -1
- package/lib/src/embed/app.d.ts +0 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +1 -2
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +0 -10
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +1 -1
- package/lib/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/utils.js +7 -1
- package/lib/src/embed/hostEventClient/utils.js.map +1 -1
- package/lib/src/embed/hostEventClient/utils.spec.js +80 -5
- package/lib/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +12 -4
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +30 -69
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts +0 -1
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js +0 -1
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +1 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +1 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/react/all-types-export.d.ts +2 -2
- package/lib/src/react/all-types-export.d.ts.map +1 -1
- package/lib/src/react/all-types-export.js +1 -1
- package/lib/src/react/all-types-export.js.map +1 -1
- package/lib/src/react/index.d.ts +1 -36
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +0 -33
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/types.d.ts +41 -75
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +17 -47
- package/lib/src/types.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +42 -240
- package/package.json +1 -1
- package/src/embed/app.spec.ts +0 -15
- package/src/embed/app.ts +2 -20
- package/src/embed/conversation.ts +4 -4
- package/src/embed/hostEventClient/utils.spec.ts +94 -6
- package/src/embed/hostEventClient/utils.ts +15 -2
- package/src/embed/ts-embed.spec.ts +56 -108
- package/src/embed/ts-embed.ts +10 -3
- package/src/errors.ts +0 -1
- package/src/index.ts +2 -5
- package/src/react/all-types-export.ts +0 -3
- package/src/react/index.tsx +15 -59
- package/src/types.ts +102 -138
- package/cjs/src/embed/sage.d.ts +0 -164
- package/cjs/src/embed/sage.d.ts.map +0 -1
- package/cjs/src/embed/sage.js +0 -88
- package/cjs/src/embed/sage.js.map +0 -1
- package/cjs/src/embed/sage.spec.d.ts +0 -2
- package/cjs/src/embed/sage.spec.d.ts.map +0 -1
- package/cjs/src/embed/sage.spec.js +0 -151
- package/cjs/src/embed/sage.spec.js.map +0 -1
- package/dist/index-DGV_zh53.js +0 -7371
- package/dist/index-DW2wEHqy.js +0 -7371
- package/dist/src/embed/sage.d.ts +0 -164
- package/dist/src/embed/sage.d.ts.map +0 -1
- package/dist/src/embed/sage.spec.d.ts +0 -2
- package/dist/src/embed/sage.spec.d.ts.map +0 -1
- package/lib/src/embed/sage.d.ts +0 -164
- package/lib/src/embed/sage.d.ts.map +0 -1
- package/lib/src/embed/sage.js +0 -84
- package/lib/src/embed/sage.js.map +0 -1
- package/lib/src/embed/sage.spec.d.ts +0 -2
- package/lib/src/embed/sage.spec.d.ts.map +0 -1
- package/lib/src/embed/sage.spec.js +0 -148
- package/lib/src/embed/sage.spec.js.map +0 -1
- package/src/embed/sage.spec.ts +0 -206
- package/src/embed/sage.ts +0 -231
|
@@ -10,6 +10,10 @@ import { EmbedEvent } from '../../types';
|
|
|
10
10
|
import { embedEventStatus } from '../../utils';
|
|
11
11
|
|
|
12
12
|
describe('hostEventClient utils', () => {
|
|
13
|
+
|
|
14
|
+
// =========================
|
|
15
|
+
// UpdateFilters Validation
|
|
16
|
+
// =========================
|
|
13
17
|
describe('isValidUpdateFiltersPayload', () => {
|
|
14
18
|
it('returns false for undefined', () => {
|
|
15
19
|
expect(isValidUpdateFiltersPayload(undefined)).toBe(false);
|
|
@@ -19,12 +23,24 @@ describe('hostEventClient utils', () => {
|
|
|
19
23
|
expect(isValidUpdateFiltersPayload({})).toBe(false);
|
|
20
24
|
});
|
|
21
25
|
|
|
22
|
-
it('returns true for valid filter', () => {
|
|
26
|
+
it('returns true for valid filter with column', () => {
|
|
23
27
|
expect(isValidUpdateFiltersPayload({
|
|
24
28
|
filter: { column: 'region', oper: 'EQ', values: ['North'] },
|
|
25
29
|
} as any)).toBe(true);
|
|
26
30
|
});
|
|
27
31
|
|
|
32
|
+
it('returns true for valid filter with columnName', () => {
|
|
33
|
+
expect(isValidUpdateFiltersPayload({
|
|
34
|
+
filter: { columnName: 'region', oper: 'EQ', values: ['North'] },
|
|
35
|
+
} as any)).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('returns true for filter with operator instead of oper', () => {
|
|
39
|
+
expect(isValidUpdateFiltersPayload({
|
|
40
|
+
filter: { column: 'region', operator: 'EQ', values: ['North'] },
|
|
41
|
+
} as any)).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
28
44
|
it('returns true for valid filters array', () => {
|
|
29
45
|
expect(isValidUpdateFiltersPayload({
|
|
30
46
|
filters: [
|
|
@@ -34,13 +50,31 @@ describe('hostEventClient utils', () => {
|
|
|
34
50
|
} as any)).toBe(true);
|
|
35
51
|
});
|
|
36
52
|
|
|
37
|
-
it('returns
|
|
53
|
+
it('returns true for valid filters array with columnName', () => {
|
|
54
|
+
expect(isValidUpdateFiltersPayload({
|
|
55
|
+
filters: [
|
|
56
|
+
{ columnName: 'x', oper: 'IN', values: ['a', 'b'] },
|
|
57
|
+
{ columnName: 'y', oper: 'EQ', values: ['c'] },
|
|
58
|
+
],
|
|
59
|
+
} as any)).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns false if one filter in filters array is invalid', () => {
|
|
63
|
+
expect(isValidUpdateFiltersPayload({
|
|
64
|
+
filters: [
|
|
65
|
+
{ column: 'x', oper: 'EQ', values: ['a'] },
|
|
66
|
+
{ column: 'y', values: ['b'] }, // invalid
|
|
67
|
+
],
|
|
68
|
+
} as any)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('returns false for filter with missing column/columnName', () => {
|
|
38
72
|
expect(isValidUpdateFiltersPayload({
|
|
39
73
|
filter: { oper: 'EQ', values: ['a'] },
|
|
40
74
|
} as any)).toBe(false);
|
|
41
75
|
});
|
|
42
76
|
|
|
43
|
-
it('returns false for filter with missing
|
|
77
|
+
it('returns false for filter with missing operator', () => {
|
|
44
78
|
expect(isValidUpdateFiltersPayload({
|
|
45
79
|
filter: { column: 'x', values: ['a'] },
|
|
46
80
|
} as any)).toBe(false);
|
|
@@ -52,11 +86,39 @@ describe('hostEventClient utils', () => {
|
|
|
52
86
|
} as any)).toBe(false);
|
|
53
87
|
});
|
|
54
88
|
|
|
89
|
+
it('returns false for filter with non-string type', () => {
|
|
90
|
+
expect(isValidUpdateFiltersPayload({
|
|
91
|
+
filter: { column: 'x', oper: 'EQ', values: ['a'], type: 123 },
|
|
92
|
+
} as any)).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('returns true for filter with valid string type', () => {
|
|
96
|
+
expect(isValidUpdateFiltersPayload({
|
|
97
|
+
filter: { column: 'x', oper: 'EQ', values: ['a'], type: 'STRING' },
|
|
98
|
+
} as any)).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
55
101
|
it('returns false for empty filters array', () => {
|
|
56
102
|
expect(isValidUpdateFiltersPayload({ filters: [] } as any)).toBe(false);
|
|
57
103
|
});
|
|
104
|
+
|
|
105
|
+
it('returns false if filters is not an array', () => {
|
|
106
|
+
expect(isValidUpdateFiltersPayload({
|
|
107
|
+
filters: 'invalid',
|
|
108
|
+
} as any)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('returns true if filter is valid even when filters is invalid', () => {
|
|
112
|
+
expect(isValidUpdateFiltersPayload({
|
|
113
|
+
filter: { column: 'x', oper: 'EQ', values: ['a'] },
|
|
114
|
+
filters: [{ column: 'y' }], // invalid
|
|
115
|
+
} as any)).toBe(true);
|
|
116
|
+
});
|
|
58
117
|
});
|
|
59
118
|
|
|
119
|
+
// =========================
|
|
120
|
+
// DrillDown Validation
|
|
121
|
+
// =========================
|
|
60
122
|
describe('isValidDrillDownPayload', () => {
|
|
61
123
|
it('returns false for undefined', () => {
|
|
62
124
|
expect(isValidDrillDownPayload(undefined)).toBe(false);
|
|
@@ -66,7 +128,7 @@ describe('hostEventClient utils', () => {
|
|
|
66
128
|
expect(isValidDrillDownPayload({})).toBe(false);
|
|
67
129
|
});
|
|
68
130
|
|
|
69
|
-
it('returns false for empty points', () => {
|
|
131
|
+
it('returns false for empty points object', () => {
|
|
70
132
|
expect(isValidDrillDownPayload({ points: {} } as any)).toBe(false);
|
|
71
133
|
});
|
|
72
134
|
|
|
@@ -97,16 +159,42 @@ describe('hostEventClient utils', () => {
|
|
|
97
159
|
points: { selectedPoints: [] },
|
|
98
160
|
} as any)).toBe(false);
|
|
99
161
|
});
|
|
162
|
+
|
|
163
|
+
it('returns false if clickedPoint is null', () => {
|
|
164
|
+
expect(isValidDrillDownPayload({
|
|
165
|
+
points: { clickedPoint: null },
|
|
166
|
+
} as any)).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('returns false if selectedPoints is not an array', () => {
|
|
170
|
+
expect(isValidDrillDownPayload({
|
|
171
|
+
points: { selectedPoints: 'invalid' },
|
|
172
|
+
} as any)).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('returns false if both clickedPoint and selectedPoints are invalid', () => {
|
|
176
|
+
expect(isValidDrillDownPayload({
|
|
177
|
+
points: { clickedPoint: null, selectedPoints: [] },
|
|
178
|
+
} as any)).toBe(false);
|
|
179
|
+
});
|
|
100
180
|
});
|
|
101
181
|
|
|
182
|
+
// =========================
|
|
183
|
+
// Error Handling
|
|
184
|
+
// =========================
|
|
102
185
|
describe('createValidationError', () => {
|
|
103
|
-
it('throws with message
|
|
186
|
+
it('throws with message', () => {
|
|
104
187
|
expect(() => createValidationError('test error')).toThrow('test error');
|
|
188
|
+
});
|
|
105
189
|
|
|
190
|
+
it('throws Error instance with metadata', () => {
|
|
106
191
|
try {
|
|
107
192
|
createValidationError('custom msg');
|
|
108
193
|
} catch (err: any) {
|
|
194
|
+
expect(err).toBeInstanceOf(Error);
|
|
109
195
|
expect(err.isValidationError).toBe(true);
|
|
196
|
+
expect(err.embedErrorDetails).toBeDefined();
|
|
197
|
+
|
|
110
198
|
expect(err.embedErrorDetails).toMatchObject({
|
|
111
199
|
type: EmbedEvent.Error,
|
|
112
200
|
data: {
|
|
@@ -134,4 +222,4 @@ describe('hostEventClient utils', () => {
|
|
|
134
222
|
.toThrow(ERROR_MESSAGE.DRILLDOWN_INVALID_PAYLOAD);
|
|
135
223
|
});
|
|
136
224
|
});
|
|
137
|
-
});
|
|
225
|
+
});
|
|
@@ -8,8 +8,21 @@ export function isValidUpdateFiltersPayload(
|
|
|
8
8
|
): boolean {
|
|
9
9
|
if (!payload) return false;
|
|
10
10
|
|
|
11
|
-
const isValidFilter = (f: {
|
|
12
|
-
|
|
11
|
+
const isValidFilter = (f: {
|
|
12
|
+
column?: string;
|
|
13
|
+
oper?: string;
|
|
14
|
+
values?: unknown[];
|
|
15
|
+
type?: string;
|
|
16
|
+
columnName?: string;
|
|
17
|
+
operator?: string
|
|
18
|
+
}) => {
|
|
19
|
+
const hasColumn = typeof f.column === 'string' || typeof f.columnName === 'string';
|
|
20
|
+
const hasOperator = typeof f.oper === 'string' || typeof f.operator === 'string';
|
|
21
|
+
const hasValues = Array.isArray(f.values);
|
|
22
|
+
const validType = !f.type || typeof f.type === 'string';
|
|
23
|
+
|
|
24
|
+
return hasColumn && hasOperator && hasValues && validType;
|
|
25
|
+
};
|
|
13
26
|
|
|
14
27
|
const hasValidFilter = payload.filter && isValidFilter(payload.filter);
|
|
15
28
|
const hasValidFilters = Array.isArray(payload.filters) && payload.filters.length > 0 && payload.filters.every(isValidFilter);
|
|
@@ -11,8 +11,6 @@ import {
|
|
|
11
11
|
AppEmbed,
|
|
12
12
|
LiveboardEmbed,
|
|
13
13
|
AppViewConfig,
|
|
14
|
-
SageEmbed,
|
|
15
|
-
SageViewConfig,
|
|
16
14
|
SearchViewConfig,
|
|
17
15
|
AnswerService,
|
|
18
16
|
SpotterEmbed,
|
|
@@ -2192,28 +2190,6 @@ describe('Unit test case for ts embed', () => {
|
|
|
2192
2190
|
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}#/embed/viz/${liveboardId}`,
|
|
2193
2191
|
);
|
|
2194
2192
|
});
|
|
2195
|
-
|
|
2196
|
-
const defaultConfig: SageViewConfig = {
|
|
2197
|
-
disableWorksheetChange: false,
|
|
2198
|
-
hideWorksheetSelector: false,
|
|
2199
|
-
hideSageAnswerHeader: false,
|
|
2200
|
-
hideAutocompleteSuggestions: false,
|
|
2201
|
-
hideSampleQuestions: false,
|
|
2202
|
-
isProductTour: false,
|
|
2203
|
-
dataPanelV2: false,
|
|
2204
|
-
};
|
|
2205
|
-
|
|
2206
|
-
const sageEmbed = new SageEmbed(getRootEl(), {
|
|
2207
|
-
...defaultConfig,
|
|
2208
|
-
} as SageViewConfig);
|
|
2209
|
-
|
|
2210
|
-
sageEmbed.render();
|
|
2211
|
-
await executeAfterWait(() => {
|
|
2212
|
-
expectUrlMatch(
|
|
2213
|
-
getIFrameSrc(),
|
|
2214
|
-
`http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
|
|
2215
|
-
);
|
|
2216
|
-
});
|
|
2217
2193
|
});
|
|
2218
2194
|
|
|
2219
2195
|
it('Should add contextMenuEnabledOnWhichClick flag to the iframe with left value', async () => {
|
|
@@ -2230,29 +2206,6 @@ describe('Unit test case for ts embed', () => {
|
|
|
2230
2206
|
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&contextMenuEnabledOnWhichClick=left#/embed/viz/${liveboardId}`,
|
|
2231
2207
|
);
|
|
2232
2208
|
});
|
|
2233
|
-
|
|
2234
|
-
const defaultConfig: SageViewConfig = {
|
|
2235
|
-
disableWorksheetChange: false,
|
|
2236
|
-
hideWorksheetSelector: false,
|
|
2237
|
-
hideSageAnswerHeader: false,
|
|
2238
|
-
hideAutocompleteSuggestions: false,
|
|
2239
|
-
hideSampleQuestions: false,
|
|
2240
|
-
isProductTour: false,
|
|
2241
|
-
dataPanelV2: false,
|
|
2242
|
-
};
|
|
2243
|
-
|
|
2244
|
-
const sageEmbed = new SageEmbed(getRootEl(), {
|
|
2245
|
-
...defaultConfig,
|
|
2246
|
-
contextMenuTrigger: ContextMenuTriggerOptions.LEFT_CLICK,
|
|
2247
|
-
} as SageViewConfig);
|
|
2248
|
-
|
|
2249
|
-
sageEmbed.render();
|
|
2250
|
-
await executeAfterWait(() => {
|
|
2251
|
-
expectUrlMatch(
|
|
2252
|
-
getIFrameSrc(),
|
|
2253
|
-
`http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&contextMenuEnabledOnWhichClick=left&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
|
|
2254
|
-
);
|
|
2255
|
-
});
|
|
2256
2209
|
});
|
|
2257
2210
|
|
|
2258
2211
|
it('Should add contextMenuEnabledOnWhichClick flag to the iframe with right value', async () => {
|
|
@@ -2269,28 +2222,6 @@ describe('Unit test case for ts embed', () => {
|
|
|
2269
2222
|
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&contextMenuEnabledOnWhichClick=right#/embed/viz/${liveboardId}`,
|
|
2270
2223
|
);
|
|
2271
2224
|
});
|
|
2272
|
-
const defaultConfig: SageViewConfig = {
|
|
2273
|
-
disableWorksheetChange: false,
|
|
2274
|
-
hideWorksheetSelector: false,
|
|
2275
|
-
hideSageAnswerHeader: false,
|
|
2276
|
-
hideAutocompleteSuggestions: false,
|
|
2277
|
-
hideSampleQuestions: false,
|
|
2278
|
-
isProductTour: false,
|
|
2279
|
-
dataPanelV2: false,
|
|
2280
|
-
};
|
|
2281
|
-
|
|
2282
|
-
const sageEmbed = new SageEmbed(getRootEl(), {
|
|
2283
|
-
...defaultConfig,
|
|
2284
|
-
contextMenuTrigger: ContextMenuTriggerOptions.RIGHT_CLICK,
|
|
2285
|
-
} as SageViewConfig);
|
|
2286
|
-
|
|
2287
|
-
sageEmbed.render();
|
|
2288
|
-
await executeAfterWait(() => {
|
|
2289
|
-
expectUrlMatch(
|
|
2290
|
-
getIFrameSrc(),
|
|
2291
|
-
`http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&contextMenuEnabledOnWhichClick=right&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
|
|
2292
|
-
);
|
|
2293
|
-
});
|
|
2294
2225
|
});
|
|
2295
2226
|
|
|
2296
2227
|
it('Should add contextMenuEnabledOnWhichClick flag to the iframe with both value', async () => {
|
|
@@ -2307,28 +2238,6 @@ describe('Unit test case for ts embed', () => {
|
|
|
2307
2238
|
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&contextMenuEnabledOnWhichClick=both#/embed/viz/${liveboardId}`,
|
|
2308
2239
|
);
|
|
2309
2240
|
});
|
|
2310
|
-
const defaultConfig: SageViewConfig = {
|
|
2311
|
-
disableWorksheetChange: false,
|
|
2312
|
-
hideWorksheetSelector: false,
|
|
2313
|
-
hideSageAnswerHeader: false,
|
|
2314
|
-
hideAutocompleteSuggestions: false,
|
|
2315
|
-
hideSampleQuestions: false,
|
|
2316
|
-
isProductTour: false,
|
|
2317
|
-
dataPanelV2: false,
|
|
2318
|
-
};
|
|
2319
|
-
|
|
2320
|
-
const sageEmbed = new SageEmbed(getRootEl(), {
|
|
2321
|
-
...defaultConfig,
|
|
2322
|
-
contextMenuTrigger: ContextMenuTriggerOptions.BOTH_CLICKS,
|
|
2323
|
-
} as SageViewConfig);
|
|
2324
|
-
|
|
2325
|
-
sageEmbed.render();
|
|
2326
|
-
await executeAfterWait(() => {
|
|
2327
|
-
expectUrlMatch(
|
|
2328
|
-
getIFrameSrc(),
|
|
2329
|
-
`http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&contextMenuEnabledOnWhichClick=both&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
|
|
2330
|
-
);
|
|
2331
|
-
});
|
|
2332
2241
|
});
|
|
2333
2242
|
});
|
|
2334
2243
|
|
|
@@ -3558,6 +3467,45 @@ describe('Unit test case for ts embed', () => {
|
|
|
3558
3467
|
expect(getRootEl().nextElementSibling.innerHTML).toBe('');
|
|
3559
3468
|
});
|
|
3560
3469
|
|
|
3470
|
+
it('should not call trigger or remove DOM if destroy is called before render', () => {
|
|
3471
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3472
|
+
frameParams: { width: '100%', height: '100%' },
|
|
3473
|
+
});
|
|
3474
|
+
|
|
3475
|
+
const triggerSpy = jest.spyOn(appEmbed, 'trigger');
|
|
3476
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild');
|
|
3477
|
+
|
|
3478
|
+
appEmbed.destroy();
|
|
3479
|
+
|
|
3480
|
+
expect(triggerSpy).not.toHaveBeenCalled();
|
|
3481
|
+
expect(removeChildSpy).not.toHaveBeenCalled();
|
|
3482
|
+
});
|
|
3483
|
+
|
|
3484
|
+
it('should still remove DOM element when trigger rejects (waitForCleanupOnDestroy: true)', async () => {
|
|
3485
|
+
const originalEmbedConfig = embedConfig.getEmbedConfig();
|
|
3486
|
+
embedConfig.setEmbedConfig({
|
|
3487
|
+
...originalEmbedConfig,
|
|
3488
|
+
waitForCleanupOnDestroy: true,
|
|
3489
|
+
cleanupTimeout: 1000,
|
|
3490
|
+
});
|
|
3491
|
+
|
|
3492
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3493
|
+
frameParams: { width: '100%', height: '100%' },
|
|
3494
|
+
});
|
|
3495
|
+
await appEmbed.render();
|
|
3496
|
+
|
|
3497
|
+
jest.spyOn(appEmbed, 'trigger').mockRejectedValue(new Error('trigger failed'));
|
|
3498
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
|
|
3499
|
+
|
|
3500
|
+
appEmbed.destroy();
|
|
3501
|
+
|
|
3502
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
3503
|
+
|
|
3504
|
+
expect(removeChildSpy).toHaveBeenCalled();
|
|
3505
|
+
|
|
3506
|
+
embedConfig.setEmbedConfig(originalEmbedConfig);
|
|
3507
|
+
});
|
|
3508
|
+
|
|
3561
3509
|
describe('with waitForCleanupOnDestroy configuration', () => {
|
|
3562
3510
|
let originalEmbedConfig: any;
|
|
3563
3511
|
|
|
@@ -4220,9 +4168,9 @@ describe('PreRender replaceExistingPreRender scenarios', () => {
|
|
|
4220
4168
|
preRenderId: 'no-replace-test',
|
|
4221
4169
|
liveboardId: 'lb2',
|
|
4222
4170
|
});
|
|
4223
|
-
|
|
4171
|
+
|
|
4224
4172
|
const result = await embed2.preRender(false, false);
|
|
4225
|
-
|
|
4173
|
+
|
|
4226
4174
|
expect(result).toBe(embed2);
|
|
4227
4175
|
// The original iframe should still have lb1
|
|
4228
4176
|
const iframe = getIFrameEl();
|
|
@@ -4247,17 +4195,17 @@ describe('Destroy error handling', () => {
|
|
|
4247
4195
|
frameParams: { width: '100%', height: '100%' },
|
|
4248
4196
|
});
|
|
4249
4197
|
await appEmbed.render();
|
|
4250
|
-
|
|
4198
|
+
|
|
4251
4199
|
const logSpy = jest.spyOn(logger, 'log').mockImplementation(() => {});
|
|
4252
|
-
|
|
4200
|
+
|
|
4253
4201
|
jest.spyOn(Node.prototype, 'removeChild').mockImplementationOnce(() => {
|
|
4254
4202
|
throw new Error('Remove failed');
|
|
4255
4203
|
});
|
|
4256
|
-
|
|
4204
|
+
|
|
4257
4205
|
expect(() => {
|
|
4258
4206
|
appEmbed.destroy();
|
|
4259
4207
|
}).not.toThrow();
|
|
4260
|
-
|
|
4208
|
+
|
|
4261
4209
|
expect(logSpy).toHaveBeenCalledWith('Error destroying TS Embed', expect.any(Error));
|
|
4262
4210
|
logSpy.mockReset();
|
|
4263
4211
|
});
|
|
@@ -4282,25 +4230,25 @@ describe('Fullscreen change handler behavior', () => {
|
|
|
4282
4230
|
liveboardId: 'test-lb',
|
|
4283
4231
|
});
|
|
4284
4232
|
await liveboardEmbed.render();
|
|
4285
|
-
|
|
4233
|
+
|
|
4286
4234
|
await executeAfterWait(() => {
|
|
4287
4235
|
const iframe = getIFrameEl();
|
|
4288
4236
|
expect(iframe).toBeTruthy();
|
|
4289
4237
|
});
|
|
4290
4238
|
|
|
4291
4239
|
mockProcessTrigger.mockResolvedValue({});
|
|
4292
|
-
|
|
4240
|
+
|
|
4293
4241
|
liveboardEmbed['setupFullscreenChangeHandler']();
|
|
4294
|
-
|
|
4242
|
+
|
|
4295
4243
|
Object.defineProperty(document, 'fullscreenElement', {
|
|
4296
4244
|
value: null,
|
|
4297
4245
|
writable: true,
|
|
4298
4246
|
configurable: true,
|
|
4299
4247
|
});
|
|
4300
|
-
|
|
4248
|
+
|
|
4301
4249
|
const event = new Event('fullscreenchange');
|
|
4302
4250
|
document.dispatchEvent(event);
|
|
4303
|
-
|
|
4251
|
+
|
|
4304
4252
|
await executeAfterWait(() => {
|
|
4305
4253
|
expect(mockProcessTrigger).toHaveBeenLastCalledWith(
|
|
4306
4254
|
expect.any(Object),
|
|
@@ -4318,7 +4266,7 @@ describe('Fullscreen change handler behavior', () => {
|
|
|
4318
4266
|
liveboardId: 'test-lb-fullscreen',
|
|
4319
4267
|
});
|
|
4320
4268
|
await liveboardEmbed.render();
|
|
4321
|
-
|
|
4269
|
+
|
|
4322
4270
|
await executeAfterWait(() => {
|
|
4323
4271
|
const iframe = getIFrameEl();
|
|
4324
4272
|
expect(iframe).toBeTruthy();
|
|
@@ -4326,18 +4274,18 @@ describe('Fullscreen change handler behavior', () => {
|
|
|
4326
4274
|
|
|
4327
4275
|
mockProcessTrigger.mockClear();
|
|
4328
4276
|
mockProcessTrigger.mockResolvedValue({});
|
|
4329
|
-
|
|
4277
|
+
|
|
4330
4278
|
liveboardEmbed['setupFullscreenChangeHandler']();
|
|
4331
|
-
|
|
4279
|
+
|
|
4332
4280
|
Object.defineProperty(document, 'fullscreenElement', {
|
|
4333
4281
|
value: getIFrameEl(),
|
|
4334
4282
|
writable: true,
|
|
4335
4283
|
configurable: true,
|
|
4336
4284
|
});
|
|
4337
|
-
|
|
4285
|
+
|
|
4338
4286
|
const event = new Event('fullscreenchange');
|
|
4339
4287
|
document.dispatchEvent(event);
|
|
4340
|
-
|
|
4288
|
+
|
|
4341
4289
|
await executeAfterWait(() => {
|
|
4342
4290
|
expect(mockProcessTrigger).not.toHaveBeenCalledWith(
|
|
4343
4291
|
expect.any(Object),
|
|
@@ -4365,7 +4313,7 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
|
|
|
4365
4313
|
preRenderId,
|
|
4366
4314
|
...initialConfig,
|
|
4367
4315
|
});
|
|
4368
|
-
|
|
4316
|
+
|
|
4369
4317
|
await embed1.preRender();
|
|
4370
4318
|
await waitFor(() => !!getIFrameEl());
|
|
4371
4319
|
|
package/src/embed/ts-embed.ts
CHANGED
|
@@ -1602,6 +1602,9 @@ export class TsEmbed {
|
|
|
1602
1602
|
try {
|
|
1603
1603
|
this.removeFullscreenChangeHandler();
|
|
1604
1604
|
this.unsubscribeToEvents();
|
|
1605
|
+
if (!this.isRendered) {
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1605
1608
|
if (!getEmbedConfig().waitForCleanupOnDestroy) {
|
|
1606
1609
|
this.trigger(HostEvent.DestroyEmbed)
|
|
1607
1610
|
this.insertedDomEl?.parentNode?.removeChild(this.insertedDomEl);
|
|
@@ -1610,10 +1613,14 @@ export class TsEmbed {
|
|
|
1610
1613
|
Promise.race([
|
|
1611
1614
|
this.trigger(HostEvent.DestroyEmbed),
|
|
1612
1615
|
new Promise((resolve) => setTimeout(resolve, cleanupTimeout)),
|
|
1613
|
-
]).
|
|
1614
|
-
this.insertedDomEl?.parentNode?.removeChild(this.insertedDomEl);
|
|
1615
|
-
}).catch((e) => {
|
|
1616
|
+
]).catch((e) => {
|
|
1616
1617
|
logger.log('Error destroying TS Embed', e);
|
|
1618
|
+
}).finally(() => {
|
|
1619
|
+
try {
|
|
1620
|
+
this.insertedDomEl?.parentNode?.removeChild(this.insertedDomEl);
|
|
1621
|
+
} catch (e) {
|
|
1622
|
+
logger.log('Error removing DOM element on destroy', e);
|
|
1623
|
+
}
|
|
1617
1624
|
});
|
|
1618
1625
|
}
|
|
1619
1626
|
} catch (e) {
|
package/src/errors.ts
CHANGED
|
@@ -4,7 +4,6 @@ export const ERROR_MESSAGE = {
|
|
|
4
4
|
LIVEBOARD_VIZ_ID_VALIDATION: 'Please select a Liveboard to embed.',
|
|
5
5
|
TRIGGER_TIMED_OUT: 'Trigger timed-out in getting a response',
|
|
6
6
|
SEARCHEMBED_BETA_WRANING_MESSAGE: 'SearchEmbed is in Beta in this release.',
|
|
7
|
-
SAGE_EMBED_BETA_WARNING_MESSAGE: 'SageEmbed is in Beta in this release.',
|
|
8
7
|
THIRD_PARTY_COOKIE_BLOCKED_ALERT: '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.',
|
|
9
8
|
DUPLICATE_TOKEN_ERR: 'Duplicate token. Please issue a new token every time getAuthToken callback is called. See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.',
|
|
10
9
|
SDK_NOT_INITIALIZED: 'SDK not initialized',
|
package/src/index.ts
CHANGED
|
@@ -67,13 +67,12 @@ import {
|
|
|
67
67
|
CustomActionTarget,
|
|
68
68
|
InterceptedApiType,
|
|
69
69
|
EmbedErrorCodes,
|
|
70
|
-
EmbedErrorDetailsEvent,
|
|
70
|
+
EmbedErrorDetailsEvent,
|
|
71
71
|
ErrorDetailsTypes,
|
|
72
72
|
ContextType,
|
|
73
73
|
AutoMCPFrameRendererViewConfig,
|
|
74
74
|
} from './types';
|
|
75
75
|
import { CustomCssVariables } from './css-variables';
|
|
76
|
-
import { SageEmbed, SageViewConfig } from './embed/sage';
|
|
77
76
|
import { AnswerService, SessionInterface, UnderlyingDataPoint } from './utils/graphql/answerService/answerService';
|
|
78
77
|
import { getEmbedConfig } from './embed/embedConfig';
|
|
79
78
|
import { uploadMixpanelEvent, MIXPANEL_EVENT } from './mixpanel-service';
|
|
@@ -100,7 +99,6 @@ export {
|
|
|
100
99
|
SearchBarEmbed,
|
|
101
100
|
PinboardEmbed,
|
|
102
101
|
LiveboardEmbed,
|
|
103
|
-
SageEmbed,
|
|
104
102
|
AppEmbed,
|
|
105
103
|
SpotterAgentEmbed,
|
|
106
104
|
SpotterAgentEmbedViewConfig,
|
|
@@ -134,7 +132,6 @@ export {
|
|
|
134
132
|
SearchViewConfig,
|
|
135
133
|
SearchBarViewConfig,
|
|
136
134
|
LiveboardViewConfig,
|
|
137
|
-
SageViewConfig,
|
|
138
135
|
AppViewConfig,
|
|
139
136
|
PrefetchFeatures,
|
|
140
137
|
FrameParams,
|
|
@@ -171,4 +168,4 @@ export {
|
|
|
171
168
|
};
|
|
172
169
|
|
|
173
170
|
export { resetCachedAuthToken } from './authToken';
|
|
174
|
-
export { startAutoMCPFrameRenderer } from './embed/auto-frame-renderer';
|
|
171
|
+
export { startAutoMCPFrameRenderer } from './embed/auto-frame-renderer';
|
|
@@ -7,8 +7,6 @@ export {
|
|
|
7
7
|
PreRenderedSearchBarEmbed,
|
|
8
8
|
AppEmbed,
|
|
9
9
|
PreRenderedAppEmbed,
|
|
10
|
-
SageEmbed,
|
|
11
|
-
PreRenderedSageEmbed,
|
|
12
10
|
SpotterEmbed,
|
|
13
11
|
ConversationEmbed,
|
|
14
12
|
PreRenderedConversationEmbed,
|
|
@@ -44,7 +42,6 @@ export {
|
|
|
44
42
|
SearchViewConfig,
|
|
45
43
|
SearchBarViewConfig,
|
|
46
44
|
LiveboardViewConfig,
|
|
47
|
-
SageViewConfig,
|
|
48
45
|
AppViewConfig,
|
|
49
46
|
PrefetchFeatures,
|
|
50
47
|
FrameParams,
|