@thoughtspot/visual-embed-sdk 1.39.1 → 1.39.2-alpha.2
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/config.spec.js +9 -0
- package/cjs/src/config.spec.js.map +1 -1
- package/cjs/src/embed/app.d.ts +75 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +69 -9
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +374 -12
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
- package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +24 -4
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
- package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +28 -0
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/embedConfig.d.ts +9 -7
- package/cjs/src/embed/embedConfig.d.ts.map +1 -1
- package/cjs/src/embed/embedConfig.js +9 -7
- package/cjs/src/embed/embedConfig.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +56 -17
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +48 -4
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +215 -11
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +5 -0
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +16 -1
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +164 -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 +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 +3 -2
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.d.ts +71 -20
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +79 -42
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +436 -100
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +80 -6
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +45 -1
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/cjs/src/utils/processTrigger.js +2 -1
- package/cjs/src/utils/processTrigger.js.map +1 -1
- package/cjs/src/utils.d.ts +6 -0
- package/cjs/src/utils.d.ts.map +1 -1
- package/cjs/src/utils.js +23 -3
- package/cjs/src/utils.js.map +1 -1
- package/cjs/src/utils.spec.js +237 -1
- package/cjs/src/utils.spec.js.map +1 -1
- package/dist/{index-JaFaxrvQ.js → index-CmEQfuE3.js} +1 -1
- package/dist/index-DeFzsyFF.js +7371 -0
- package/dist/index-Dpf0rd6w.js +7371 -0
- package/dist/index-UuEbsISo.js +7447 -0
- package/dist/index-e3Uw3YFO.js +7371 -0
- package/dist/src/embed/app.d.ts +75 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/bodyless-conversation.d.ts +19 -7
- package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/dist/src/embed/embedConfig.d.ts +9 -7
- package/dist/src/embed/embedConfig.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +56 -17
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +5 -0
- 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/react/all-types-export.d.ts +1 -1
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +71 -20
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +80 -6
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/dist/src/utils.d.ts +6 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +320 -78
- package/dist/tsembed-react.js +320 -76
- package/dist/tsembed.es.js +238 -31
- package/dist/tsembed.js +236 -29
- package/dist/visual-embed-sdk-react-full.d.ts +288 -72
- package/dist/visual-embed-sdk-react.d.ts +288 -72
- package/dist/visual-embed-sdk.d.ts +218 -53
- package/lib/package.json +1 -1
- package/lib/src/config.spec.js +9 -0
- package/lib/src/config.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +75 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +69 -9
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +376 -14
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +19 -7
- package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +23 -4
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.spec.js +9 -191
- package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +30 -2
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/embedConfig.d.ts +9 -7
- package/lib/src/embed/embedConfig.d.ts.map +1 -1
- package/lib/src/embed/embedConfig.js +9 -7
- package/lib/src/embed/embedConfig.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +56 -17
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +49 -5
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +215 -11
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +5 -0
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +16 -1
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +164 -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/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/react/index.d.ts +71 -20
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +79 -43
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +439 -103
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +80 -6
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +45 -1
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/lib/src/utils/processTrigger.js +2 -1
- package/lib/src/utils/processTrigger.js.map +1 -1
- package/lib/src/utils.d.ts +6 -0
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +21 -2
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +238 -2
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +219 -54
- package/package.json +1 -1
- package/src/config.spec.ts +11 -0
- package/src/embed/app.spec.ts +479 -26
- package/src/embed/app.ts +133 -27
- package/src/embed/bodyless-conversation.spec.ts +9 -203
- package/src/embed/bodyless-conversation.ts +24 -10
- package/src/embed/conversation.spec.ts +40 -2
- package/src/embed/embedConfig.ts +10 -8
- package/src/embed/liveboard.spec.ts +256 -5
- package/src/embed/liveboard.ts +99 -27
- package/src/embed/ts-embed.spec.ts +225 -0
- package/src/embed/ts-embed.ts +19 -0
- package/src/errors.ts +1 -0
- package/src/index.ts +2 -0
- package/src/react/all-types-export.ts +2 -1
- package/src/react/index.spec.tsx +556 -157
- package/src/react/index.tsx +117 -51
- package/src/types.ts +117 -43
- package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
- package/src/utils/processTrigger.ts +1 -1
- package/src/utils.spec.ts +279 -2
- package/src/utils.ts +28 -2
package/src/react/index.spec.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import '@testing-library/jest-dom';
|
|
3
3
|
import '@testing-library/jest-dom/extend-expect';
|
|
4
4
|
import {
|
|
@@ -15,8 +15,7 @@ import {
|
|
|
15
15
|
mockMessageChannel,
|
|
16
16
|
} from '../test/test-utils';
|
|
17
17
|
import {
|
|
18
|
-
SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed, PreRenderedLiveboardEmbed,
|
|
19
|
-
SpotterAgentEmbed
|
|
18
|
+
SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed, PreRenderedLiveboardEmbed, PreRenderedSearchEmbed, PreRenderedAppEmbed, useSpotterAgent, SpotterMessage, useInit
|
|
20
19
|
} from './index';
|
|
21
20
|
import * as allExports from './index';
|
|
22
21
|
import {
|
|
@@ -236,199 +235,599 @@ describe('React Components', () => {
|
|
|
236
235
|
});
|
|
237
236
|
});
|
|
238
237
|
|
|
239
|
-
describe('
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
describe('SpotterMessage', () => {
|
|
239
|
+
const mockMessage = {
|
|
240
|
+
sessionId: "session123",
|
|
241
|
+
genNo: 1,
|
|
242
|
+
acSessionId: "acSession123",
|
|
243
|
+
acGenNo: 2,
|
|
244
|
+
worksheetId: "worksheet123"
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
it('Should render the SpotterMessage component with required props', async () => {
|
|
248
|
+
const { container } = render(
|
|
249
|
+
<SpotterMessage message={mockMessage} />,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
await waitFor(() => getIFrameEl(container));
|
|
253
|
+
|
|
254
|
+
expect(getIFrameEl(container)).not.toBe(null);
|
|
255
|
+
expect(getIFrameSrc(container)).toContain('sessionId=session123');
|
|
256
|
+
expect(getIFrameSrc(container)).toContain('genNo=1');
|
|
257
|
+
expect(getIFrameSrc(container)).toContain('acSessionId=acSession123');
|
|
258
|
+
expect(getIFrameSrc(container)).toContain('acGenNo=2');
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('Should render the SpotterMessage component with optional query', async () => {
|
|
262
|
+
const { container } = render(
|
|
263
|
+
<SpotterMessage
|
|
264
|
+
message={mockMessage}
|
|
265
|
+
query="show me sales"
|
|
266
|
+
/>,
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
await waitFor(() => getIFrameEl(container));
|
|
270
|
+
|
|
271
|
+
expect(getIFrameEl(container)).not.toBe(null);
|
|
272
|
+
expect(getIFrameSrc(container)).toContain('sessionId=session123');
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('Should have the correct container element with className', async () => {
|
|
276
|
+
const { container } = render(
|
|
277
|
+
<SpotterMessage
|
|
278
|
+
message={mockMessage}
|
|
279
|
+
className="custom-class"
|
|
280
|
+
/>,
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
await waitFor(() => getIFrameEl(container));
|
|
284
|
+
|
|
285
|
+
expect(
|
|
286
|
+
getIFrameEl(container).parentElement.classList.contains('custom-class'),
|
|
287
|
+
).toBe(true);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Note: insertAsSibling is not supported for SpotterMessage as it's not part of the allowed props
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe('Component Factory Coverage', () => {
|
|
294
|
+
it('Should test basic component creation', () => {
|
|
295
|
+
expect(() => {
|
|
296
|
+
render(<LiveboardEmbed liveboardId="test" />);
|
|
297
|
+
}).not.toThrow();
|
|
242
298
|
|
|
243
|
-
|
|
299
|
+
expect(() => {
|
|
300
|
+
render(<SearchEmbed dataSource="test" />);
|
|
301
|
+
}).not.toThrow();
|
|
244
302
|
|
|
245
|
-
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
303
|
+
expect(() => {
|
|
304
|
+
render(<AppEmbed showPrimaryNavbar={false} />);
|
|
305
|
+
}).not.toThrow();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('Should test component factory existence', () => {
|
|
309
|
+
expect(PreRenderedLiveboardEmbed).toBeDefined();
|
|
310
|
+
expect(PreRenderedSearchEmbed).toBeDefined();
|
|
311
|
+
expect(PreRenderedAppEmbed).toBeDefined();
|
|
312
|
+
expect(typeof PreRenderedLiveboardEmbed).toBe('object');
|
|
313
|
+
expect(typeof PreRenderedSearchEmbed).toBe('object');
|
|
314
|
+
expect(typeof PreRenderedAppEmbed).toBe('object');
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe('Components with insertAsSibling', () => {
|
|
319
|
+
it('Should render LiveboardEmbed with insertAsSibling', async () => {
|
|
320
|
+
const { container } = render(
|
|
321
|
+
<LiveboardEmbed
|
|
322
|
+
liveboardId="test-liveboard"
|
|
323
|
+
insertAsSibling={true}
|
|
324
|
+
/>,
|
|
258
325
|
);
|
|
259
326
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
327
|
+
await waitFor(() => getIFrameEl(container));
|
|
328
|
+
expect(container.querySelector('span')).not.toBe(null);
|
|
329
|
+
expect(container.querySelector('span')?.style.position).toBe('absolute');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('Should render SearchEmbed with insertAsSibling', async () => {
|
|
333
|
+
const { container } = render(
|
|
334
|
+
<SearchEmbed
|
|
335
|
+
dataSource="test-datasource"
|
|
336
|
+
insertAsSibling={true}
|
|
337
|
+
/>,
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
await waitFor(() => getIFrameEl(container));
|
|
341
|
+
expect(container.querySelector('span')).not.toBe(null);
|
|
342
|
+
expect(container.querySelector('span')?.style.position).toBe('absolute');
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('Should render AppEmbed with insertAsSibling', async () => {
|
|
346
|
+
const { container } = render(
|
|
347
|
+
<AppEmbed
|
|
348
|
+
showPrimaryNavbar={false}
|
|
349
|
+
insertAsSibling={true}
|
|
350
|
+
/>,
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
await waitFor(() => getIFrameEl(container));
|
|
354
|
+
expect(container.querySelector('span')).not.toBe(null);
|
|
355
|
+
expect(container.querySelector('span')?.style.position).toBe('absolute');
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('Should render SearchBarEmbed with insertAsSibling', async () => {
|
|
359
|
+
const { container } = render(
|
|
360
|
+
<SearchBarEmbed
|
|
361
|
+
dataSource="test-datasource"
|
|
362
|
+
insertAsSibling={true}
|
|
363
|
+
/>,
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
await waitFor(() => getIFrameEl(container));
|
|
367
|
+
expect(container.querySelector('span')).not.toBe(null);
|
|
368
|
+
expect(container.querySelector('span')?.style.position).toBe('absolute');
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('Should render components with both insertAsSibling and className', async () => {
|
|
372
|
+
const { container } = render(
|
|
373
|
+
<LiveboardEmbed
|
|
374
|
+
liveboardId="test-liveboard"
|
|
375
|
+
insertAsSibling={true}
|
|
376
|
+
className="custom-class"
|
|
377
|
+
/>,
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
await waitFor(() => getIFrameEl(container));
|
|
381
|
+
expect(container.querySelector('span')).not.toBe(null);
|
|
382
|
+
expect(getIFrameEl(container).classList.contains('custom-class')).toBe(true);
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
describe('useSpotterAgent', () => {
|
|
387
|
+
it('Should return an object with sendMessage function', () => {
|
|
388
|
+
const TestComponent = () => {
|
|
389
|
+
const spotterAgent = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
390
|
+
expect(typeof spotterAgent).toBe('object');
|
|
391
|
+
expect(typeof spotterAgent.sendMessage).toBe('function');
|
|
392
|
+
return <div>Test</div>;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
render(<TestComponent />);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('Should have proper sendMessage callback structure', () => {
|
|
399
|
+
const TestComponent = () => {
|
|
400
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
401
|
+
|
|
402
|
+
// Test that sendMessage is a function that accepts a string
|
|
403
|
+
expect(typeof sendMessage).toBe('function');
|
|
404
|
+
expect(sendMessage.length).toBe(1); // Should accept one parameter
|
|
264
405
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
406
|
+
return <div>Test</div>;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
render(<TestComponent />);
|
|
268
410
|
});
|
|
269
411
|
|
|
270
|
-
it('Should
|
|
271
|
-
|
|
272
|
-
container: document.createElement('div'),
|
|
273
|
-
viz: {}
|
|
274
|
-
});
|
|
412
|
+
it('Should return error when service is not initialized', async () => {
|
|
413
|
+
let sendMessageResult: any;
|
|
275
414
|
|
|
276
415
|
const TestComponent = () => {
|
|
277
|
-
const
|
|
416
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
278
417
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
conversationRef.current.sendMessage = mockSendMessage;
|
|
282
|
-
|
|
283
|
-
conversationRef.current.sendMessage("Test message");
|
|
284
|
-
}
|
|
285
|
-
};
|
|
418
|
+
// Call sendMessage immediately before service has time to initialize
|
|
419
|
+
sendMessageResult = sendMessage('test query');
|
|
286
420
|
|
|
287
|
-
return
|
|
288
|
-
<>
|
|
289
|
-
<SpotterAgentEmbed
|
|
290
|
-
ref={conversationRef}
|
|
291
|
-
worksheetId="test-worksheet-id"
|
|
292
|
-
/>
|
|
293
|
-
<button data-testid="test-button" onClick={handleClick}>
|
|
294
|
-
Send Message
|
|
295
|
-
</button>
|
|
296
|
-
</>
|
|
297
|
-
);
|
|
421
|
+
return <div>Test</div>;
|
|
298
422
|
};
|
|
423
|
+
|
|
424
|
+
render(<TestComponent />);
|
|
299
425
|
|
|
300
|
-
const
|
|
426
|
+
const result = await sendMessageResult;
|
|
427
|
+
expect(result).toEqual({
|
|
428
|
+
error: expect.any(Error)
|
|
429
|
+
});
|
|
430
|
+
expect(result.error.message).toBe('SpotterAgent not initialized');
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('Should call sendMessage and handle async behavior', async () => {
|
|
434
|
+
let sendMessageFunction: any;
|
|
301
435
|
|
|
302
|
-
|
|
436
|
+
const TestComponent = () => {
|
|
437
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
438
|
+
sendMessageFunction = sendMessage;
|
|
439
|
+
return <div>Test</div>;
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
render(<TestComponent />);
|
|
303
443
|
|
|
304
|
-
|
|
444
|
+
// Test that sendMessage is a function
|
|
445
|
+
expect(typeof sendMessageFunction).toBe('function');
|
|
446
|
+
|
|
447
|
+
// Call sendMessage - should not throw
|
|
448
|
+
expect(() => {
|
|
449
|
+
sendMessageFunction('test query');
|
|
450
|
+
}).not.toThrow();
|
|
305
451
|
});
|
|
306
452
|
|
|
307
|
-
it('Should
|
|
308
|
-
|
|
309
|
-
container: document.createElement('div'),
|
|
310
|
-
viz: {}
|
|
311
|
-
});
|
|
453
|
+
it('Should handle multiple calls to sendMessage', async () => {
|
|
454
|
+
let sendMessageFunction: any;
|
|
312
455
|
|
|
313
456
|
const TestComponent = () => {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (embedRef.current) {
|
|
318
|
-
const service = embedRef.current as unknown as {
|
|
319
|
-
sendMessage: typeof mockSendMessage
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
service.sendMessage = mockSendMessage;
|
|
323
|
-
|
|
324
|
-
service.sendMessage("Test with useEmbedRef");
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
return (
|
|
329
|
-
<>
|
|
330
|
-
<SpotterAgentEmbed
|
|
331
|
-
ref={embedRef}
|
|
332
|
-
worksheetId="test-worksheet-id"
|
|
333
|
-
/>
|
|
334
|
-
<button data-testid="use-embed-ref-button" onClick={handleClick}>
|
|
335
|
-
Send with useEmbedRef
|
|
336
|
-
</button>
|
|
337
|
-
</>
|
|
338
|
-
);
|
|
457
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
458
|
+
sendMessageFunction = sendMessage;
|
|
459
|
+
return <div>Test</div>;
|
|
339
460
|
};
|
|
461
|
+
|
|
462
|
+
render(<TestComponent />);
|
|
340
463
|
|
|
341
|
-
|
|
464
|
+
// Multiple calls should not throw
|
|
465
|
+
expect(() => {
|
|
466
|
+
sendMessageFunction('query 1');
|
|
467
|
+
sendMessageFunction('query 2');
|
|
468
|
+
sendMessageFunction('query 3');
|
|
469
|
+
}).not.toThrow();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('Should handle config object changes', () => {
|
|
473
|
+
const TestComponent = ({ config }: { config: any }) => {
|
|
474
|
+
const { sendMessage } = useSpotterAgent(config);
|
|
475
|
+
expect(sendMessage).toBeDefined();
|
|
476
|
+
return <div>Test</div>;
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const config1 = { worksheetId: 'test1' };
|
|
480
|
+
const config2 = { worksheetId: 'test2' };
|
|
342
481
|
|
|
343
|
-
|
|
482
|
+
const { rerender } = render(<TestComponent config={config1} />);
|
|
344
483
|
|
|
345
|
-
|
|
484
|
+
// Should not throw when config changes
|
|
485
|
+
expect(() => {
|
|
486
|
+
rerender(<TestComponent config={config2} />);
|
|
487
|
+
}).not.toThrow();
|
|
346
488
|
});
|
|
347
489
|
|
|
348
|
-
it('Should
|
|
349
|
-
let capturedInstance: any = null;
|
|
350
|
-
|
|
490
|
+
it('Should handle unmounting without errors', () => {
|
|
351
491
|
const TestComponent = () => {
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
capturedInstance = embedRef.current;
|
|
356
|
-
|
|
357
|
-
if (capturedInstance) {
|
|
358
|
-
const mockConversationService = {
|
|
359
|
-
sendMessage: jest.fn().mockResolvedValue({
|
|
360
|
-
data: {
|
|
361
|
-
sessionId: 'test-session',
|
|
362
|
-
genNo: 1,
|
|
363
|
-
stateKey: {
|
|
364
|
-
transactionId: 'test-transaction',
|
|
365
|
-
generationNumber: 1
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
})
|
|
369
|
-
};
|
|
370
|
-
(capturedInstance as any).conversationService = mockConversationService;
|
|
371
|
-
}
|
|
372
|
-
}, []);
|
|
373
|
-
|
|
374
|
-
return (
|
|
375
|
-
<SpotterAgentEmbed
|
|
376
|
-
ref={embedRef}
|
|
377
|
-
worksheetId="test-worksheet-id"
|
|
378
|
-
className="embedClass"
|
|
379
|
-
/>
|
|
380
|
-
);
|
|
492
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
493
|
+
expect(sendMessage).toBeDefined();
|
|
494
|
+
return <div>Test</div>;
|
|
381
495
|
};
|
|
496
|
+
|
|
497
|
+
const { unmount } = render(<TestComponent />);
|
|
382
498
|
|
|
383
|
-
|
|
499
|
+
// Should not throw when unmounting
|
|
500
|
+
expect(() => {
|
|
501
|
+
unmount();
|
|
502
|
+
}).not.toThrow();
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('Should create stable hook structure', () => {
|
|
506
|
+
let hookResult1: any, hookResult2: any;
|
|
384
507
|
|
|
385
|
-
|
|
508
|
+
const TestComponent = ({ counter }: { counter: number }) => {
|
|
509
|
+
const result = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
510
|
+
|
|
511
|
+
if (counter === 1) {
|
|
512
|
+
hookResult1 = result;
|
|
513
|
+
} else {
|
|
514
|
+
hookResult2 = result;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return <div>Test</div>;
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const { rerender } = render(<TestComponent counter={1} />);
|
|
521
|
+
rerender(<TestComponent counter={2} />);
|
|
386
522
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
523
|
+
// Both should have same structure
|
|
524
|
+
expect(hookResult1).toEqual({ sendMessage: expect.any(Function) });
|
|
525
|
+
expect(hookResult2).toEqual({ sendMessage: expect.any(Function) });
|
|
391
526
|
});
|
|
527
|
+
|
|
528
|
+
it('Should handle different worksheet IDs', () => {
|
|
529
|
+
const TestComponent = ({ worksheetId }: { worksheetId: string }) => {
|
|
530
|
+
const { sendMessage } = useSpotterAgent({ worksheetId });
|
|
531
|
+
expect(sendMessage).toBeDefined();
|
|
532
|
+
return <div>Test</div>;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const { rerender } = render(<TestComponent worksheetId="worksheet1" />);
|
|
536
|
+
|
|
537
|
+
// Should handle different worksheet IDs
|
|
538
|
+
expect(() => {
|
|
539
|
+
rerender(<TestComponent worksheetId="worksheet2" />);
|
|
540
|
+
rerender(<TestComponent worksheetId="worksheet3" />);
|
|
541
|
+
}).not.toThrow();
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('Should handle empty query strings', () => {
|
|
545
|
+
let sendMessageFunction: any;
|
|
546
|
+
|
|
547
|
+
const TestComponent = () => {
|
|
548
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
549
|
+
sendMessageFunction = sendMessage;
|
|
550
|
+
return <div>Test</div>;
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
render(<TestComponent />);
|
|
554
|
+
|
|
555
|
+
// Should handle empty strings
|
|
556
|
+
expect(() => {
|
|
557
|
+
sendMessageFunction('');
|
|
558
|
+
sendMessageFunction(' ');
|
|
559
|
+
}).not.toThrow();
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it('Should handle complex config objects', () => {
|
|
563
|
+
const complexConfig = {
|
|
564
|
+
worksheetId: 'test-worksheet',
|
|
565
|
+
hiddenActions: [Action.ReportError],
|
|
566
|
+
className: 'test-class',
|
|
567
|
+
searchOptions: {
|
|
568
|
+
searchQuery: 'test query'
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const TestComponent = () => {
|
|
573
|
+
const { sendMessage } = useSpotterAgent(complexConfig);
|
|
574
|
+
expect(sendMessage).toBeDefined();
|
|
575
|
+
return <div>Test</div>;
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// Should not throw with complex config
|
|
579
|
+
expect(() => {
|
|
580
|
+
render(<TestComponent />);
|
|
581
|
+
}).not.toThrow();
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it('Should maintain function identity across re-renders with same config', () => {
|
|
585
|
+
let sendMessage1: any, sendMessage2: any;
|
|
586
|
+
|
|
587
|
+
const TestComponent = ({ forceRender }: { forceRender: number }) => {
|
|
588
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
589
|
+
|
|
590
|
+
if (forceRender === 1) {
|
|
591
|
+
sendMessage1 = sendMessage;
|
|
592
|
+
} else {
|
|
593
|
+
sendMessage2 = sendMessage;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
return <div>Test</div>;
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
const { rerender } = render(<TestComponent forceRender={1} />);
|
|
600
|
+
rerender(<TestComponent forceRender={2} />);
|
|
601
|
+
|
|
602
|
+
// Functions should exist
|
|
603
|
+
expect(sendMessage1).toBeDefined();
|
|
604
|
+
expect(sendMessage2).toBeDefined();
|
|
605
|
+
expect(typeof sendMessage1).toBe('function');
|
|
606
|
+
expect(typeof sendMessage2).toBe('function');
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it('Should handle sendMessage calls with null service ref', async () => {
|
|
610
|
+
let capturedSendMessage: any;
|
|
611
|
+
|
|
612
|
+
const TestComponent = () => {
|
|
613
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
614
|
+
capturedSendMessage = sendMessage;
|
|
615
|
+
return <div>Test</div>;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
const { unmount } = render(<TestComponent />);
|
|
619
|
+
|
|
620
|
+
// Unmount to trigger cleanup
|
|
621
|
+
unmount();
|
|
622
|
+
|
|
623
|
+
// Now call sendMessage after unmount - should return error
|
|
624
|
+
const result = await capturedSendMessage('test query');
|
|
625
|
+
expect(result).toEqual({
|
|
626
|
+
error: expect.any(Error)
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('Should test service ref cleanup on config change', () => {
|
|
631
|
+
const TestComponent = ({ worksheetId }: { worksheetId: string }) => {
|
|
632
|
+
const { sendMessage } = useSpotterAgent({ worksheetId });
|
|
633
|
+
expect(sendMessage).toBeDefined();
|
|
634
|
+
return <div>Test</div>;
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
const { rerender } = render(<TestComponent worksheetId="worksheet1" />);
|
|
638
|
+
|
|
639
|
+
// This should trigger the cleanup and create new service
|
|
640
|
+
rerender(<TestComponent worksheetId="worksheet2" />);
|
|
641
|
+
|
|
642
|
+
// Should still work after rerender
|
|
643
|
+
expect(() => {
|
|
644
|
+
rerender(<TestComponent worksheetId="worksheet3" />);
|
|
645
|
+
}).not.toThrow();
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
it('Should test different config variations', () => {
|
|
649
|
+
const configs = [
|
|
650
|
+
{ worksheetId: 'test1' },
|
|
651
|
+
{ worksheetId: 'test2', hiddenActions: [Action.ReportError] },
|
|
652
|
+
{ worksheetId: 'test3', className: 'test-class' },
|
|
653
|
+
{ worksheetId: 'test4', searchOptions: { searchQuery: 'test' } }
|
|
654
|
+
];
|
|
655
|
+
|
|
656
|
+
configs.forEach((config, index) => {
|
|
657
|
+
const TestComponent = () => {
|
|
658
|
+
const { sendMessage } = useSpotterAgent(config);
|
|
659
|
+
expect(sendMessage).toBeDefined();
|
|
660
|
+
return <div>Test {index}</div>;
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
expect(() => {
|
|
664
|
+
const { unmount } = render(<TestComponent />);
|
|
665
|
+
unmount();
|
|
666
|
+
}).not.toThrow();
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it('Should handle rapid config changes', () => {
|
|
671
|
+
const TestComponent = ({ worksheetId }: { worksheetId: string }) => {
|
|
672
|
+
const { sendMessage } = useSpotterAgent({ worksheetId });
|
|
673
|
+
expect(sendMessage).toBeDefined();
|
|
674
|
+
return <div>Test</div>;
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
const { rerender } = render(<TestComponent worksheetId="worksheet1" />);
|
|
678
|
+
|
|
679
|
+
// Rapid config changes to test cleanup logic
|
|
680
|
+
for (let i = 2; i <= 10; i++) {
|
|
681
|
+
rerender(<TestComponent worksheetId={`worksheet${i}`} />);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Should still work after many changes
|
|
685
|
+
expect(() => {
|
|
686
|
+
rerender(<TestComponent worksheetId="final-worksheet" />);
|
|
687
|
+
}).not.toThrow();
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
it('Should handle sendMessage with different query types', () => {
|
|
691
|
+
let sendMessageFunction: any;
|
|
692
|
+
|
|
693
|
+
const TestComponent = () => {
|
|
694
|
+
const { sendMessage } = useSpotterAgent({ worksheetId: 'test-worksheet' });
|
|
695
|
+
sendMessageFunction = sendMessage;
|
|
696
|
+
return <div>Test</div>;
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
render(<TestComponent />);
|
|
700
|
+
|
|
701
|
+
// Test different query types
|
|
702
|
+
const queries = [
|
|
703
|
+
'simple query',
|
|
704
|
+
'query with numbers 123',
|
|
705
|
+
'query with special chars !@#$%',
|
|
706
|
+
'very long query that might test different code paths in the system when processing',
|
|
707
|
+
'',
|
|
708
|
+
' whitespace ',
|
|
709
|
+
'null',
|
|
710
|
+
'undefined'
|
|
711
|
+
];
|
|
712
|
+
|
|
713
|
+
queries.forEach(query => {
|
|
714
|
+
expect(() => {
|
|
715
|
+
sendMessageFunction(query);
|
|
716
|
+
}).not.toThrow();
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
it('Should handle service ref cleanup when it already exists', () => {
|
|
721
|
+
const TestComponent = ({ worksheetId }: { worksheetId: string }) => {
|
|
722
|
+
const { sendMessage } = useSpotterAgent({ worksheetId });
|
|
723
|
+
expect(sendMessage).toBeDefined();
|
|
724
|
+
return <div>Test</div>;
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
const { rerender } = render(<TestComponent worksheetId="worksheet1" />);
|
|
728
|
+
|
|
729
|
+
// This should trigger the "if (serviceRef.current)" branch in useEffect
|
|
730
|
+
rerender(<TestComponent worksheetId="worksheet1" />);
|
|
731
|
+
rerender(<TestComponent worksheetId="worksheet2" />);
|
|
732
|
+
rerender(<TestComponent worksheetId="worksheet3" />);
|
|
733
|
+
|
|
734
|
+
// Multiple rapid changes should exercise the cleanup logic
|
|
735
|
+
for (let i = 0; i < 5; i++) {
|
|
736
|
+
rerender(<TestComponent worksheetId={`worksheet${i}`} />);
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it('Should test various config combinations to hit all branches', () => {
|
|
741
|
+
const testConfigs = [
|
|
742
|
+
{ worksheetId: 'test1' },
|
|
743
|
+
{ worksheetId: 'test2', className: 'custom-class' },
|
|
744
|
+
{ worksheetId: 'test3', hiddenActions: [Action.ReportError] },
|
|
745
|
+
{ worksheetId: 'test4', searchOptions: { searchQuery: 'test' } },
|
|
746
|
+
{ worksheetId: 'test5', insertAsSibling: true },
|
|
747
|
+
{ worksheetId: 'test6', insertAsSibling: false },
|
|
748
|
+
];
|
|
749
|
+
|
|
750
|
+
testConfigs.forEach((config, index) => {
|
|
751
|
+
const TestComponent = () => {
|
|
752
|
+
const { sendMessage } = useSpotterAgent(config);
|
|
753
|
+
expect(sendMessage).toBeDefined();
|
|
754
|
+
return <div>Test {index}</div>;
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
const { unmount } = render(<TestComponent />);
|
|
758
|
+
unmount();
|
|
759
|
+
});
|
|
760
|
+
});
|
|
392
761
|
});
|
|
393
762
|
|
|
394
|
-
describe('
|
|
395
|
-
it('
|
|
396
|
-
|
|
763
|
+
describe('Component Props and Functions', () => {
|
|
764
|
+
it('Should have PreRenderedLiveboardEmbed component', () => {
|
|
765
|
+
expect(PreRenderedLiveboardEmbed).toBeDefined();
|
|
766
|
+
expect(typeof PreRenderedLiveboardEmbed).toBe('object');
|
|
767
|
+
});
|
|
397
768
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
preRenderId="test"
|
|
402
|
-
liveboardId="libId"
|
|
403
|
-
/>,
|
|
404
|
-
);
|
|
769
|
+
it('Should have useInit hook', () => {
|
|
770
|
+
expect(typeof useInit).toBe('function');
|
|
771
|
+
});
|
|
405
772
|
|
|
406
|
-
|
|
407
|
-
|
|
773
|
+
it('Should test basic component factory patterns', () => {
|
|
774
|
+
// Test that components can be created without errors
|
|
775
|
+
expect(() => {
|
|
776
|
+
const TestComponent = () => <div>Test</div>;
|
|
777
|
+
render(<TestComponent />);
|
|
778
|
+
}).not.toThrow();
|
|
779
|
+
});
|
|
780
|
+
});
|
|
408
781
|
|
|
409
|
-
|
|
410
|
-
|
|
782
|
+
describe('Hook Coverage', () => {
|
|
783
|
+
it('Should have useInit function available', () => {
|
|
784
|
+
expect(typeof useInit).toBe('function');
|
|
785
|
+
});
|
|
411
786
|
|
|
412
|
-
|
|
413
|
-
const
|
|
414
|
-
|
|
787
|
+
it('Should test useInit hook basic functionality', () => {
|
|
788
|
+
const TestComponent = () => {
|
|
789
|
+
const authEE = useInit({
|
|
790
|
+
thoughtSpotHost: 'localhost',
|
|
791
|
+
authType: AuthType.None
|
|
792
|
+
});
|
|
793
|
+
expect(authEE).toBeDefined();
|
|
794
|
+
expect(authEE.current).toBeDefined();
|
|
795
|
+
return <div>Test</div>;
|
|
796
|
+
};
|
|
415
797
|
|
|
416
|
-
(
|
|
417
|
-
|
|
418
|
-
observe: jest.fn(),
|
|
419
|
-
unobserve: jest.fn(),
|
|
420
|
-
}));
|
|
421
|
-
const { container: libContainer } = render(
|
|
422
|
-
<LiveboardEmbed
|
|
423
|
-
className="embedClass"
|
|
424
|
-
preRenderId="test"
|
|
425
|
-
liveboardId="libId"
|
|
426
|
-
/>,
|
|
427
|
-
);
|
|
798
|
+
render(<TestComponent />);
|
|
799
|
+
});
|
|
428
800
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
801
|
+
it('Should handle useInit with different config changes', () => {
|
|
802
|
+
const TestComponent = ({ host }: { host: string }) => {
|
|
803
|
+
const authEE = useInit({
|
|
804
|
+
thoughtSpotHost: host,
|
|
805
|
+
authType: AuthType.None
|
|
806
|
+
});
|
|
807
|
+
expect(authEE).toBeDefined();
|
|
808
|
+
return <div>Test</div>;
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const { rerender } = render(<TestComponent host="localhost" />);
|
|
812
|
+
|
|
813
|
+
// Change config to test useDeepCompareEffect
|
|
814
|
+
rerender(<TestComponent host="localhost2" />);
|
|
815
|
+
rerender(<TestComponent host="localhost3" />);
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
it('Should test useInit with complex config objects', () => {
|
|
819
|
+
const TestComponent = () => {
|
|
820
|
+
const authEE = useInit({
|
|
821
|
+
thoughtSpotHost: 'localhost',
|
|
822
|
+
authType: AuthType.None,
|
|
823
|
+
suppressNoCookieAccessAlert: true,
|
|
824
|
+
suppressErrorAlerts: true
|
|
825
|
+
});
|
|
826
|
+
expect(authEE).toBeDefined();
|
|
827
|
+
return <div>Test</div>;
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
render(<TestComponent />);
|
|
432
831
|
});
|
|
433
832
|
});
|
|
434
833
|
});
|