@thoughtspot/visual-embed-sdk 1.37.1-spotter-embed → 1.38.0-alpha.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/README.md +1 -1
- package/cjs/package.json +2 -2
- package/cjs/src/embed/app.d.ts +43 -3
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +40 -7
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +23 -6
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +7 -0
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +8 -3
- package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +5 -2
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.spec.js +286 -1
- package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +5 -3
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +3 -2
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +21 -10
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +6 -4
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +105 -0
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +4 -4
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +5 -3
- 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/react/index.d.ts +32 -3
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +54 -2
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +94 -0
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +25 -51
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +24 -50
- package/cjs/src/types.js.map +1 -1
- package/dist/{index-Cj4BVGHL.js → index-DeFzsyFF.js} +1 -1
- package/dist/{index-DnIvX1FR.js → index-NZYq1Tu3.js} +1 -2
- package/dist/src/embed/app.d.ts +43 -3
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/bodyless-conversation.d.ts +8 -3
- package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +5 -3
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -4
- 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 +32 -3
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +25 -51
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +614 -77
- package/dist/tsembed-react.js +758 -296
- package/dist/tsembed.es.js +153 -75
- package/dist/tsembed.js +297 -295
- package/dist/visual-embed-sdk-react-full.d.ts +194 -145
- package/dist/visual-embed-sdk-react.d.ts +194 -145
- package/dist/visual-embed-sdk.d.ts +82 -61
- package/lib/package.json +2 -2
- package/lib/src/embed/app.d.ts +43 -3
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +39 -6
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +24 -7
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +7 -0
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +8 -3
- package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +5 -2
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.spec.js +287 -2
- package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +5 -3
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +3 -2
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +21 -10
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +6 -4
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +105 -0
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +4 -4
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +4 -4
- 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 +32 -3
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +53 -1
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +96 -2
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +25 -51
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +24 -50
- package/lib/src/types.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +85 -64
- package/package.json +2 -2
- package/src/embed/app.spec.ts +30 -6
- package/src/embed/app.ts +62 -9
- package/src/embed/base.ts +9 -0
- package/src/embed/bodyless-conversation.spec.ts +308 -1
- package/src/embed/bodyless-conversation.ts +13 -3
- package/src/embed/conversation.ts +5 -3
- package/src/embed/liveboard.ts +25 -10
- package/src/embed/ts-embed.spec.ts +130 -0
- package/src/embed/ts-embed.ts +6 -4
- package/src/index.ts +10 -3
- package/src/react/all-types-export.ts +1 -0
- package/src/react/index.spec.tsx +157 -1
- package/src/react/index.tsx +64 -3
- package/src/types.ts +24 -56
- package/cjs/src/pages/embed-test.page.d.ts +0 -8
- package/cjs/src/pages/embed-test.page.d.ts.map +0 -1
- package/cjs/src/pages/embed-test.page.js +0 -20
- package/cjs/src/pages/embed-test.page.js.map +0 -1
- package/cjs/src/pages/home.page.d.ts +0 -6
- package/cjs/src/pages/home.page.d.ts.map +0 -1
- package/cjs/src/pages/home.page.js +0 -12
- package/cjs/src/pages/home.page.js.map +0 -1
- package/cjs/src/pages/login.page.d.ts +0 -15
- package/cjs/src/pages/login.page.d.ts.map +0 -1
- package/cjs/src/pages/login.page.js +0 -22
- package/cjs/src/pages/login.page.js.map +0 -1
- package/cjs/src/tests/auth.test.d.ts +0 -1
- package/cjs/src/tests/auth.test.d.ts.map +0 -1
- package/cjs/src/tests/auth.test.js +0 -1
- package/cjs/src/tests/auth.test.js.map +0 -1
- package/cjs/src/tests/e2e/auth.spec.d.ts +0 -2
- package/cjs/src/tests/e2e/auth.spec.d.ts.map +0 -1
- package/cjs/src/tests/e2e/auth.spec.js +0 -54
- package/cjs/src/tests/e2e/auth.spec.js.map +0 -1
- package/dist/index-DUaG1OG2.js +0 -7447
- package/dist/index-Fhk1V_Gw.js +0 -7371
- package/dist/index-OuiZF3zE.js +0 -7371
package/src/react/index.spec.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from '../test/test-utils';
|
|
17
17
|
import {
|
|
18
18
|
SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed, PreRenderedLiveboardEmbed,
|
|
19
|
+
SpotterAgentEmbed
|
|
19
20
|
} from './index';
|
|
20
21
|
import * as allExports from './index';
|
|
21
22
|
import {
|
|
@@ -235,6 +236,161 @@ describe('React Components', () => {
|
|
|
235
236
|
});
|
|
236
237
|
});
|
|
237
238
|
|
|
239
|
+
describe('SpotterAgentEmbed', () => {
|
|
240
|
+
it('Should work as a React component integrating BodylessConversation', async () => {
|
|
241
|
+
const mockDiv = document.createElement('div');
|
|
242
|
+
|
|
243
|
+
let conversationService: any = null;
|
|
244
|
+
|
|
245
|
+
render(
|
|
246
|
+
<SpotterAgentEmbed
|
|
247
|
+
ref={(instance: any) => {
|
|
248
|
+
conversationService = instance;
|
|
249
|
+
|
|
250
|
+
if (instance) {
|
|
251
|
+
instance.sendMessage = jest.fn().mockResolvedValue({
|
|
252
|
+
container: mockDiv
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}}
|
|
256
|
+
worksheetId="test-worksheet-id"
|
|
257
|
+
/>
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect(conversationService).not.toBeNull();
|
|
261
|
+
|
|
262
|
+
if (conversationService) {
|
|
263
|
+
expect(typeof conversationService.sendMessage).toBe('function');
|
|
264
|
+
|
|
265
|
+
const response = await conversationService.sendMessage("What are my sales this month?");
|
|
266
|
+
expect(response.container).toBe(mockDiv);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('Should work as a React component with ref support', () => {
|
|
271
|
+
const mockSendMessage = jest.fn().mockResolvedValue({
|
|
272
|
+
container: document.createElement('div'),
|
|
273
|
+
viz: {}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const TestComponent = () => {
|
|
277
|
+
const conversationRef = React.useRef(null);
|
|
278
|
+
|
|
279
|
+
const handleClick = () => {
|
|
280
|
+
if (conversationRef.current) {
|
|
281
|
+
conversationRef.current.sendMessage = mockSendMessage;
|
|
282
|
+
|
|
283
|
+
conversationRef.current.sendMessage("Test message");
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
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
|
+
);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const { getByTestId } = render(<TestComponent />);
|
|
301
|
+
|
|
302
|
+
fireEvent.click(getByTestId('test-button'));
|
|
303
|
+
|
|
304
|
+
expect(mockSendMessage).toHaveBeenCalledWith("Test message");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('Should work with the useEmbedRef hook', () => {
|
|
308
|
+
const mockSendMessage = jest.fn().mockResolvedValue({
|
|
309
|
+
container: document.createElement('div'),
|
|
310
|
+
viz: {}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const TestComponent = () => {
|
|
314
|
+
const embedRef = useEmbedRef<typeof SpotterAgentEmbed>();
|
|
315
|
+
|
|
316
|
+
const handleClick = () => {
|
|
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
|
+
);
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const { getByTestId } = render(<TestComponent />);
|
|
342
|
+
|
|
343
|
+
fireEvent.click(getByTestId('use-embed-ref-button'));
|
|
344
|
+
|
|
345
|
+
expect(mockSendMessage).toHaveBeenCalledWith("Test with useEmbedRef");
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('Should work with the className prop', async () => {
|
|
349
|
+
let capturedInstance: any = null;
|
|
350
|
+
|
|
351
|
+
const TestComponent = () => {
|
|
352
|
+
const embedRef = useEmbedRef<typeof SpotterAgentEmbed>();
|
|
353
|
+
|
|
354
|
+
React.useEffect(() => {
|
|
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
|
+
);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
render(<TestComponent />);
|
|
384
|
+
|
|
385
|
+
expect(capturedInstance).not.toBeNull();
|
|
386
|
+
|
|
387
|
+
if (capturedInstance) {
|
|
388
|
+
const result = await capturedInstance.sendMessage("test");
|
|
389
|
+
expect(result.container.className).toBe("embedClass");
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
238
394
|
describe('PreRenderedLiveboardEmbed', () => {
|
|
239
395
|
it('should preRender the liveboard ', async () => {
|
|
240
396
|
const preRenderId = 'tsEmbed-pre-render-wrapper-test';
|
|
@@ -285,7 +441,7 @@ describe('allExports', () => {
|
|
|
285
441
|
it('should not have undefined exports', () => {
|
|
286
442
|
Object.keys(allExports).forEach(
|
|
287
443
|
(exportKey) => expect(
|
|
288
|
-
Boolean(allExports[exportKey]),
|
|
444
|
+
Boolean(allExports[exportKey as keyof typeof allExports]),
|
|
289
445
|
)
|
|
290
446
|
.toBe(true),
|
|
291
447
|
);
|
package/src/react/index.tsx
CHANGED
|
@@ -10,10 +10,11 @@ import { SearchEmbed as _SearchEmbed, SearchViewConfig } from '../embed/search';
|
|
|
10
10
|
import { AppEmbed as _AppEmbed, AppViewConfig } from '../embed/app';
|
|
11
11
|
import { LiveboardEmbed as _LiveboardEmbed, LiveboardViewConfig } from '../embed/liveboard';
|
|
12
12
|
import { TsEmbed } from '../embed/ts-embed';
|
|
13
|
+
import { SpotterAgentEmbed as _SpotterAgentEmbed, SpotterAgentEmbedViewConfig } from '../embed/bodyless-conversation';
|
|
13
14
|
|
|
14
15
|
import { EmbedConfig, EmbedEvent, ViewConfig } from '../types';
|
|
15
16
|
import { EmbedProps, getViewPropsAndListeners } from './util';
|
|
16
|
-
import { SpotterEmbed as _SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed as _ConversationEmbed, ConversationViewConfig
|
|
17
|
+
import { SpotterEmbed as _SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed as _ConversationEmbed, ConversationViewConfig } from '../embed/conversation';
|
|
17
18
|
import { init } from '../embed/base';
|
|
18
19
|
|
|
19
20
|
const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V extends ViewConfig>(
|
|
@@ -23,7 +24,7 @@ const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V exte
|
|
|
23
24
|
// Embed.preRender() method instead of the usual render method, and it will
|
|
24
25
|
// not be destroyed when the component is unmounted.
|
|
25
26
|
isPreRenderedComponent = false,
|
|
26
|
-
) => React.forwardRef<InstanceType<T>, U>(
|
|
27
|
+
) => React.forwardRef<InstanceType<T>, U>(
|
|
27
28
|
(props: U, forwardedRef: React.MutableRefObject<InstanceType<T>>) => {
|
|
28
29
|
const ref = React.useRef<HTMLDivElement>(null);
|
|
29
30
|
const { className, style, ...embedProps } = props;
|
|
@@ -361,7 +362,8 @@ export const SpotterEmbed = componentFactory<
|
|
|
361
362
|
|
|
362
363
|
/**
|
|
363
364
|
* React component for LLM based conversation BI.
|
|
364
|
-
* @deprecated
|
|
365
|
+
* @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
|
|
366
|
+
* Use {@link SpotterEmbed} instead
|
|
365
367
|
* @example
|
|
366
368
|
* ```tsx
|
|
367
369
|
* function Sage() {
|
|
@@ -381,6 +383,64 @@ export const ConversationEmbed = componentFactory<
|
|
|
381
383
|
ConversationViewConfig
|
|
382
384
|
>(_ConversationEmbed);
|
|
383
385
|
|
|
386
|
+
interface SpotterAgentEmbedProps extends EmbedProps, SpotterAgentEmbedViewConfig {}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* React component for SpotterAgent embed, which can be integrated inside
|
|
390
|
+
* chatbots or other conversational interfaces.
|
|
391
|
+
* @example
|
|
392
|
+
* ```tsx
|
|
393
|
+
* function SpotterAgent() {
|
|
394
|
+
* const ref = useRef();
|
|
395
|
+
*
|
|
396
|
+
* const handleSendMessage = async () => {
|
|
397
|
+
* const { container, error } = await ref.current.sendMessage('show me sales by region');
|
|
398
|
+
* if (container) {
|
|
399
|
+
* document.body.appendChild(container);
|
|
400
|
+
* }
|
|
401
|
+
* };
|
|
402
|
+
*
|
|
403
|
+
* return (
|
|
404
|
+
* <div>
|
|
405
|
+
* <SpotterAgentEmbed ref={ref} worksheetId="worksheetId" />
|
|
406
|
+
* <button onClick={handleSendMessage}>Send Message</button>
|
|
407
|
+
* </div>
|
|
408
|
+
* );
|
|
409
|
+
* }
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
export const SpotterAgentEmbed = React.forwardRef<_SpotterAgentEmbed, SpotterAgentEmbedProps>((props, ref) => {
|
|
413
|
+
const { className, ...restProps } = props;
|
|
414
|
+
const serviceRef = useRef<_SpotterAgentEmbed | null>(null);
|
|
415
|
+
|
|
416
|
+
useDeepCompareEffect(() => {
|
|
417
|
+
if (serviceRef.current) {
|
|
418
|
+
serviceRef.current = null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const configProps = {
|
|
422
|
+
...restProps,
|
|
423
|
+
...(className ? { containerClassName: className } : {})
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
serviceRef.current = new _SpotterAgentEmbed(configProps);
|
|
427
|
+
|
|
428
|
+
if (ref) {
|
|
429
|
+
if (typeof ref === 'function') {
|
|
430
|
+
ref(serviceRef.current);
|
|
431
|
+
} else {
|
|
432
|
+
ref.current = serviceRef.current;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return () => {
|
|
437
|
+
serviceRef.current = null;
|
|
438
|
+
};
|
|
439
|
+
}, [props]);
|
|
440
|
+
|
|
441
|
+
return null;
|
|
442
|
+
});
|
|
443
|
+
|
|
384
444
|
/**
|
|
385
445
|
* React component for PreRendered Conversation embed.
|
|
386
446
|
*
|
|
@@ -410,6 +470,7 @@ type EmbedComponent = typeof SearchEmbed
|
|
|
410
470
|
| typeof LiveboardEmbed
|
|
411
471
|
| typeof SearchBarEmbed
|
|
412
472
|
| typeof SageEmbed
|
|
473
|
+
| typeof SpotterAgentEmbed
|
|
413
474
|
| typeof SpotterEmbed
|
|
414
475
|
| typeof ConversationEmbed;
|
|
415
476
|
|
package/src/types.ts
CHANGED
|
@@ -2679,9 +2679,12 @@ export enum HostEvent {
|
|
|
2679
2679
|
* @example
|
|
2680
2680
|
* ```js
|
|
2681
2681
|
* searchEmbed.trigger(HostEvent.OpenFilter,
|
|
2682
|
-
* { columnId: '<column-GUID>', name: 'column name', type: 'INT64', dataType: 'ATTRIBUTE'})
|
|
2682
|
+
* {column: { columnId: '<column-GUID>', name: 'column name', type: 'INT64', dataType: 'ATTRIBUTE'}})
|
|
2683
|
+
* ```
|
|
2684
|
+
* @example
|
|
2685
|
+
* ```js
|
|
2683
2686
|
* LiveboardEmbed.trigger(HostEvent.OpenFilter,
|
|
2684
|
-
*
|
|
2687
|
+
* { column: {columnId: '<column-GUID>'}})
|
|
2685
2688
|
* ```
|
|
2686
2689
|
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl
|
|
2687
2690
|
*/
|
|
@@ -3290,6 +3293,25 @@ export enum HostEvent {
|
|
|
3290
3293
|
* }]
|
|
3291
3294
|
* });
|
|
3292
3295
|
* ```
|
|
3296
|
+
* If there are multiple columns with the same name, consider
|
|
3297
|
+
* using `WORKSHEET_NAME::COLUMN_NAME` format.
|
|
3298
|
+
*
|
|
3299
|
+
* @example
|
|
3300
|
+
*
|
|
3301
|
+
* ```js
|
|
3302
|
+
* liveboardEmbed.trigger(HostEvent.UpdateFilters, {
|
|
3303
|
+
* filters: [{
|
|
3304
|
+
* column: "(Sample) Retail - Apparel::city",
|
|
3305
|
+
* oper: 'IN',
|
|
3306
|
+
* values: ["atlanta"]
|
|
3307
|
+
* },
|
|
3308
|
+
* {
|
|
3309
|
+
* column: "(Sample) Retail - Apparel::Region",
|
|
3310
|
+
* oper: 'IN',
|
|
3311
|
+
* values: ["West","Midwest"]
|
|
3312
|
+
* }]
|
|
3313
|
+
* });
|
|
3314
|
+
* ```
|
|
3293
3315
|
* @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
|
|
3294
3316
|
*/
|
|
3295
3317
|
UpdateFilters = 'updateFilters',
|
|
@@ -3499,60 +3521,6 @@ export enum HostEvent {
|
|
|
3499
3521
|
* @version SDK: 1.37.0 | ThoughtSpot: 10.8.0.cl
|
|
3500
3522
|
*/
|
|
3501
3523
|
TransformTableVizData = 'TransformTableVizData',
|
|
3502
|
-
|
|
3503
|
-
/**
|
|
3504
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3505
|
-
* Includes the following properties:
|
|
3506
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3507
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3508
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3509
|
-
*/
|
|
3510
|
-
SpotterSearch = 'SpotterSearch',
|
|
3511
|
-
|
|
3512
|
-
/**
|
|
3513
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3514
|
-
* Includes the following properties:
|
|
3515
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3516
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3517
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3518
|
-
*/
|
|
3519
|
-
EditLastPrompt = 'EditLastPrompt',
|
|
3520
|
-
|
|
3521
|
-
/**
|
|
3522
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3523
|
-
* Includes the following properties:
|
|
3524
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3525
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3526
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3527
|
-
*/
|
|
3528
|
-
PreviewSpotterData = 'PreviewSpotterData',
|
|
3529
|
-
|
|
3530
|
-
/**
|
|
3531
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3532
|
-
* Includes the following properties:
|
|
3533
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3534
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3535
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3536
|
-
*/
|
|
3537
|
-
ResetSpotterConversation = 'ResetSpotterConversation',
|
|
3538
|
-
|
|
3539
|
-
/**
|
|
3540
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3541
|
-
* Includes the following properties:
|
|
3542
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3543
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3544
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3545
|
-
*/
|
|
3546
|
-
DeleteLastPrompt = 'DeleteLastPrompt',
|
|
3547
|
-
|
|
3548
|
-
/**
|
|
3549
|
-
* Triggers the table visualization re-render with the updated data.
|
|
3550
|
-
* Includes the following properties:
|
|
3551
|
-
* @param - `columnDataLite` - an array of object containing the
|
|
3552
|
-
* data value modifications retrieved from the `EmbedEvent.TableVizRendered`
|
|
3553
|
-
* payload.For example, { columnDataLite: []}`.
|
|
3554
|
-
*/
|
|
3555
|
-
AnswerChartSwitcher = 'answerChartSwitcher',
|
|
3556
3524
|
}
|
|
3557
3525
|
|
|
3558
3526
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embed-test.page.d.ts","sourceRoot":"","sources":["../../../src/pages/embed-test.page.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IACV,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,GAAG;IAEvB,IAAI;IAIJ,kBAAkB;IAIlB,eAAe;CAIxB"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EmbedTestPage = void 0;
|
|
4
|
-
class EmbedTestPage {
|
|
5
|
-
constructor(page) {
|
|
6
|
-
this.page = page;
|
|
7
|
-
}
|
|
8
|
-
async goto() {
|
|
9
|
-
// Implement navigation logic
|
|
10
|
-
}
|
|
11
|
-
async waitForFrameToLoad() {
|
|
12
|
-
// Implement frame load wait logic
|
|
13
|
-
}
|
|
14
|
-
async switchToTSFrame() {
|
|
15
|
-
// Implement frame switching logic
|
|
16
|
-
return this.page;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
exports.EmbedTestPage = EmbedTestPage;
|
|
20
|
-
//# sourceMappingURL=embed-test.page.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embed-test.page.js","sourceRoot":"","sources":["../../../src/pages/embed-test.page.ts"],"names":[],"mappings":";;;AAAA,MAAa,aAAa;IACtB,YAAoB,IAAS;QAAT,SAAI,GAAJ,IAAI,CAAK;IAAG,CAAC;IAEjC,KAAK,CAAC,IAAI;QACN,6BAA6B;IACjC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACpB,kCAAkC;IACtC,CAAC;IAED,KAAK,CAAC,eAAe;QACjB,kCAAkC;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;CACJ;AAfD,sCAeC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"home.page.d.ts","sourceRoot":"","sources":["../../../src/pages/home.page.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACjB,SAAS;;MAEP;CACL"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HomePage = void 0;
|
|
4
|
-
class HomePage {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.selectors = {
|
|
7
|
-
homePage: '[data-testid="home-page"]'
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
exports.HomePage = HomePage;
|
|
12
|
-
//# sourceMappingURL=home.page.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"home.page.js","sourceRoot":"","sources":["../../../src/pages/home.page.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAQ;IAArB;QACI,cAAS,GAAG;YACR,QAAQ,EAAE,2BAA2B;SACxC,CAAC;IACN,CAAC;CAAA;AAJD,4BAIC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export declare class LoginPage {
|
|
2
|
-
private page;
|
|
3
|
-
selectors: {
|
|
4
|
-
userAvatar: string;
|
|
5
|
-
signOutButtonInProfileMenu: string;
|
|
6
|
-
loginPageLogo: string;
|
|
7
|
-
};
|
|
8
|
-
utils: {
|
|
9
|
-
getRandomName: () => string;
|
|
10
|
-
getStrongPassword: () => string;
|
|
11
|
-
};
|
|
12
|
-
constructor(page: any);
|
|
13
|
-
loginAsUser(username: string, password: string): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=login.page.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"login.page.d.ts","sourceRoot":"","sources":["../../../src/pages/login.page.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAS;IAYN,OAAO,CAAC,IAAI;IAXxB,SAAS;;;;MAIP;IAEF,KAAK;;;MAGH;gBAEkB,IAAI,EAAE,GAAG;IAEvB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAGvD"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LoginPage = void 0;
|
|
4
|
-
class LoginPage {
|
|
5
|
-
constructor(page) {
|
|
6
|
-
this.page = page;
|
|
7
|
-
this.selectors = {
|
|
8
|
-
userAvatar: '[data-testid="user-avatar"]',
|
|
9
|
-
signOutButtonInProfileMenu: '[data-testid="sign-out-button"]',
|
|
10
|
-
loginPageLogo: '[data-testid="login-logo"]'
|
|
11
|
-
};
|
|
12
|
-
this.utils = {
|
|
13
|
-
getRandomName: () => `testUser${Math.random().toString(36).substring(7)}`,
|
|
14
|
-
getStrongPassword: () => 'Test@123'
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
async loginAsUser(username, password) {
|
|
18
|
-
// Implement login logic here
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.LoginPage = LoginPage;
|
|
22
|
-
//# sourceMappingURL=login.page.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"login.page.js","sourceRoot":"","sources":["../../../src/pages/login.page.ts"],"names":[],"mappings":";;;AAAA,MAAa,SAAS;IAYlB,YAAoB,IAAS;QAAT,SAAI,GAAJ,IAAI,CAAK;QAX7B,cAAS,GAAG;YACR,UAAU,EAAE,6BAA6B;YACzC,0BAA0B,EAAE,iCAAiC;YAC7D,aAAa,EAAE,4BAA4B;SAC9C,CAAC;QAEF,UAAK,GAAG;YACJ,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YACzE,iBAAiB,EAAE,GAAG,EAAE,CAAC,UAAU;SACtC,CAAC;IAE8B,CAAC;IAEjC,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,QAAgB;QAChD,6BAA6B;IACjC,CAAC;CACJ;AAjBD,8BAiBC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=auth.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.test.d.ts","sourceRoot":"","sources":["../../../src/tests/auth.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=auth.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../../src/tests/auth.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.spec.d.ts","sourceRoot":"","sources":["../../../../src/tests/e2e/auth.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const login_page_1 = require("src/pages/login.page");
|
|
5
|
-
const home_page_1 = require("src/pages/home.page");
|
|
6
|
-
const embed_test_page_1 = require("src/pages/embed-test.page");
|
|
7
|
-
test_1.test.describe('Authentication flows', () => {
|
|
8
|
-
let loginPage;
|
|
9
|
-
let homePage;
|
|
10
|
-
let embedTestPage;
|
|
11
|
-
test_1.test.beforeEach(async ({ page }) => {
|
|
12
|
-
loginPage = new login_page_1.LoginPage(page);
|
|
13
|
-
homePage = new home_page_1.HomePage();
|
|
14
|
-
embedTestPage = new embed_test_page_1.EmbedTestPage(page);
|
|
15
|
-
await embedTestPage.goto();
|
|
16
|
-
});
|
|
17
|
-
(0, test_1.test)('should handle logout and login sequence correctly', async () => {
|
|
18
|
-
// Wait for initial load
|
|
19
|
-
await embedTestPage.waitForFrameToLoad();
|
|
20
|
-
const frameLoc = await embedTestPage.switchToTSFrame();
|
|
21
|
-
// Verify user is logged in
|
|
22
|
-
await (0, test_1.expect)(frameLoc.locator(homePage.selectors.homePage)).toBeVisible();
|
|
23
|
-
// Perform logout
|
|
24
|
-
await frameLoc.locator(loginPage.selectors.userAvatar).click();
|
|
25
|
-
await frameLoc.locator(loginPage.selectors.signOutButtonInProfileMenu).click();
|
|
26
|
-
// Verify logout
|
|
27
|
-
await (0, test_1.expect)(frameLoc.locator(loginPage.selectors.loginPageLogo)).toBeVisible();
|
|
28
|
-
// Perform login with new credentials
|
|
29
|
-
const username = loginPage.utils.getRandomName();
|
|
30
|
-
const password = loginPage.utils.getStrongPassword();
|
|
31
|
-
await loginPage.loginAsUser(username, password);
|
|
32
|
-
// Verify successful login
|
|
33
|
-
await (0, test_1.expect)(frameLoc.locator(homePage.selectors.homePage)).toBeVisible();
|
|
34
|
-
await (0, test_1.expect)(frameLoc.locator(loginPage.selectors.userAvatar)).toBeVisible();
|
|
35
|
-
});
|
|
36
|
-
(0, test_1.test)('should handle multiple logout-login cycles', async () => {
|
|
37
|
-
await embedTestPage.waitForFrameToLoad();
|
|
38
|
-
const frameLoc = await embedTestPage.switchToTSFrame();
|
|
39
|
-
// First cycle
|
|
40
|
-
await (0, test_1.expect)(frameLoc.locator(homePage.selectors.homePage)).toBeVisible();
|
|
41
|
-
await frameLoc.locator(loginPage.selectors.userAvatar).click();
|
|
42
|
-
await frameLoc.locator(loginPage.selectors.signOutButtonInProfileMenu).click();
|
|
43
|
-
await (0, test_1.expect)(frameLoc.locator(loginPage.selectors.loginPageLogo)).toBeVisible();
|
|
44
|
-
await loginPage.loginAsUser(loginPage.utils.getRandomName(), loginPage.utils.getStrongPassword());
|
|
45
|
-
await (0, test_1.expect)(frameLoc.locator(homePage.selectors.homePage)).toBeVisible();
|
|
46
|
-
// Second cycle
|
|
47
|
-
await frameLoc.locator(loginPage.selectors.userAvatar).click();
|
|
48
|
-
await frameLoc.locator(loginPage.selectors.signOutButtonInProfileMenu).click();
|
|
49
|
-
await (0, test_1.expect)(frameLoc.locator(loginPage.selectors.loginPageLogo)).toBeVisible();
|
|
50
|
-
await loginPage.loginAsUser(loginPage.utils.getRandomName(), loginPage.utils.getStrongPassword());
|
|
51
|
-
await (0, test_1.expect)(frameLoc.locator(homePage.selectors.homePage)).toBeVisible();
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
//# sourceMappingURL=auth.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.spec.js","sourceRoot":"","sources":["../../../../src/tests/e2e/auth.spec.ts"],"names":[],"mappings":"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"}
|