@thoughtspot/visual-embed-sdk 1.43.0 → 1.43.1
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/api-intercept.d.ts +51 -0
- package/cjs/src/api-intercept.d.ts.map +1 -0
- package/cjs/src/api-intercept.js +180 -0
- package/cjs/src/api-intercept.js.map +1 -0
- package/cjs/src/api-intercept.spec.d.ts +2 -0
- package/cjs/src/api-intercept.spec.d.ts.map +1 -0
- package/cjs/src/api-intercept.spec.js +672 -0
- package/cjs/src/api-intercept.spec.js.map +1 -0
- package/cjs/src/css-variables.d.ts +4 -0
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +0 -5
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +4 -5
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +10 -0
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +2 -2
- package/cjs/src/embed/conversation.js +1 -1
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +17 -0
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.d.ts +11 -1
- package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.js +1 -0
- package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +4 -2
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +11 -0
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/search.d.ts +0 -7
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +1 -4
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +10 -0
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +56 -15
- 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 +412 -238
- package/cjs/src/embed/ts-embed.spec.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 +2 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +1 -1
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +2 -1
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/types.d.ts +244 -88
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +181 -70
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/logger.d.ts.map +1 -1
- package/cjs/src/utils/logger.js +1 -2
- package/cjs/src/utils/logger.js.map +1 -1
- package/cjs/src/utils/processData.d.ts +1 -1
- package/cjs/src/utils/processData.d.ts.map +1 -1
- package/cjs/src/utils/processData.js +8 -8
- package/cjs/src/utils/processData.js.map +1 -1
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/dist/{index-HZ94j9Ey.js → index-CpkMygsc.js} +1 -1
- package/dist/src/api-intercept.d.ts +51 -0
- package/dist/src/api-intercept.d.ts.map +1 -0
- package/dist/src/api-intercept.spec.d.ts +2 -0
- package/dist/src/api-intercept.spec.d.ts.map +1 -0
- package/dist/src/css-variables.d.ts +4 -0
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +0 -5
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +2 -2
- package/dist/src/embed/hostEventClient/contracts.d.ts +11 -1
- package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +0 -7
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +10 -0
- 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/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +1 -1
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/types.d.ts +244 -88
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/logger.d.ts.map +1 -1
- package/dist/src/utils/processData.d.ts +1 -1
- package/dist/src/utils/processData.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +435 -118
- package/dist/tsembed-react.js +434 -117
- package/dist/tsembed.es.js +3577 -3260
- package/dist/tsembed.js +3575 -3258
- package/dist/visual-embed-sdk-react-full.d.ts +271 -103
- package/dist/visual-embed-sdk-react.d.ts +268 -103
- package/dist/visual-embed-sdk.d.ts +271 -103
- package/lib/package.json +1 -1
- package/lib/src/api-intercept.d.ts +51 -0
- package/lib/src/api-intercept.d.ts.map +1 -0
- package/lib/src/api-intercept.js +173 -0
- package/lib/src/api-intercept.js.map +1 -0
- package/lib/src/api-intercept.spec.d.ts +2 -0
- package/lib/src/api-intercept.spec.d.ts.map +1 -0
- package/lib/src/api-intercept.spec.js +669 -0
- package/lib/src/api-intercept.spec.js.map +1 -0
- package/lib/src/css-variables.d.ts +4 -0
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +0 -5
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +4 -5
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +10 -0
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +2 -2
- package/lib/src/embed/conversation.js +1 -1
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +17 -0
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.d.ts +11 -1
- package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.js +1 -0
- package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +4 -2
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +11 -0
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/search.d.ts +0 -7
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +1 -4
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +10 -0
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +56 -15
- 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 +412 -238
- package/lib/src/embed/ts-embed.spec.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/react/all-types-export.d.ts +1 -1
- 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/types.d.ts +244 -88
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +180 -69
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/logger.d.ts.map +1 -1
- package/lib/src/utils/logger.js +1 -2
- package/lib/src/utils/logger.js.map +1 -1
- package/lib/src/utils/processData.d.ts +1 -1
- package/lib/src/utils/processData.d.ts.map +1 -1
- package/lib/src/utils/processData.js +8 -8
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/api-intercept.spec.ts +856 -0
- package/src/api-intercept.ts +204 -0
- package/src/css-variables.ts +5 -0
- package/src/embed/app.spec.ts +11 -0
- package/src/embed/app.ts +5 -16
- package/src/embed/conversation.spec.ts +22 -0
- package/src/embed/conversation.ts +3 -3
- package/src/embed/hostEventClient/contracts.ts +10 -0
- package/src/embed/liveboard.spec.ts +12 -0
- package/src/embed/liveboard.ts +6 -2
- package/src/embed/search.ts +1 -14
- package/src/embed/ts-embed.spec.ts +498 -250
- package/src/embed/ts-embed.ts +80 -32
- package/src/index.ts +2 -0
- package/src/react/all-types-export.ts +1 -0
- package/src/types.ts +327 -165
- package/src/utils/logger.ts +1 -2
- package/src/utils/processData.spec.ts +0 -1
- package/src/utils/processData.ts +10 -11
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
import * as apiIntercept from './api-intercept';
|
|
2
|
+
import * as config from './config';
|
|
3
|
+
import * as embedConfig from './embed/embedConfig';
|
|
4
|
+
import { InterceptedApiType, EmbedEvent } from './types';
|
|
5
|
+
import { embedEventStatus } from './utils';
|
|
6
|
+
import { logger } from './utils/logger';
|
|
7
|
+
jest.mock('./config');
|
|
8
|
+
jest.mock('./embed/embedConfig');
|
|
9
|
+
jest.mock('./utils/logger');
|
|
10
|
+
const mockGetThoughtSpotHost = config.getThoughtSpotHost;
|
|
11
|
+
const mockGetEmbedConfig = embedConfig.getEmbedConfig;
|
|
12
|
+
const mockLogger = logger;
|
|
13
|
+
describe('api-intercept', () => {
|
|
14
|
+
const thoughtSpotHost = 'https://test.thoughtspot.com';
|
|
15
|
+
let originalJsonParse;
|
|
16
|
+
beforeAll(() => {
|
|
17
|
+
originalJsonParse = JSON.parse;
|
|
18
|
+
});
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
mockGetThoughtSpotHost.mockReturnValue(thoughtSpotHost);
|
|
22
|
+
mockGetEmbedConfig.mockReturnValue({});
|
|
23
|
+
// Restore JSON.parse before each test
|
|
24
|
+
JSON.parse = originalJsonParse;
|
|
25
|
+
});
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
// Ensure JSON.parse is restored after each test
|
|
28
|
+
JSON.parse = originalJsonParse;
|
|
29
|
+
});
|
|
30
|
+
describe('getInterceptInitData', () => {
|
|
31
|
+
it('should return default intercept flags when no intercepts are configured', () => {
|
|
32
|
+
const viewConfig = {};
|
|
33
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
34
|
+
expect(result).toEqual({
|
|
35
|
+
interceptUrls: [],
|
|
36
|
+
interceptTimeout: undefined,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it('should expand InterceptedApiType.AnswerData to specific URLs', () => {
|
|
40
|
+
const viewConfig = {
|
|
41
|
+
interceptUrls: [InterceptedApiType.AnswerData]
|
|
42
|
+
};
|
|
43
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
44
|
+
expect(result.interceptUrls).toEqual([
|
|
45
|
+
`${thoughtSpotHost}/prism/?op=GetChartWithData`,
|
|
46
|
+
`${thoughtSpotHost}/prism/?op=GetTableWithHeadlineData`,
|
|
47
|
+
`${thoughtSpotHost}/prism/?op=GetTableWithData`,
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
it('should expand InterceptedApiType.LiveboardData to specific URLs', () => {
|
|
51
|
+
const viewConfig = {
|
|
52
|
+
interceptUrls: [InterceptedApiType.LiveboardData]
|
|
53
|
+
};
|
|
54
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
55
|
+
expect(result.interceptUrls).toEqual([
|
|
56
|
+
`${thoughtSpotHost}/prism/?op=LoadContextBook`
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
it('should handle multiple intercept types', () => {
|
|
60
|
+
const viewConfig = {
|
|
61
|
+
interceptUrls: [
|
|
62
|
+
InterceptedApiType.AnswerData,
|
|
63
|
+
InterceptedApiType.LiveboardData
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
67
|
+
expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
|
|
68
|
+
expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=LoadContextBook`);
|
|
69
|
+
expect(result.interceptUrls.length).toBe(4);
|
|
70
|
+
});
|
|
71
|
+
it('should handle custom URL strings', () => {
|
|
72
|
+
const customUrl = '/api/custom-endpoint';
|
|
73
|
+
const viewConfig = {
|
|
74
|
+
interceptUrls: [customUrl]
|
|
75
|
+
};
|
|
76
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
77
|
+
expect(result.interceptUrls).toEqual([`${thoughtSpotHost}${customUrl}`]);
|
|
78
|
+
});
|
|
79
|
+
it('should handle full URL strings', () => {
|
|
80
|
+
const fullUrl = 'https://example.com/api/endpoint';
|
|
81
|
+
const viewConfig = {
|
|
82
|
+
interceptUrls: [fullUrl]
|
|
83
|
+
};
|
|
84
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
85
|
+
expect(result.interceptUrls).toEqual([fullUrl]);
|
|
86
|
+
});
|
|
87
|
+
it('should handle InterceptedApiType.ALL', () => {
|
|
88
|
+
const viewConfig = {
|
|
89
|
+
interceptUrls: [InterceptedApiType.ALL]
|
|
90
|
+
};
|
|
91
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
92
|
+
expect(result.interceptUrls).toEqual([InterceptedApiType.ALL]);
|
|
93
|
+
});
|
|
94
|
+
it('should prioritize ALL over other intercept types', () => {
|
|
95
|
+
const viewConfig = {
|
|
96
|
+
interceptUrls: [
|
|
97
|
+
InterceptedApiType.AnswerData,
|
|
98
|
+
InterceptedApiType.ALL,
|
|
99
|
+
'/api/custom'
|
|
100
|
+
]
|
|
101
|
+
};
|
|
102
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
103
|
+
expect(result.interceptUrls).toEqual([InterceptedApiType.ALL]);
|
|
104
|
+
});
|
|
105
|
+
it('should handle legacy isOnBeforeGetVizDataInterceptEnabled flag', () => {
|
|
106
|
+
const viewConfig = {
|
|
107
|
+
isOnBeforeGetVizDataInterceptEnabled: true
|
|
108
|
+
};
|
|
109
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
110
|
+
expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
|
|
111
|
+
});
|
|
112
|
+
it('should combine legacy flag with interceptUrls', () => {
|
|
113
|
+
const viewConfig = {
|
|
114
|
+
isOnBeforeGetVizDataInterceptEnabled: true,
|
|
115
|
+
interceptUrls: [InterceptedApiType.LiveboardData]
|
|
116
|
+
};
|
|
117
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
118
|
+
expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=GetChartWithData`);
|
|
119
|
+
expect(result.interceptUrls).toContain(`${thoughtSpotHost}/prism/?op=LoadContextBook`);
|
|
120
|
+
});
|
|
121
|
+
it('should pass through interceptTimeout', () => {
|
|
122
|
+
const viewConfig = {
|
|
123
|
+
interceptUrls: [],
|
|
124
|
+
interceptTimeout: 5000
|
|
125
|
+
};
|
|
126
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
127
|
+
expect(result.interceptTimeout).toBe(5000);
|
|
128
|
+
});
|
|
129
|
+
it('should deduplicate URLs when same type is added multiple times', () => {
|
|
130
|
+
const viewConfig = {
|
|
131
|
+
interceptUrls: [
|
|
132
|
+
InterceptedApiType.AnswerData,
|
|
133
|
+
InterceptedApiType.AnswerData
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
const result = apiIntercept.getInterceptInitData(viewConfig);
|
|
137
|
+
expect(result.interceptUrls.length).toBe(3); // 3 answer data URLs
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('handleInterceptEvent', () => {
|
|
141
|
+
let executeEvent;
|
|
142
|
+
let getUnsavedAnswerTml;
|
|
143
|
+
let viewConfig;
|
|
144
|
+
beforeEach(() => {
|
|
145
|
+
executeEvent = jest.fn();
|
|
146
|
+
getUnsavedAnswerTml = jest.fn().mockResolvedValue({ answer: { tml: 'test-tml' } });
|
|
147
|
+
viewConfig = {};
|
|
148
|
+
});
|
|
149
|
+
it('should handle valid intercept data', async () => {
|
|
150
|
+
const eventData = {
|
|
151
|
+
data: JSON.stringify({
|
|
152
|
+
input: '/prism/?op=GetChartWithData',
|
|
153
|
+
init: {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
body: JSON.stringify({
|
|
156
|
+
variables: {
|
|
157
|
+
session: { sessionId: 'session-123' },
|
|
158
|
+
contextBookId: 'viz-456'
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
await apiIntercept.handleInterceptEvent({
|
|
165
|
+
eventData,
|
|
166
|
+
executeEvent,
|
|
167
|
+
viewConfig,
|
|
168
|
+
getUnsavedAnswerTml
|
|
169
|
+
});
|
|
170
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.objectContaining({
|
|
171
|
+
input: '/prism/?op=GetChartWithData',
|
|
172
|
+
urlType: InterceptedApiType.AnswerData
|
|
173
|
+
}));
|
|
174
|
+
});
|
|
175
|
+
it('should trigger legacy OnBeforeGetVizDataIntercept for answer data URLs', async () => {
|
|
176
|
+
viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
|
|
177
|
+
const eventData = {
|
|
178
|
+
data: JSON.stringify({
|
|
179
|
+
input: '/prism/?op=GetChartWithData',
|
|
180
|
+
init: {
|
|
181
|
+
method: 'POST',
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
variables: {
|
|
184
|
+
session: { sessionId: 'session-123' },
|
|
185
|
+
contextBookId: 'viz-456'
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
};
|
|
191
|
+
await apiIntercept.handleInterceptEvent({
|
|
192
|
+
eventData,
|
|
193
|
+
executeEvent,
|
|
194
|
+
viewConfig,
|
|
195
|
+
getUnsavedAnswerTml
|
|
196
|
+
});
|
|
197
|
+
expect(getUnsavedAnswerTml).toHaveBeenCalledWith({
|
|
198
|
+
sessionId: 'session-123',
|
|
199
|
+
vizId: 'viz-456'
|
|
200
|
+
});
|
|
201
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.OnBeforeGetVizDataIntercept, {
|
|
202
|
+
data: {
|
|
203
|
+
data: { answer: { tml: 'test-tml' } },
|
|
204
|
+
status: embedEventStatus.END,
|
|
205
|
+
type: EmbedEvent.OnBeforeGetVizDataIntercept
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.any(Object));
|
|
209
|
+
});
|
|
210
|
+
it('should not trigger legacy intercept for non-answer data URLs', async () => {
|
|
211
|
+
viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
|
|
212
|
+
const eventData = {
|
|
213
|
+
data: JSON.stringify({
|
|
214
|
+
input: '/prism/?op=LoadContextBook',
|
|
215
|
+
init: {
|
|
216
|
+
method: 'POST',
|
|
217
|
+
body: '{}'
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
};
|
|
221
|
+
await apiIntercept.handleInterceptEvent({
|
|
222
|
+
eventData,
|
|
223
|
+
executeEvent,
|
|
224
|
+
viewConfig,
|
|
225
|
+
getUnsavedAnswerTml
|
|
226
|
+
});
|
|
227
|
+
expect(getUnsavedAnswerTml).not.toHaveBeenCalled();
|
|
228
|
+
expect(executeEvent).toHaveBeenCalledTimes(1);
|
|
229
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.any(Object));
|
|
230
|
+
});
|
|
231
|
+
it('should handle GetTableWithHeadlineData URL as answer data', async () => {
|
|
232
|
+
viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
|
|
233
|
+
const eventData = {
|
|
234
|
+
data: JSON.stringify({
|
|
235
|
+
input: '/prism/?op=GetTableWithHeadlineData',
|
|
236
|
+
init: {
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
variables: { session: { sessionId: 'test' } }
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
};
|
|
243
|
+
await apiIntercept.handleInterceptEvent({
|
|
244
|
+
eventData,
|
|
245
|
+
executeEvent,
|
|
246
|
+
viewConfig,
|
|
247
|
+
getUnsavedAnswerTml
|
|
248
|
+
});
|
|
249
|
+
expect(getUnsavedAnswerTml).toHaveBeenCalled();
|
|
250
|
+
});
|
|
251
|
+
it('should handle GetTableWithData URL as answer data', async () => {
|
|
252
|
+
viewConfig.isOnBeforeGetVizDataInterceptEnabled = true;
|
|
253
|
+
const eventData = {
|
|
254
|
+
data: JSON.stringify({
|
|
255
|
+
input: '/prism/?op=GetTableWithData',
|
|
256
|
+
init: {
|
|
257
|
+
body: JSON.stringify({
|
|
258
|
+
variables: { session: { sessionId: 'test' } }
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
};
|
|
263
|
+
await apiIntercept.handleInterceptEvent({
|
|
264
|
+
eventData,
|
|
265
|
+
executeEvent,
|
|
266
|
+
viewConfig,
|
|
267
|
+
getUnsavedAnswerTml
|
|
268
|
+
});
|
|
269
|
+
expect(getUnsavedAnswerTml).toHaveBeenCalled();
|
|
270
|
+
});
|
|
271
|
+
it('should handle invalid JSON in event data', async () => {
|
|
272
|
+
const eventData = {
|
|
273
|
+
data: 'invalid-json'
|
|
274
|
+
};
|
|
275
|
+
await apiIntercept.handleInterceptEvent({
|
|
276
|
+
eventData,
|
|
277
|
+
executeEvent,
|
|
278
|
+
viewConfig,
|
|
279
|
+
getUnsavedAnswerTml
|
|
280
|
+
});
|
|
281
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.Error, { error: 'Error parsing api intercept body' });
|
|
282
|
+
expect(mockLogger.error).toHaveBeenCalled();
|
|
283
|
+
});
|
|
284
|
+
it('should handle init with non-JSON body', async () => {
|
|
285
|
+
const eventData = {
|
|
286
|
+
data: JSON.stringify({
|
|
287
|
+
input: '/api/test',
|
|
288
|
+
init: {
|
|
289
|
+
method: 'POST',
|
|
290
|
+
body: 'plain-text-body'
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
};
|
|
294
|
+
await apiIntercept.handleInterceptEvent({
|
|
295
|
+
eventData,
|
|
296
|
+
executeEvent,
|
|
297
|
+
viewConfig,
|
|
298
|
+
getUnsavedAnswerTml
|
|
299
|
+
});
|
|
300
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.objectContaining({
|
|
301
|
+
init: expect.objectContaining({
|
|
302
|
+
body: 'plain-text-body'
|
|
303
|
+
})
|
|
304
|
+
}));
|
|
305
|
+
});
|
|
306
|
+
it('should handle malformed event data structure with property access error', async () => {
|
|
307
|
+
// Create an object with a getter that throws when accessing 'input'
|
|
308
|
+
global.JSON.parse = jest.fn().mockImplementationOnce((str) => {
|
|
309
|
+
// Return an object with a getter that throws
|
|
310
|
+
return new Proxy({}, {
|
|
311
|
+
get(target, prop) {
|
|
312
|
+
if (prop === 'input') {
|
|
313
|
+
throw new Error('Property access error');
|
|
314
|
+
}
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
const eventData = {
|
|
320
|
+
data: JSON.stringify({ input: '/test', init: {} })
|
|
321
|
+
};
|
|
322
|
+
await apiIntercept.handleInterceptEvent({
|
|
323
|
+
eventData,
|
|
324
|
+
executeEvent,
|
|
325
|
+
viewConfig,
|
|
326
|
+
getUnsavedAnswerTml
|
|
327
|
+
});
|
|
328
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.Error, { error: 'Error parsing api intercept body' });
|
|
329
|
+
expect(mockLogger.error).toHaveBeenCalled();
|
|
330
|
+
// Explicitly restore for this test
|
|
331
|
+
global.JSON.parse = originalJsonParse;
|
|
332
|
+
});
|
|
333
|
+
it('should determine urlType as ALL for unknown URLs', async () => {
|
|
334
|
+
const eventData = {
|
|
335
|
+
data: JSON.stringify({
|
|
336
|
+
input: '/unknown/endpoint',
|
|
337
|
+
init: { method: 'GET' }
|
|
338
|
+
})
|
|
339
|
+
};
|
|
340
|
+
await apiIntercept.handleInterceptEvent({
|
|
341
|
+
eventData,
|
|
342
|
+
executeEvent,
|
|
343
|
+
viewConfig,
|
|
344
|
+
getUnsavedAnswerTml
|
|
345
|
+
});
|
|
346
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.objectContaining({
|
|
347
|
+
urlType: InterceptedApiType.ALL
|
|
348
|
+
}));
|
|
349
|
+
});
|
|
350
|
+
it('should determine urlType as LiveboardData for liveboard URLs', async () => {
|
|
351
|
+
const eventData = {
|
|
352
|
+
data: JSON.stringify({
|
|
353
|
+
input: '/prism/?op=LoadContextBook',
|
|
354
|
+
init: { method: 'POST' }
|
|
355
|
+
})
|
|
356
|
+
};
|
|
357
|
+
await apiIntercept.handleInterceptEvent({
|
|
358
|
+
eventData,
|
|
359
|
+
executeEvent,
|
|
360
|
+
viewConfig,
|
|
361
|
+
getUnsavedAnswerTml
|
|
362
|
+
});
|
|
363
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.objectContaining({
|
|
364
|
+
urlType: InterceptedApiType.LiveboardData
|
|
365
|
+
}));
|
|
366
|
+
});
|
|
367
|
+
it('should handle event data with missing init', async () => {
|
|
368
|
+
const eventData = {
|
|
369
|
+
data: JSON.stringify({
|
|
370
|
+
input: '/prism/?op=GetChartWithData'
|
|
371
|
+
})
|
|
372
|
+
};
|
|
373
|
+
await apiIntercept.handleInterceptEvent({
|
|
374
|
+
eventData,
|
|
375
|
+
executeEvent,
|
|
376
|
+
viewConfig,
|
|
377
|
+
getUnsavedAnswerTml
|
|
378
|
+
});
|
|
379
|
+
// When init is missing, accessing init.body throws an error
|
|
380
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.Error, { error: 'Error parsing api intercept body' });
|
|
381
|
+
});
|
|
382
|
+
it('should handle event data with missing body', async () => {
|
|
383
|
+
const eventData = {
|
|
384
|
+
data: JSON.stringify({
|
|
385
|
+
input: '/prism/?op=GetChartWithData',
|
|
386
|
+
init: {}
|
|
387
|
+
})
|
|
388
|
+
};
|
|
389
|
+
await apiIntercept.handleInterceptEvent({
|
|
390
|
+
eventData,
|
|
391
|
+
executeEvent,
|
|
392
|
+
viewConfig,
|
|
393
|
+
getUnsavedAnswerTml
|
|
394
|
+
});
|
|
395
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.any(Object));
|
|
396
|
+
});
|
|
397
|
+
it('should handle event data with missing variables in body', async () => {
|
|
398
|
+
const eventData = {
|
|
399
|
+
data: JSON.stringify({
|
|
400
|
+
input: '/prism/?op=GetChartWithData',
|
|
401
|
+
init: {
|
|
402
|
+
body: JSON.stringify({})
|
|
403
|
+
}
|
|
404
|
+
})
|
|
405
|
+
};
|
|
406
|
+
await apiIntercept.handleInterceptEvent({
|
|
407
|
+
eventData,
|
|
408
|
+
executeEvent,
|
|
409
|
+
viewConfig,
|
|
410
|
+
getUnsavedAnswerTml
|
|
411
|
+
});
|
|
412
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.any(Object));
|
|
413
|
+
});
|
|
414
|
+
it('should handle event data with missing session in variables', async () => {
|
|
415
|
+
const eventData = {
|
|
416
|
+
data: JSON.stringify({
|
|
417
|
+
input: '/prism/?op=GetChartWithData',
|
|
418
|
+
init: {
|
|
419
|
+
body: JSON.stringify({
|
|
420
|
+
variables: {}
|
|
421
|
+
})
|
|
422
|
+
}
|
|
423
|
+
})
|
|
424
|
+
};
|
|
425
|
+
await apiIntercept.handleInterceptEvent({
|
|
426
|
+
eventData,
|
|
427
|
+
executeEvent,
|
|
428
|
+
viewConfig,
|
|
429
|
+
getUnsavedAnswerTml
|
|
430
|
+
});
|
|
431
|
+
expect(executeEvent).toHaveBeenCalledWith(EmbedEvent.ApiIntercept, expect.any(Object));
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
describe('processApiInterceptResponse', () => {
|
|
435
|
+
it('should process legacy format with error', () => {
|
|
436
|
+
const legacyPayload = {
|
|
437
|
+
data: {
|
|
438
|
+
error: {
|
|
439
|
+
errorText: 'Test Error',
|
|
440
|
+
errorDescription: 'Test Description'
|
|
441
|
+
},
|
|
442
|
+
execute: false
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
const result = apiIntercept.processApiInterceptResponse(legacyPayload);
|
|
446
|
+
expect(result).toEqual({
|
|
447
|
+
data: {
|
|
448
|
+
execute: false,
|
|
449
|
+
response: {
|
|
450
|
+
body: {
|
|
451
|
+
errors: [
|
|
452
|
+
{
|
|
453
|
+
title: 'Test Error',
|
|
454
|
+
description: 'Test Description',
|
|
455
|
+
isUserError: true,
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
data: {},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
it('should pass through new format unchanged', () => {
|
|
465
|
+
const newPayload = {
|
|
466
|
+
execute: true,
|
|
467
|
+
response: {
|
|
468
|
+
body: { data: 'test' }
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
const result = apiIntercept.processApiInterceptResponse(newPayload);
|
|
472
|
+
expect(result).toEqual(newPayload);
|
|
473
|
+
});
|
|
474
|
+
it('should handle payload without data property', () => {
|
|
475
|
+
const payload = {
|
|
476
|
+
execute: true
|
|
477
|
+
};
|
|
478
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
479
|
+
expect(result).toEqual(payload);
|
|
480
|
+
});
|
|
481
|
+
it('should handle payload with data but no error', () => {
|
|
482
|
+
const payload = {
|
|
483
|
+
data: {
|
|
484
|
+
execute: true,
|
|
485
|
+
someOtherProperty: 'value'
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
489
|
+
expect(result).toEqual(payload);
|
|
490
|
+
});
|
|
491
|
+
it('should handle null payload', () => {
|
|
492
|
+
const result = apiIntercept.processApiInterceptResponse(null);
|
|
493
|
+
expect(result).toBeNull();
|
|
494
|
+
});
|
|
495
|
+
it('should handle undefined payload', () => {
|
|
496
|
+
const result = apiIntercept.processApiInterceptResponse(undefined);
|
|
497
|
+
expect(result).toBeUndefined();
|
|
498
|
+
});
|
|
499
|
+
it('should handle payload with null data', () => {
|
|
500
|
+
const payload = {
|
|
501
|
+
data: null
|
|
502
|
+
};
|
|
503
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
504
|
+
expect(result).toEqual(payload);
|
|
505
|
+
});
|
|
506
|
+
it('should handle payload with data.error set to null', () => {
|
|
507
|
+
const payload = {
|
|
508
|
+
data: {
|
|
509
|
+
error: null,
|
|
510
|
+
execute: true
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
514
|
+
expect(result).toEqual(payload);
|
|
515
|
+
});
|
|
516
|
+
it('should handle payload with data.error set to undefined', () => {
|
|
517
|
+
const payload = {
|
|
518
|
+
data: {
|
|
519
|
+
error: undefined,
|
|
520
|
+
execute: true
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
524
|
+
expect(result).toEqual(payload);
|
|
525
|
+
});
|
|
526
|
+
it('should handle payload with data.error set to false', () => {
|
|
527
|
+
const payload = {
|
|
528
|
+
data: {
|
|
529
|
+
error: false,
|
|
530
|
+
execute: true
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
534
|
+
expect(result).toEqual(payload);
|
|
535
|
+
});
|
|
536
|
+
it('should handle payload with data.error set to 0', () => {
|
|
537
|
+
const payload = {
|
|
538
|
+
data: {
|
|
539
|
+
error: 0,
|
|
540
|
+
execute: true
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
544
|
+
expect(result).toEqual(payload);
|
|
545
|
+
});
|
|
546
|
+
it('should handle payload with data.error set to empty string', () => {
|
|
547
|
+
const payload = {
|
|
548
|
+
data: {
|
|
549
|
+
error: '',
|
|
550
|
+
execute: true
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
const result = apiIntercept.processApiInterceptResponse(payload);
|
|
554
|
+
expect(result).toEqual(payload);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
describe('processLegacyInterceptResponse', () => {
|
|
558
|
+
it('should convert legacy error format to new format', () => {
|
|
559
|
+
const legacyPayload = {
|
|
560
|
+
data: {
|
|
561
|
+
error: {
|
|
562
|
+
errorText: 'Custom Error',
|
|
563
|
+
errorDescription: 'Custom Description'
|
|
564
|
+
},
|
|
565
|
+
execute: false
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
569
|
+
expect(result).toEqual({
|
|
570
|
+
data: {
|
|
571
|
+
execute: false,
|
|
572
|
+
response: {
|
|
573
|
+
body: {
|
|
574
|
+
errors: [
|
|
575
|
+
{
|
|
576
|
+
title: 'Custom Error',
|
|
577
|
+
description: 'Custom Description',
|
|
578
|
+
isUserError: true,
|
|
579
|
+
},
|
|
580
|
+
],
|
|
581
|
+
data: {},
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
it('should handle missing error properties', () => {
|
|
588
|
+
const legacyPayload = {
|
|
589
|
+
data: {
|
|
590
|
+
error: {},
|
|
591
|
+
execute: true
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
595
|
+
expect(result.data.response.body.errors[0]).toEqual({
|
|
596
|
+
title: undefined,
|
|
597
|
+
description: undefined,
|
|
598
|
+
isUserError: true,
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
it('should handle missing execute property', () => {
|
|
602
|
+
const legacyPayload = {
|
|
603
|
+
data: {
|
|
604
|
+
error: {
|
|
605
|
+
errorText: 'Error',
|
|
606
|
+
errorDescription: 'Description'
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
611
|
+
expect(result.data.execute).toBeUndefined();
|
|
612
|
+
});
|
|
613
|
+
it('should always include empty data object', () => {
|
|
614
|
+
const legacyPayload = {
|
|
615
|
+
data: {
|
|
616
|
+
error: {
|
|
617
|
+
errorText: 'Error',
|
|
618
|
+
errorDescription: 'Description'
|
|
619
|
+
},
|
|
620
|
+
execute: false
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
624
|
+
expect(result.data.response.body.data).toEqual({});
|
|
625
|
+
});
|
|
626
|
+
it('should always set isUserError to true', () => {
|
|
627
|
+
const legacyPayload = {
|
|
628
|
+
data: {
|
|
629
|
+
error: {
|
|
630
|
+
errorText: 'Error',
|
|
631
|
+
errorDescription: 'Description'
|
|
632
|
+
},
|
|
633
|
+
execute: false
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
637
|
+
expect(result.data.response.body.errors[0].isUserError).toBe(true);
|
|
638
|
+
});
|
|
639
|
+
it('should handle payload with null data', () => {
|
|
640
|
+
const legacyPayload = {
|
|
641
|
+
data: null
|
|
642
|
+
};
|
|
643
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
644
|
+
expect(result.data.execute).toBeUndefined();
|
|
645
|
+
expect(result.data.response.body.errors[0].title).toBeUndefined();
|
|
646
|
+
expect(result.data.response.body.errors[0].description).toBeUndefined();
|
|
647
|
+
});
|
|
648
|
+
it('should handle payload with null error', () => {
|
|
649
|
+
const legacyPayload = {
|
|
650
|
+
data: {
|
|
651
|
+
error: null,
|
|
652
|
+
execute: true
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
656
|
+
expect(result.data.execute).toBe(true);
|
|
657
|
+
expect(result.data.response.body.errors[0].title).toBeUndefined();
|
|
658
|
+
expect(result.data.response.body.errors[0].description).toBeUndefined();
|
|
659
|
+
});
|
|
660
|
+
it('should handle payload with undefined properties', () => {
|
|
661
|
+
const legacyPayload = {};
|
|
662
|
+
const result = apiIntercept.processLegacyInterceptResponse(legacyPayload);
|
|
663
|
+
expect(result.data.execute).toBeUndefined();
|
|
664
|
+
expect(result.data.response.body.errors[0].title).toBeUndefined();
|
|
665
|
+
expect(result.data.response.body.errors[0].description).toBeUndefined();
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
//# sourceMappingURL=api-intercept.spec.js.map
|