@thoughtspot/visual-embed-sdk 1.50.0 → 1.51.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/css-variables.d.ts +95 -0
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +136 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +59 -37
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +419 -149
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +230 -1
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +30 -16
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +221 -17
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/events.spec.js +635 -0
- package/cjs/src/embed/events.spec.js.map +1 -1
- package/cjs/src/embed/host-events.spec.js +151 -0
- package/cjs/src/embed/host-events.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.js +11 -1
- package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.js +9 -0
- package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js +218 -0
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.d.ts +2 -0
- package/cjs/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.js +32 -2
- package/cjs/src/embed/hostEventClient/utils.js.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.spec.js +178 -0
- package/cjs/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +42 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +26 -6
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +83 -2
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/spotter-utils.d.ts +8 -1
- package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-utils.js +14 -1
- package/cjs/src/embed/spotter-utils.js.map +1 -1
- package/cjs/src/embed/spotter-utils.spec.js +61 -0
- package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.d.ts +34 -0
- package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.spec.js +17 -0
- package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +29 -7
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +146 -0
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.d.ts +1 -0
- package/cjs/src/errors.d.ts.map +1 -1
- package/cjs/src/errors.js +1 -0
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +2 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +3 -2
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/mixpanel-service.d.ts +4 -0
- package/cjs/src/mixpanel-service.d.ts.map +1 -1
- package/cjs/src/mixpanel-service.js +4 -0
- package/cjs/src/mixpanel-service.js.map +1 -1
- package/cjs/src/react/util.spec.js +251 -0
- package/cjs/src/react/util.spec.js.map +1 -1
- package/cjs/src/types.d.ts +573 -11
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +519 -2
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/processData.spec.js +93 -0
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/cjs/src/utils/processTrigger.spec.js +61 -0
- package/cjs/src/utils/processTrigger.spec.js.map +1 -1
- package/dist/{index-B5xoN6Cp.js → index-aBzH5ZwF.js} +1 -1
- package/dist/src/css-variables.d.ts +95 -0
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +136 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +230 -1
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/utils.d.ts +2 -0
- package/dist/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +42 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/spotter-utils.d.ts +8 -1
- package/dist/src/embed/spotter-utils.d.ts.map +1 -1
- package/dist/src/embed/spotter-viz-utils.d.ts +34 -0
- package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/mixpanel-service.d.ts +4 -0
- package/dist/src/mixpanel-service.d.ts.map +1 -1
- package/dist/src/types.d.ts +573 -11
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +936 -142
- package/dist/tsembed-react.js +935 -141
- package/dist/tsembed.es.js +935 -142
- package/dist/tsembed.js +933 -140
- package/dist/visual-embed-sdk-react-full.d.ts +1147 -44
- package/dist/visual-embed-sdk-react.d.ts +1153 -46
- package/dist/visual-embed-sdk.d.ts +1161 -46
- package/lib/package.json +1 -1
- package/lib/src/css-variables.d.ts +95 -0
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +136 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +60 -38
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +420 -150
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +230 -1
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +31 -17
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +222 -18
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/events.spec.js +635 -0
- package/lib/src/embed/events.spec.js.map +1 -1
- package/lib/src/embed/host-events.spec.js +152 -1
- package/lib/src/embed/host-events.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.js +10 -0
- package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.js +10 -1
- package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.spec.js +218 -0
- package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/utils.d.ts +2 -0
- package/lib/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/utils.js +28 -1
- package/lib/src/embed/hostEventClient/utils.js.map +1 -1
- package/lib/src/embed/hostEventClient/utils.spec.js +179 -1
- package/lib/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +42 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +26 -6
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +83 -2
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/spotter-utils.d.ts +8 -1
- package/lib/src/embed/spotter-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-utils.js +12 -0
- package/lib/src/embed/spotter-utils.js.map +1 -1
- package/lib/src/embed/spotter-utils.spec.js +62 -1
- package/lib/src/embed/spotter-utils.spec.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.d.ts +34 -0
- package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-viz-utils.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.spec.js +17 -0
- package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +29 -7
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +146 -0
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts +1 -0
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js +1 -0
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +2 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/mixpanel-service.d.ts +4 -0
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +4 -0
- package/lib/src/mixpanel-service.js.map +1 -1
- package/lib/src/react/util.spec.js +251 -0
- package/lib/src/react/util.spec.js.map +1 -1
- package/lib/src/types.d.ts +573 -11
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +519 -2
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/processData.spec.js +93 -0
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/utils/processTrigger.spec.js +61 -0
- package/lib/src/utils/processTrigger.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +1161 -46
- package/package.json +1 -1
- package/src/css-variables.ts +118 -0
- package/src/embed/app.spec.ts +530 -183
- package/src/embed/app.ts +209 -66
- package/src/embed/conversation.spec.ts +275 -21
- package/src/embed/conversation.ts +262 -17
- package/src/embed/events.spec.ts +757 -1
- package/src/embed/host-events.spec.ts +194 -0
- package/src/embed/hostEventClient/contracts.ts +57 -14
- package/src/embed/hostEventClient/host-event-client.spec.ts +338 -0
- package/src/embed/hostEventClient/host-event-client.ts +16 -0
- package/src/embed/hostEventClient/utils.spec.ts +204 -0
- package/src/embed/hostEventClient/utils.ts +37 -10
- package/src/embed/liveboard.spec.ts +108 -2
- package/src/embed/liveboard.ts +82 -14
- package/src/embed/spotter-utils.spec.ts +68 -1
- package/src/embed/spotter-utils.ts +16 -1
- package/src/embed/spotter-viz-utils.spec.ts +17 -0
- package/src/embed/spotter-viz-utils.ts +34 -0
- package/src/embed/ts-embed.spec.ts +186 -0
- package/src/embed/ts-embed.ts +30 -4
- package/src/errors.ts +1 -0
- package/src/index.ts +3 -1
- package/src/mixpanel-service.ts +4 -0
- package/src/react/util.spec.tsx +255 -0
- package/src/types.ts +575 -8
- package/src/utils/processData.spec.ts +97 -0
- package/src/utils/processTrigger.spec.ts +91 -0
|
@@ -3,8 +3,10 @@ import { processTrigger as processTriggerService } from '../../utils/processTrig
|
|
|
3
3
|
import { getEmbedConfig } from '../embedConfig';
|
|
4
4
|
import {
|
|
5
5
|
isValidUpdateFiltersPayload,
|
|
6
|
+
isValidUpdateParametersPayload,
|
|
6
7
|
isValidDrillDownPayload,
|
|
7
8
|
throwUpdateFiltersValidationError,
|
|
9
|
+
throwUpdateParametersValidationError,
|
|
8
10
|
throwDrillDownValidationError,
|
|
9
11
|
} from './utils';
|
|
10
12
|
import {
|
|
@@ -36,6 +38,7 @@ const PASSTHROUGH_MAP: Partial<Record<HostEvent, UIPassthroughEvent>> = {
|
|
|
36
38
|
[HostEvent.GetParameters]: UIPassthroughEvent.GetParameters,
|
|
37
39
|
[HostEvent.GetTML]: UIPassthroughEvent.GetTML,
|
|
38
40
|
[HostEvent.GetTabs]: UIPassthroughEvent.GetTabs,
|
|
41
|
+
[HostEvent.GetGroups]: UIPassthroughEvent.GetGroups,
|
|
39
42
|
[HostEvent.getExportRequestForCurrentPinboard]: UIPassthroughEvent.GetExportRequestForCurrentPinboard,
|
|
40
43
|
};
|
|
41
44
|
|
|
@@ -58,6 +61,7 @@ export class HostEventClient {
|
|
|
58
61
|
[HostEvent.Pin]: (p, c) => this.handlePinEvent(p, c),
|
|
59
62
|
[HostEvent.SaveAnswer]: (p, c) => this.handleSaveAnswerEvent(p, c),
|
|
60
63
|
[HostEvent.UpdateFilters]: (p, c) => this.handleUpdateFiltersEvent(p, c),
|
|
64
|
+
[HostEvent.UpdateParameters]: (p, c) => this.handleUpdateParametersEvent(p, c),
|
|
61
65
|
[HostEvent.DrillDown]: (p, c) => this.handleDrillDownEvent(p, c),
|
|
62
66
|
};
|
|
63
67
|
}
|
|
@@ -243,6 +247,18 @@ export class HostEventClient {
|
|
|
243
247
|
return this.handleHostEventWithParam(UIPassthroughEvent.UpdateFilters, payload, context as ContextType);
|
|
244
248
|
}
|
|
245
249
|
|
|
250
|
+
protected handleUpdateParametersEvent(
|
|
251
|
+
payload: HostEventRequest<HostEvent.UpdateParameters>,
|
|
252
|
+
context?: ContextType,
|
|
253
|
+
): Promise<any> {
|
|
254
|
+
if (!isValidUpdateParametersPayload(payload)) {
|
|
255
|
+
throwUpdateParametersValidationError();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// UpdateParameters has no UI passthrough contract; dispatch over the legacy channel
|
|
259
|
+
return this.hostEventFallback(HostEvent.UpdateParameters, payload, context);
|
|
260
|
+
}
|
|
261
|
+
|
|
246
262
|
protected handleDrillDownEvent(
|
|
247
263
|
payload: HostEventRequest<HostEvent.DrillDown>,
|
|
248
264
|
context?: ContextType,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isValidUpdateFiltersPayload,
|
|
3
|
+
isValidUpdateParametersPayload,
|
|
3
4
|
isValidDrillDownPayload,
|
|
4
5
|
createValidationError,
|
|
5
6
|
throwUpdateFiltersValidationError,
|
|
7
|
+
throwUpdateParametersValidationError,
|
|
6
8
|
throwDrillDownValidationError,
|
|
7
9
|
} from './utils';
|
|
8
10
|
import { ERROR_MESSAGE } from '../../errors';
|
|
@@ -114,6 +116,201 @@ describe('hostEventClient utils', () => {
|
|
|
114
116
|
filters: [{ column: 'y' }], // invalid
|
|
115
117
|
} as any)).toBe(true);
|
|
116
118
|
});
|
|
119
|
+
|
|
120
|
+
it('returns true for filter without applicability', () => {
|
|
121
|
+
expect(isValidUpdateFiltersPayload({
|
|
122
|
+
filter: { column: 'x', oper: 'EQ', values: ['a'] },
|
|
123
|
+
} as any)).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('returns true for filter with valid applicability', () => {
|
|
127
|
+
expect(isValidUpdateFiltersPayload({
|
|
128
|
+
filter: {
|
|
129
|
+
column: 'x',
|
|
130
|
+
oper: 'EQ',
|
|
131
|
+
values: ['a'],
|
|
132
|
+
applicability: { level: 'TAB', targetId: 'tab-guid-1' },
|
|
133
|
+
},
|
|
134
|
+
} as any)).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('returns true for filters array with applicability on some filters', () => {
|
|
138
|
+
expect(isValidUpdateFiltersPayload({
|
|
139
|
+
filters: [
|
|
140
|
+
{
|
|
141
|
+
column: 'x',
|
|
142
|
+
oper: 'IN',
|
|
143
|
+
values: ['a', 'b'],
|
|
144
|
+
applicability: { level: 'TAB', targetId: 'tab-guid-1' },
|
|
145
|
+
},
|
|
146
|
+
{ column: 'y', oper: 'EQ', values: ['c'] },
|
|
147
|
+
],
|
|
148
|
+
} as any)).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('returns false for applicability missing targetId', () => {
|
|
152
|
+
expect(isValidUpdateFiltersPayload({
|
|
153
|
+
filter: {
|
|
154
|
+
column: 'x',
|
|
155
|
+
oper: 'EQ',
|
|
156
|
+
values: ['a'],
|
|
157
|
+
applicability: { level: 'TAB' },
|
|
158
|
+
},
|
|
159
|
+
} as any)).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('returns false for applicability with empty targetId', () => {
|
|
163
|
+
expect(isValidUpdateFiltersPayload({
|
|
164
|
+
filter: {
|
|
165
|
+
column: 'x',
|
|
166
|
+
oper: 'EQ',
|
|
167
|
+
values: ['a'],
|
|
168
|
+
applicability: { level: 'TAB', targetId: '' },
|
|
169
|
+
},
|
|
170
|
+
} as any)).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('returns false for null applicability', () => {
|
|
174
|
+
expect(isValidUpdateFiltersPayload({
|
|
175
|
+
filter: {
|
|
176
|
+
column: 'x',
|
|
177
|
+
oper: 'EQ',
|
|
178
|
+
values: ['a'],
|
|
179
|
+
applicability: null,
|
|
180
|
+
},
|
|
181
|
+
} as any)).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('returns false for non-object applicability', () => {
|
|
185
|
+
expect(isValidUpdateFiltersPayload({
|
|
186
|
+
filter: {
|
|
187
|
+
column: 'x',
|
|
188
|
+
oper: 'EQ',
|
|
189
|
+
values: ['a'],
|
|
190
|
+
applicability: 'TAB',
|
|
191
|
+
},
|
|
192
|
+
} as any)).toBe(false);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('returns true for LIVEBOARD level applicability without targetId', () => {
|
|
196
|
+
expect(isValidUpdateFiltersPayload({
|
|
197
|
+
filter: {
|
|
198
|
+
column: 'x',
|
|
199
|
+
oper: 'EQ',
|
|
200
|
+
values: ['a'],
|
|
201
|
+
applicability: { level: 'LIVEBOARD' },
|
|
202
|
+
},
|
|
203
|
+
} as any)).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('returns false for applicability missing level', () => {
|
|
207
|
+
expect(isValidUpdateFiltersPayload({
|
|
208
|
+
filter: {
|
|
209
|
+
column: 'x',
|
|
210
|
+
oper: 'EQ',
|
|
211
|
+
values: ['a'],
|
|
212
|
+
applicability: { targetId: 'tab-guid-1' },
|
|
213
|
+
},
|
|
214
|
+
} as any)).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('returns false for applicability with non-string level', () => {
|
|
218
|
+
expect(isValidUpdateFiltersPayload({
|
|
219
|
+
filter: {
|
|
220
|
+
column: 'x',
|
|
221
|
+
oper: 'EQ',
|
|
222
|
+
values: ['a'],
|
|
223
|
+
applicability: { level: 123, targetId: 'tab-guid-1' },
|
|
224
|
+
},
|
|
225
|
+
} as any)).toBe(false);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('returns false if one filter in filters array has invalid applicability', () => {
|
|
229
|
+
expect(isValidUpdateFiltersPayload({
|
|
230
|
+
filters: [
|
|
231
|
+
{ column: 'x', oper: 'EQ', values: ['a'] },
|
|
232
|
+
{
|
|
233
|
+
column: 'y',
|
|
234
|
+
oper: 'EQ',
|
|
235
|
+
values: ['b'],
|
|
236
|
+
applicability: { level: 'TAB' }, // missing targetId
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
} as any)).toBe(false);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// =========================
|
|
244
|
+
// UpdateParameters Validation
|
|
245
|
+
// =========================
|
|
246
|
+
describe('isValidUpdateParametersPayload', () => {
|
|
247
|
+
it('returns true for undefined payload', () => {
|
|
248
|
+
expect(isValidUpdateParametersPayload(undefined)).toBe(true);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('returns true for non-array payload', () => {
|
|
252
|
+
expect(isValidUpdateParametersPayload({ name: 'p', value: 1 })).toBe(true);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('returns true for parameters without applicability', () => {
|
|
256
|
+
expect(isValidUpdateParametersPayload([
|
|
257
|
+
{ name: 'p1', value: 1 },
|
|
258
|
+
{ name: 'p2', value: 'a' },
|
|
259
|
+
])).toBe(true);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('returns true for null applicability', () => {
|
|
263
|
+
expect(isValidUpdateParametersPayload([
|
|
264
|
+
{ name: 'p', value: 1, applicability: null },
|
|
265
|
+
])).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('returns true for valid TAB applicability with targetId', () => {
|
|
269
|
+
expect(isValidUpdateParametersPayload([
|
|
270
|
+
{ name: 'p', value: 1, applicability: { level: 'TAB', targetId: 'tab-guid-1' } },
|
|
271
|
+
])).toBe(true);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('returns true for LIVEBOARD level applicability without targetId', () => {
|
|
275
|
+
expect(isValidUpdateParametersPayload([
|
|
276
|
+
{ name: 'p', value: 1, applicability: { level: 'LIVEBOARD' } },
|
|
277
|
+
])).toBe(true);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('returns false for applicability missing targetId', () => {
|
|
281
|
+
expect(isValidUpdateParametersPayload([
|
|
282
|
+
{ name: 'p', value: 1, applicability: { level: 'TAB' } },
|
|
283
|
+
])).toBe(false);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('returns false for applicability with empty targetId', () => {
|
|
287
|
+
expect(isValidUpdateParametersPayload([
|
|
288
|
+
{ name: 'p', value: 1, applicability: { level: 'GROUP', targetId: ' ' } },
|
|
289
|
+
])).toBe(false);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('returns false for applicability with invalid level', () => {
|
|
293
|
+
expect(isValidUpdateParametersPayload([
|
|
294
|
+
{ name: 'p', value: 1, applicability: { level: 'VIZ', targetId: 'guid-1' } },
|
|
295
|
+
])).toBe(false);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('returns false for non-object applicability', () => {
|
|
299
|
+
expect(isValidUpdateParametersPayload([
|
|
300
|
+
{ name: 'p', value: 1, applicability: 'TAB' },
|
|
301
|
+
])).toBe(false);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('returns false if one parameter has invalid applicability', () => {
|
|
305
|
+
expect(isValidUpdateParametersPayload([
|
|
306
|
+
{ name: 'p1', value: 1 },
|
|
307
|
+
{ name: 'p2', value: 2, applicability: { level: 'GROUP' } }, // missing targetId
|
|
308
|
+
])).toBe(false);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('returns true for non-object entries', () => {
|
|
312
|
+
expect(isValidUpdateParametersPayload(['p', 1, null])).toBe(true);
|
|
313
|
+
});
|
|
117
314
|
});
|
|
118
315
|
|
|
119
316
|
// =========================
|
|
@@ -216,6 +413,13 @@ describe('hostEventClient utils', () => {
|
|
|
216
413
|
});
|
|
217
414
|
});
|
|
218
415
|
|
|
416
|
+
describe('throwUpdateParametersValidationError', () => {
|
|
417
|
+
it('throws with UPDATEPARAMETERS_INVALID_PAYLOAD message', () => {
|
|
418
|
+
expect(() => throwUpdateParametersValidationError())
|
|
419
|
+
.toThrow(ERROR_MESSAGE.UPDATEPARAMETERS_INVALID_PAYLOAD);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
219
423
|
describe('throwDrillDownValidationError', () => {
|
|
220
424
|
it('throws with DRILLDOWN_INVALID_PAYLOAD message', () => {
|
|
221
425
|
expect(() => throwDrillDownValidationError())
|
|
@@ -1,27 +1,40 @@
|
|
|
1
|
+
import isNil from 'lodash/isNil';
|
|
2
|
+
import isPlainObject from 'lodash/isPlainObject';
|
|
3
|
+
import isString from 'lodash/isString';
|
|
4
|
+
import isUndefined from 'lodash/isUndefined';
|
|
1
5
|
import { EmbedErrorCodes, EmbedEvent, ErrorDetailsTypes, HostEvent } from '../../types';
|
|
2
6
|
import { ERROR_MESSAGE } from '../../errors';
|
|
3
|
-
import { HostEventRequest } from './contracts';
|
|
7
|
+
import { ApplicabilityLevel, HostEventRequest } from './contracts';
|
|
4
8
|
import { embedEventStatus } from '../../utils';
|
|
5
9
|
|
|
10
|
+
const isValidApplicability = (a?: { level?: string; targetId?: string }) => {
|
|
11
|
+
if (isUndefined(a)) return true;
|
|
12
|
+
// targetId is not required at LIVEBOARD level, since the filter applies to the whole Liveboard
|
|
13
|
+
return isPlainObject(a)
|
|
14
|
+
&& Object.values(ApplicabilityLevel).includes(a.level as ApplicabilityLevel)
|
|
15
|
+
&& (a.level === ApplicabilityLevel.Liveboard || (isString(a.targetId) && a.targetId.trim().length > 0));
|
|
16
|
+
};
|
|
17
|
+
|
|
6
18
|
export function isValidUpdateFiltersPayload(
|
|
7
19
|
payload: HostEventRequest<HostEvent.UpdateFilters> | undefined,
|
|
8
20
|
): boolean {
|
|
9
21
|
if (!payload) return false;
|
|
10
22
|
|
|
11
|
-
const isValidFilter = (f: {
|
|
12
|
-
column?: string;
|
|
13
|
-
oper?: string;
|
|
14
|
-
values?: unknown[];
|
|
15
|
-
type?: string;
|
|
16
|
-
columnName?: string;
|
|
17
|
-
operator?: string
|
|
23
|
+
const isValidFilter = (f: {
|
|
24
|
+
column?: string;
|
|
25
|
+
oper?: string;
|
|
26
|
+
values?: unknown[];
|
|
27
|
+
type?: string;
|
|
28
|
+
columnName?: string;
|
|
29
|
+
operator?: string;
|
|
30
|
+
applicability?: { level?: string; targetId?: string };
|
|
18
31
|
}) => {
|
|
19
32
|
const hasColumn = typeof f.column === 'string' || typeof f.columnName === 'string';
|
|
20
33
|
const hasOperator = typeof f.oper === 'string' || typeof f.operator === 'string';
|
|
21
34
|
const hasValues = Array.isArray(f.values);
|
|
22
35
|
const validType = !f.type || typeof f.type === 'string';
|
|
23
|
-
|
|
24
|
-
return hasColumn && hasOperator && hasValues && validType;
|
|
36
|
+
|
|
37
|
+
return hasColumn && hasOperator && hasValues && validType && isValidApplicability(f.applicability);
|
|
25
38
|
};
|
|
26
39
|
|
|
27
40
|
const hasValidFilter = payload.filter && isValidFilter(payload.filter);
|
|
@@ -30,6 +43,16 @@ export function isValidUpdateFiltersPayload(
|
|
|
30
43
|
return !!(hasValidFilter || hasValidFilters);
|
|
31
44
|
}
|
|
32
45
|
|
|
46
|
+
export function isValidUpdateParametersPayload(payload: unknown): boolean {
|
|
47
|
+
// Only validates the applicability of each parameter (null treated as absent); the rest is forwarded as-is for backward compatibility.
|
|
48
|
+
if (!Array.isArray(payload)) return true;
|
|
49
|
+
return payload.every((p) => {
|
|
50
|
+
if (!isPlainObject(p)) return true;
|
|
51
|
+
const { applicability } = p as { applicability?: { level?: string; targetId?: string } };
|
|
52
|
+
return isNil(applicability) || isValidApplicability(applicability);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
33
56
|
export function isValidDrillDownPayload(
|
|
34
57
|
payload: HostEventRequest<HostEvent.DrillDown> | undefined,
|
|
35
58
|
): boolean {
|
|
@@ -72,3 +95,7 @@ export function throwUpdateFiltersValidationError(): never {
|
|
|
72
95
|
export function throwDrillDownValidationError(): never {
|
|
73
96
|
createValidationError(ERROR_MESSAGE.DRILLDOWN_INVALID_PAYLOAD);
|
|
74
97
|
}
|
|
98
|
+
|
|
99
|
+
export function throwUpdateParametersValidationError(): never {
|
|
100
|
+
createValidationError(ERROR_MESSAGE.UPDATEPARAMETERS_INVALID_PAYLOAD);
|
|
101
|
+
}
|
|
@@ -275,7 +275,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
275
275
|
});
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
test('should
|
|
278
|
+
test('should not set isWYSIWYGLiveboardPDFEnabled in url by default', async () => {
|
|
279
279
|
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
280
280
|
...defaultViewConfig,
|
|
281
281
|
liveboardId,
|
|
@@ -284,7 +284,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
284
284
|
await executeAfterWait(() => {
|
|
285
285
|
expectUrlMatchesWithParams(
|
|
286
286
|
getIFrameSrc(),
|
|
287
|
-
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}
|
|
287
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParams}#/embed/viz/${liveboardId}`,
|
|
288
288
|
);
|
|
289
289
|
});
|
|
290
290
|
});
|
|
@@ -756,6 +756,47 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
756
756
|
});
|
|
757
757
|
});
|
|
758
758
|
|
|
759
|
+
test('should add isScopedLiveboardFilteringEnabled flag and set value to true to the iframe src', async () => {
|
|
760
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
761
|
+
...defaultViewConfig,
|
|
762
|
+
liveboardId,
|
|
763
|
+
isScopedLiveboardFilteringEnabled: true,
|
|
764
|
+
} as LiveboardViewConfig);
|
|
765
|
+
liveboardEmbed.render();
|
|
766
|
+
await executeAfterWait(() => {
|
|
767
|
+
expectUrlMatchesWithParams(
|
|
768
|
+
getIFrameSrc(),
|
|
769
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&isScopedLiveboardFilteringEnabled=true${prefixParams}#/embed/viz/${liveboardId}`,
|
|
770
|
+
);
|
|
771
|
+
});
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
test('should add isScopedLiveboardFilteringEnabled flag and set value to false to the iframe src', async () => {
|
|
775
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
776
|
+
...defaultViewConfig,
|
|
777
|
+
liveboardId,
|
|
778
|
+
isScopedLiveboardFilteringEnabled: false,
|
|
779
|
+
} as LiveboardViewConfig);
|
|
780
|
+
liveboardEmbed.render();
|
|
781
|
+
await executeAfterWait(() => {
|
|
782
|
+
expectUrlMatchesWithParams(
|
|
783
|
+
getIFrameSrc(),
|
|
784
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}&isScopedLiveboardFilteringEnabled=false${prefixParams}#/embed/viz/${liveboardId}`,
|
|
785
|
+
);
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
test('should not add isScopedLiveboardFilteringEnabled flag to the iframe src when undefined', async () => {
|
|
790
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
791
|
+
...defaultViewConfig,
|
|
792
|
+
liveboardId,
|
|
793
|
+
} as LiveboardViewConfig);
|
|
794
|
+
liveboardEmbed.render();
|
|
795
|
+
await executeAfterWait(() => {
|
|
796
|
+
expect(getIFrameSrc()).not.toContain('isScopedLiveboardFilteringEnabled');
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
|
|
759
800
|
test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
|
|
760
801
|
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
761
802
|
...defaultViewConfig,
|
|
@@ -1339,6 +1380,35 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
1339
1380
|
});
|
|
1340
1381
|
});
|
|
1341
1382
|
|
|
1383
|
+
test('should render the liveboard embed with showSpotterRadiance', async () => {
|
|
1384
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
1385
|
+
...defaultViewConfig,
|
|
1386
|
+
liveboardId,
|
|
1387
|
+
showSpotterRadiance: true,
|
|
1388
|
+
} as LiveboardViewConfig);
|
|
1389
|
+
await liveboardEmbed.render();
|
|
1390
|
+
await executeAfterWait(() => {
|
|
1391
|
+
expectUrlMatchesWithParams(
|
|
1392
|
+
getIFrameSrc(),
|
|
1393
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParams}&showSpotterRadiance=true#/embed/viz/${liveboardId}`,
|
|
1394
|
+
);
|
|
1395
|
+
});
|
|
1396
|
+
});
|
|
1397
|
+
test('should render the liveboard embed with showSpotterRadiance disabled', async () => {
|
|
1398
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
1399
|
+
...defaultViewConfig,
|
|
1400
|
+
liveboardId,
|
|
1401
|
+
showSpotterRadiance: false,
|
|
1402
|
+
} as LiveboardViewConfig);
|
|
1403
|
+
await liveboardEmbed.render();
|
|
1404
|
+
await executeAfterWait(() => {
|
|
1405
|
+
expectUrlMatchesWithParams(
|
|
1406
|
+
getIFrameSrc(),
|
|
1407
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParams}&showSpotterRadiance=false#/embed/viz/${liveboardId}`,
|
|
1408
|
+
);
|
|
1409
|
+
});
|
|
1410
|
+
});
|
|
1411
|
+
|
|
1342
1412
|
test('should set hideToolResponseCardBranding parameter in url params via spotterChatConfig', async () => {
|
|
1343
1413
|
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
1344
1414
|
...defaultViewConfig,
|
|
@@ -2306,3 +2376,39 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
2306
2376
|
});
|
|
2307
2377
|
});
|
|
2308
2378
|
});
|
|
2379
|
+
|
|
2380
|
+
describe('LiveboardEmbed updatedSpotterExperience tests', () => {
|
|
2381
|
+
beforeEach(() => {
|
|
2382
|
+
document.body.innerHTML = getDocumentBody();
|
|
2383
|
+
});
|
|
2384
|
+
|
|
2385
|
+
test('should render the liveboard embed with updatedSpotterExperience', async () => {
|
|
2386
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
2387
|
+
...defaultViewConfig,
|
|
2388
|
+
liveboardId,
|
|
2389
|
+
updatedSpotterExperience: true,
|
|
2390
|
+
} as LiveboardViewConfig);
|
|
2391
|
+
await liveboardEmbed.render();
|
|
2392
|
+
await executeAfterWait(() => {
|
|
2393
|
+
expectUrlMatchesWithParams(
|
|
2394
|
+
getIFrameSrc(),
|
|
2395
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParams}&updatedSpotterExperience=true#/embed/viz/${liveboardId}`,
|
|
2396
|
+
);
|
|
2397
|
+
});
|
|
2398
|
+
});
|
|
2399
|
+
|
|
2400
|
+
test('should render the liveboard embed with updatedSpotterExperience disabled', async () => {
|
|
2401
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
2402
|
+
...defaultViewConfig,
|
|
2403
|
+
liveboardId,
|
|
2404
|
+
updatedSpotterExperience: false,
|
|
2405
|
+
} as LiveboardViewConfig);
|
|
2406
|
+
await liveboardEmbed.render();
|
|
2407
|
+
await executeAfterWait(() => {
|
|
2408
|
+
expectUrlMatchesWithParams(
|
|
2409
|
+
getIFrameSrc(),
|
|
2410
|
+
`http://${thoughtSpotHost}/?embedApp=true${defaultParams}${prefixParams}&updatedSpotterExperience=false#/embed/viz/${liveboardId}`,
|
|
2411
|
+
);
|
|
2412
|
+
});
|
|
2413
|
+
});
|
|
2414
|
+
});
|