@thoughtspot/visual-embed-sdk 1.50.0 → 1.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/package.json +1 -1
- package/cjs/src/css-variables.d.ts +95 -0
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +136 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +59 -37
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +419 -149
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +230 -1
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +30 -16
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +221 -17
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/events.spec.js +635 -0
- package/cjs/src/embed/events.spec.js.map +1 -1
- package/cjs/src/embed/host-events.spec.js +151 -0
- package/cjs/src/embed/host-events.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.js +11 -1
- package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.js +9 -0
- package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js +218 -0
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.d.ts +2 -0
- package/cjs/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.js +32 -2
- package/cjs/src/embed/hostEventClient/utils.js.map +1 -1
- package/cjs/src/embed/hostEventClient/utils.spec.js +178 -0
- package/cjs/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +42 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +26 -6
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +83 -2
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/spotter-utils.d.ts +8 -1
- package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-utils.js +14 -1
- package/cjs/src/embed/spotter-utils.js.map +1 -1
- package/cjs/src/embed/spotter-utils.spec.js +61 -0
- package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.d.ts +34 -0
- package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.spec.js +17 -0
- package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +29 -7
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +146 -0
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.d.ts +1 -0
- package/cjs/src/errors.d.ts.map +1 -1
- package/cjs/src/errors.js +1 -0
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +2 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +3 -2
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/mixpanel-service.d.ts +4 -0
- package/cjs/src/mixpanel-service.d.ts.map +1 -1
- package/cjs/src/mixpanel-service.js +4 -0
- package/cjs/src/mixpanel-service.js.map +1 -1
- package/cjs/src/react/util.spec.js +251 -0
- package/cjs/src/react/util.spec.js.map +1 -1
- package/cjs/src/types.d.ts +573 -11
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +519 -2
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/processData.spec.js +93 -0
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/cjs/src/utils/processTrigger.spec.js +61 -0
- package/cjs/src/utils/processTrigger.spec.js.map +1 -1
- package/dist/{index-B5xoN6Cp.js → index-aBzH5ZwF.js} +1 -1
- package/dist/src/css-variables.d.ts +95 -0
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +136 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +230 -1
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/utils.d.ts +2 -0
- package/dist/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +42 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/spotter-utils.d.ts +8 -1
- package/dist/src/embed/spotter-utils.d.ts.map +1 -1
- package/dist/src/embed/spotter-viz-utils.d.ts +34 -0
- package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/mixpanel-service.d.ts +4 -0
- package/dist/src/mixpanel-service.d.ts.map +1 -1
- package/dist/src/types.d.ts +573 -11
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +936 -142
- package/dist/tsembed-react.js +935 -141
- package/dist/tsembed.es.js +935 -142
- package/dist/tsembed.js +933 -140
- package/dist/visual-embed-sdk-react-full.d.ts +1147 -44
- package/dist/visual-embed-sdk-react.d.ts +1153 -46
- package/dist/visual-embed-sdk.d.ts +1161 -46
- package/lib/package.json +1 -1
- package/lib/src/css-variables.d.ts +95 -0
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +136 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +60 -38
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +420 -150
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +230 -1
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +31 -17
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +222 -18
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/events.spec.js +635 -0
- package/lib/src/embed/events.spec.js.map +1 -1
- package/lib/src/embed/host-events.spec.js +152 -1
- package/lib/src/embed/host-events.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.d.ts +51 -14
- package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.js +10 -0
- package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.d.ts +1 -0
- package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.js +10 -1
- package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.spec.js +218 -0
- package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/utils.d.ts +2 -0
- package/lib/src/embed/hostEventClient/utils.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/utils.js +28 -1
- package/lib/src/embed/hostEventClient/utils.js.map +1 -1
- package/lib/src/embed/hostEventClient/utils.spec.js +179 -1
- package/lib/src/embed/hostEventClient/utils.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +42 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +26 -6
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +83 -2
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/spotter-utils.d.ts +8 -1
- package/lib/src/embed/spotter-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-utils.js +12 -0
- package/lib/src/embed/spotter-utils.js.map +1 -1
- package/lib/src/embed/spotter-utils.spec.js +62 -1
- package/lib/src/embed/spotter-utils.spec.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.d.ts +34 -0
- package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-viz-utils.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.spec.js +17 -0
- package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +29 -7
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +146 -0
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts +1 -0
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js +1 -0
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +2 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/mixpanel-service.d.ts +4 -0
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +4 -0
- package/lib/src/mixpanel-service.js.map +1 -1
- package/lib/src/react/util.spec.js +251 -0
- package/lib/src/react/util.spec.js.map +1 -1
- package/lib/src/types.d.ts +573 -11
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +519 -2
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/processData.spec.js +93 -0
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/utils/processTrigger.spec.js +61 -0
- package/lib/src/utils/processTrigger.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +1161 -46
- package/package.json +1 -1
- package/src/css-variables.ts +118 -0
- package/src/embed/app.spec.ts +530 -183
- package/src/embed/app.ts +209 -66
- package/src/embed/conversation.spec.ts +275 -21
- package/src/embed/conversation.ts +262 -17
- package/src/embed/events.spec.ts +757 -1
- package/src/embed/host-events.spec.ts +194 -0
- package/src/embed/hostEventClient/contracts.ts +57 -14
- package/src/embed/hostEventClient/host-event-client.spec.ts +338 -0
- package/src/embed/hostEventClient/host-event-client.ts +16 -0
- package/src/embed/hostEventClient/utils.spec.ts +204 -0
- package/src/embed/hostEventClient/utils.ts +37 -10
- package/src/embed/liveboard.spec.ts +108 -2
- package/src/embed/liveboard.ts +82 -14
- package/src/embed/spotter-utils.spec.ts +68 -1
- package/src/embed/spotter-utils.ts +16 -1
- package/src/embed/spotter-viz-utils.spec.ts +17 -0
- package/src/embed/spotter-viz-utils.ts +34 -0
- package/src/embed/ts-embed.spec.ts +186 -0
- package/src/embed/ts-embed.ts +30 -4
- package/src/errors.ts +1 -0
- package/src/index.ts +3 -1
- package/src/mixpanel-service.ts +4 -0
- package/src/react/util.spec.tsx +255 -0
- package/src/types.ts +575 -8
- package/src/utils/processData.spec.ts +97 -0
- package/src/utils/processTrigger.spec.ts +91 -0
package/src/embed/liveboard.ts
CHANGED
|
@@ -402,11 +402,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
402
402
|
/**
|
|
403
403
|
* Enables the 'what you see is what you get' PDF export for Liveboards. Each tab is rendered on a single page
|
|
404
404
|
* following the exact UI layout, instead of splitting visualizations across multiple A4 pages.
|
|
405
|
-
* This feature is GA from version
|
|
405
|
+
* This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.8.0.cl.
|
|
406
406
|
*
|
|
407
407
|
* Supported embed types: `AppEmbed`, `LiveboardEmbed`
|
|
408
408
|
* @type {boolean}
|
|
409
409
|
* @version SDK: 1.48.0 | ThoughtSpot: 26.5.0.cl
|
|
410
|
+
* @default true
|
|
410
411
|
* @example
|
|
411
412
|
* ```js
|
|
412
413
|
* // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
|
|
@@ -419,10 +420,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
419
420
|
isContinuousLiveboardPDFEnabled?: boolean;
|
|
420
421
|
/**
|
|
421
422
|
* This flag is used to enable/disable the XLSX/CSV download option for Liveboards
|
|
423
|
+
* This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.6.0.cl.
|
|
422
424
|
*
|
|
423
425
|
* Supported embed types: `AppEmbed`, `LiveboardEmbed`
|
|
424
426
|
* @type {boolean}
|
|
425
427
|
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
|
|
428
|
+
* @default true
|
|
426
429
|
* @example
|
|
427
430
|
* ```js
|
|
428
431
|
* // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
|
|
@@ -435,10 +438,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
435
438
|
isLiveboardXLSXCSVDownloadEnabled?: boolean;
|
|
436
439
|
/**
|
|
437
440
|
* This flag is used to enable/disable the granular XLSX/CSV schedules feature
|
|
441
|
+
* This feature is GA from SDK version 1.51.0 and ThoughtSpot version 26.6.0.cl.
|
|
438
442
|
*
|
|
439
443
|
* Supported embed types: `AppEmbed`, `LiveboardEmbed`
|
|
440
444
|
* @type {boolean}
|
|
441
445
|
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
|
|
446
|
+
* @default true
|
|
442
447
|
* @example
|
|
443
448
|
* ```js
|
|
444
449
|
* // Replace <EmbedComponent> with embed component name. For example, AppEmbed or LiveboardEmbed
|
|
@@ -529,6 +534,21 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
529
534
|
* ```
|
|
530
535
|
*/
|
|
531
536
|
updatedSpotterChatPrompt?: boolean;
|
|
537
|
+
/**
|
|
538
|
+
* showSpotterRadiance : Controls the radiance on the Spotter page.
|
|
539
|
+
*
|
|
540
|
+
* Supported embed types: `LiveboardEmbed`
|
|
541
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
542
|
+
* @default false
|
|
543
|
+
* @example
|
|
544
|
+
* ```js
|
|
545
|
+
* const embed = new LiveboardEmbed('#tsEmbed', {
|
|
546
|
+
* ... //other embed view config
|
|
547
|
+
* showSpotterRadiance : true,
|
|
548
|
+
* })
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
showSpotterRadiance?: boolean;
|
|
532
552
|
/**
|
|
533
553
|
* Enables the stop answer generation button in the Spotter embed UI,
|
|
534
554
|
* allowing users to interrupt an ongoing answer generation.
|
|
@@ -580,6 +600,12 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
580
600
|
* { label: 'Tip', text: 'try asking about revenue by region' },
|
|
581
601
|
* { label: 'Tip', text: 'use natural language' },
|
|
582
602
|
* ],
|
|
603
|
+
* // liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText require SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
604
|
+
* liveboardBrandName: 'Reports',
|
|
605
|
+
* spotterBrandName: 'Analyst',
|
|
606
|
+
* insightTileBrandName: 'Insight card',
|
|
607
|
+
* insightTileViewPlanLabel: 'View plan',
|
|
608
|
+
* insightTileLoaderText: 'Generating insight',
|
|
583
609
|
* },
|
|
584
610
|
* })
|
|
585
611
|
* ```
|
|
@@ -598,6 +624,21 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
|
|
|
598
624
|
* ```
|
|
599
625
|
*/
|
|
600
626
|
enableLiveboardDataCache?: boolean;
|
|
627
|
+
/**
|
|
628
|
+
* updatedSpotterExperience : Controls the updated Spotter experience.
|
|
629
|
+
*
|
|
630
|
+
* Supported embed types: `LiveboardEmbed`
|
|
631
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
632
|
+
* @default false
|
|
633
|
+
* @example
|
|
634
|
+
* ```js
|
|
635
|
+
* const embed = new LiveboardEmbed('#tsEmbed', {
|
|
636
|
+
* ... //other embed view config
|
|
637
|
+
* updatedSpotterExperience : true,
|
|
638
|
+
* })
|
|
639
|
+
* ```
|
|
640
|
+
*/
|
|
641
|
+
updatedSpotterExperience?: boolean;
|
|
601
642
|
}
|
|
602
643
|
|
|
603
644
|
/**
|
|
@@ -673,34 +714,37 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
673
714
|
showLiveboardDescription,
|
|
674
715
|
showLiveboardTitle,
|
|
675
716
|
isLiveboardHeaderSticky = true,
|
|
676
|
-
isLiveboardCompactHeaderEnabled
|
|
717
|
+
isLiveboardCompactHeaderEnabled,
|
|
677
718
|
showLiveboardVerifiedBadge = true,
|
|
678
719
|
showLiveboardReverifyBanner = true,
|
|
679
|
-
hideIrrelevantChipsInLiveboardTabs
|
|
720
|
+
hideIrrelevantChipsInLiveboardTabs,
|
|
680
721
|
showMaskedFilterChip = false,
|
|
681
|
-
isLiveboardMasterpiecesEnabled
|
|
722
|
+
isLiveboardMasterpiecesEnabled,
|
|
682
723
|
newChartsLibrary,
|
|
683
|
-
isEnhancedFilterInteractivityEnabled
|
|
724
|
+
isEnhancedFilterInteractivityEnabled,
|
|
684
725
|
enableAskSage,
|
|
685
726
|
enable2ColumnLayout,
|
|
686
727
|
dataPanelV2 = true,
|
|
728
|
+
updatedSpotterExperience,
|
|
687
729
|
enableCustomColumnGroups = false,
|
|
688
730
|
oAuthPollingInterval,
|
|
689
731
|
isForceRedirect,
|
|
690
732
|
dataSourceId,
|
|
691
|
-
coverAndFilterOptionInPDF
|
|
733
|
+
coverAndFilterOptionInPDF,
|
|
692
734
|
isLiveboardStylingAndGroupingEnabled,
|
|
693
735
|
isPNGInScheduledEmailsEnabled = false,
|
|
694
|
-
isLiveboardXLSXCSVDownloadEnabled
|
|
695
|
-
isGranularXLSXCSVSchedulesEnabled
|
|
736
|
+
isLiveboardXLSXCSVDownloadEnabled,
|
|
737
|
+
isGranularXLSXCSVSchedulesEnabled,
|
|
696
738
|
showSpotterLimitations,
|
|
697
739
|
isCentralizedLiveboardFilterUXEnabled = false,
|
|
740
|
+
isScopedLiveboardFilteringEnabled,
|
|
698
741
|
isLinkParametersEnabled,
|
|
699
742
|
updatedSpotterChatPrompt,
|
|
743
|
+
showSpotterRadiance,
|
|
700
744
|
enableStopAnswerGenerationEmbed,
|
|
701
745
|
spotterChatConfig,
|
|
702
746
|
isThisPeriodInDateFiltersEnabled,
|
|
703
|
-
isContinuousLiveboardPDFEnabled
|
|
747
|
+
isContinuousLiveboardPDFEnabled,
|
|
704
748
|
enableLiveboardDataCache,
|
|
705
749
|
} = this.viewConfig;
|
|
706
750
|
|
|
@@ -726,6 +770,9 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
726
770
|
if (!isUndefined(updatedSpotterChatPrompt)) {
|
|
727
771
|
params[Param.UpdatedSpotterChatPrompt] = !!updatedSpotterChatPrompt;
|
|
728
772
|
}
|
|
773
|
+
if (!isUndefined(showSpotterRadiance)) {
|
|
774
|
+
params[Param.ShowSpotterRadiance] = !!showSpotterRadiance;
|
|
775
|
+
}
|
|
729
776
|
if (!isUndefined(enableStopAnswerGenerationEmbed)) {
|
|
730
777
|
params[Param.EnableStopAnswerGenerationEmbed] = !!enableStopAnswerGenerationEmbed;
|
|
731
778
|
}
|
|
@@ -790,6 +837,10 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
790
837
|
params[Param.ShowSpotterLimitations] = showSpotterLimitations;
|
|
791
838
|
}
|
|
792
839
|
|
|
840
|
+
if (!isUndefined(updatedSpotterExperience)) {
|
|
841
|
+
params[Param.UpdatedSpotterExperience] = !!updatedSpotterExperience;
|
|
842
|
+
}
|
|
843
|
+
|
|
793
844
|
// Handle spotterChatConfig params
|
|
794
845
|
if (spotterChatConfig) {
|
|
795
846
|
const {
|
|
@@ -823,6 +874,12 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
823
874
|
] = isCentralizedLiveboardFilterUXEnabled;
|
|
824
875
|
}
|
|
825
876
|
|
|
877
|
+
if (isScopedLiveboardFilteringEnabled !== undefined) {
|
|
878
|
+
params[
|
|
879
|
+
Param.isScopedLiveboardFilteringEnabled
|
|
880
|
+
] = isScopedLiveboardFilteringEnabled;
|
|
881
|
+
}
|
|
882
|
+
|
|
826
883
|
if (isThisPeriodInDateFiltersEnabled !== undefined) {
|
|
827
884
|
params[Param.IsThisPeriodInDateFiltersEnabled] = isThisPeriodInDateFiltersEnabled;
|
|
828
885
|
}
|
|
@@ -840,16 +897,27 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
840
897
|
}
|
|
841
898
|
|
|
842
899
|
params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
|
|
843
|
-
|
|
900
|
+
if (!isUndefined(isLiveboardCompactHeaderEnabled)) {
|
|
901
|
+
params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
|
|
902
|
+
}
|
|
844
903
|
params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
|
|
845
904
|
params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
|
|
846
|
-
|
|
905
|
+
if (!isUndefined(hideIrrelevantChipsInLiveboardTabs)) {
|
|
906
|
+
params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
|
|
907
|
+
}
|
|
847
908
|
params[Param.ShowMaskedFilterChip] = showMaskedFilterChip;
|
|
848
|
-
|
|
849
|
-
|
|
909
|
+
if (!isUndefined(isLiveboardMasterpiecesEnabled)) {
|
|
910
|
+
params[Param.IsLiveboardMasterpiecesEnabled] = isLiveboardMasterpiecesEnabled;
|
|
911
|
+
}
|
|
912
|
+
if (!isUndefined(isEnhancedFilterInteractivityEnabled)) {
|
|
913
|
+
params[Param.IsEnhancedFilterInteractivityEnabled] =
|
|
914
|
+
isEnhancedFilterInteractivityEnabled;
|
|
915
|
+
}
|
|
850
916
|
params[Param.DataPanelV2Enabled] = dataPanelV2;
|
|
851
917
|
params[Param.EnableCustomColumnGroups] = enableCustomColumnGroups;
|
|
852
|
-
|
|
918
|
+
if (!isUndefined(coverAndFilterOptionInPDF)) {
|
|
919
|
+
params[Param.CoverAndFilterOptionInPDF] = coverAndFilterOptionInPDF;
|
|
920
|
+
}
|
|
853
921
|
|
|
854
922
|
const queryParams = getQueryParamString(params, true);
|
|
855
923
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
resolveEnablePastConversationsSidebar,
|
|
3
|
+
buildSpotterSidebarAppInitData,
|
|
4
|
+
buildSpotterShareConversationAppInitData,
|
|
5
|
+
} from './spotter-utils';
|
|
2
6
|
import { ErrorDetailsTypes, EmbedErrorCodes } from '../types';
|
|
3
7
|
import { ERROR_MESSAGE } from '../errors';
|
|
4
8
|
|
|
@@ -36,6 +40,22 @@ describe('buildSpotterSidebarAppInitData', () => {
|
|
|
36
40
|
});
|
|
37
41
|
});
|
|
38
42
|
|
|
43
|
+
it('forwards a nested spotterChatPinConfig object through untouched', () => {
|
|
44
|
+
const spotterChatPinConfig = {
|
|
45
|
+
enabled: true,
|
|
46
|
+
pinLabel: 'Pin to top',
|
|
47
|
+
unpinLabel: 'Unpin',
|
|
48
|
+
};
|
|
49
|
+
const result = buildSpotterSidebarAppInitData(base, {
|
|
50
|
+
spotterSidebarConfig: {
|
|
51
|
+
enablePastConversationsSidebar: true,
|
|
52
|
+
spotterChatPinConfig,
|
|
53
|
+
},
|
|
54
|
+
}, noopError);
|
|
55
|
+
expect(result.embedParams?.spotterSidebarConfig?.spotterChatPinConfig)
|
|
56
|
+
.toEqual(spotterChatPinConfig);
|
|
57
|
+
});
|
|
58
|
+
|
|
39
59
|
it('promotes standalone flag into spotterSidebarConfig.enablePastConversationsSidebar', () => {
|
|
40
60
|
const result = buildSpotterSidebarAppInitData(base, { enablePastConversationsSidebar: true }, noopError);
|
|
41
61
|
expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
|
|
@@ -106,3 +126,50 @@ describe('buildSpotterSidebarAppInitData', () => {
|
|
|
106
126
|
expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
|
|
107
127
|
});
|
|
108
128
|
});
|
|
129
|
+
|
|
130
|
+
describe('buildSpotterShareConversationAppInitData', () => {
|
|
131
|
+
const base = { type: 'APP_INIT' } as any;
|
|
132
|
+
|
|
133
|
+
it('returns base unchanged when no spotterShareConversationConfig', () => {
|
|
134
|
+
const result = buildSpotterShareConversationAppInitData(base, {});
|
|
135
|
+
expect(result).toBe(base);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('nests spotterShareConversationConfig under embedParams', () => {
|
|
139
|
+
const result = buildSpotterShareConversationAppInitData(base, {
|
|
140
|
+
spotterShareConversationConfig: { enableShareConversation: true },
|
|
141
|
+
});
|
|
142
|
+
expect(result.embedParams?.spotterShareConversationConfig).toEqual({
|
|
143
|
+
enableShareConversation: true,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('passes label override fields through untouched', () => {
|
|
148
|
+
const spotterShareConversationConfig = {
|
|
149
|
+
enableShareConversation: true,
|
|
150
|
+
spotterShareLabel: 'Share',
|
|
151
|
+
spotterShareModalTitle: 'Share conversation',
|
|
152
|
+
spotterShareConfirmLabel: 'Share',
|
|
153
|
+
spotterShareCancelLabel: 'Cancel',
|
|
154
|
+
spotterShareAddUsersLabel: 'Add users or groups',
|
|
155
|
+
spotterShareEmptyTitle: 'No users added yet',
|
|
156
|
+
spotterShareEmptySubtitle: 'Not shared with any user',
|
|
157
|
+
spotterShareIncludeNewMessagesLabel: 'Include new messages',
|
|
158
|
+
spotterShareUpToCurrentLabel: 'Share up to current moment',
|
|
159
|
+
spotterShareStaleInfoLabel: 'This snapshot may be stale',
|
|
160
|
+
};
|
|
161
|
+
const result = buildSpotterShareConversationAppInitData(base, {
|
|
162
|
+
spotterShareConversationConfig,
|
|
163
|
+
});
|
|
164
|
+
expect(result.embedParams?.spotterShareConversationConfig).toEqual(spotterShareConversationConfig);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('preserves existing embedParams when nesting the share config', () => {
|
|
168
|
+
const withParams = { type: 'APP_INIT', embedParams: { existing: 'keep' } } as any;
|
|
169
|
+
const result = buildSpotterShareConversationAppInitData(withParams, {
|
|
170
|
+
spotterShareConversationConfig: { enableShareConversation: true },
|
|
171
|
+
});
|
|
172
|
+
expect(result.embedParams?.existing).toBe('keep');
|
|
173
|
+
expect(result.embedParams?.spotterShareConversationConfig?.enableShareConversation).toBe(true);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DefaultAppInitData, ErrorDetailsTypes, EmbedErrorCodes } from '../types';
|
|
2
2
|
import { validateHttpUrl } from '../utils';
|
|
3
3
|
import { ERROR_MESSAGE } from '../errors';
|
|
4
|
-
import type { SpotterSidebarViewConfig } from './conversation';
|
|
4
|
+
import type { SpotterSidebarViewConfig, SpotterShareConversationConfig } from './conversation';
|
|
5
5
|
import type { VisualizationOverrides } from '../types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -79,3 +79,18 @@ export function buildSpotterSidebarAppInitData<T extends DefaultAppInitData>(
|
|
|
79
79
|
},
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
export function buildSpotterShareConversationAppInitData<T extends DefaultAppInitData>(
|
|
84
|
+
initData: T,
|
|
85
|
+
viewConfig: { spotterShareConversationConfig?: SpotterShareConversationConfig },
|
|
86
|
+
): T & { embedParams?: { spotterShareConversationConfig?: SpotterShareConversationConfig } } {
|
|
87
|
+
const { spotterShareConversationConfig } = viewConfig;
|
|
88
|
+
if (!spotterShareConversationConfig) return initData;
|
|
89
|
+
return {
|
|
90
|
+
...initData,
|
|
91
|
+
embedParams: {
|
|
92
|
+
...((initData as T & { embedParams?: Record<string, unknown> }).embedParams || {}),
|
|
93
|
+
spotterShareConversationConfig,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -20,6 +20,23 @@ describe('buildSpotterVizAppInitData', () => {
|
|
|
20
20
|
expect(result.embedParams?.spotterVizConfig?.brandHeadline).toBe("Hi, there! I'm");
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
+
it('passes liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText through spotterVizConfig', () => {
|
|
24
|
+
const spotterViz = {
|
|
25
|
+
brandName: 'MyBrand',
|
|
26
|
+
liveboardBrandName: 'Reports',
|
|
27
|
+
spotterBrandName: 'Analyst',
|
|
28
|
+
insightTileBrandName: 'Insight card',
|
|
29
|
+
insightTileViewPlanLabel: 'View plan',
|
|
30
|
+
insightTileLoaderText: 'Generating insight',
|
|
31
|
+
};
|
|
32
|
+
const result = buildSpotterVizAppInitData(base, { spotterViz });
|
|
33
|
+
expect(result.embedParams?.spotterVizConfig?.liveboardBrandName).toBe('Reports');
|
|
34
|
+
expect(result.embedParams?.spotterVizConfig?.spotterBrandName).toBe('Analyst');
|
|
35
|
+
expect(result.embedParams?.spotterVizConfig?.insightTileBrandName).toBe('Insight card');
|
|
36
|
+
expect(result.embedParams?.spotterVizConfig?.insightTileViewPlanLabel).toBe('View plan');
|
|
37
|
+
expect(result.embedParams?.spotterVizConfig?.insightTileLoaderText).toBe('Generating insight');
|
|
38
|
+
});
|
|
39
|
+
|
|
23
40
|
it('preserves existing embedParams when adding spotterVizConfig', () => {
|
|
24
41
|
const existing = { ...base, embedParams: { spotterSidebarConfig: { enablePastConversationsSidebar: true } } };
|
|
25
42
|
const spotterViz = { brandName: 'MyBrand' };
|
|
@@ -38,6 +38,12 @@ export interface SpotterVizStarterPrompt {
|
|
|
38
38
|
* { label: 'Tip', text: 'try asking about revenue by region' },
|
|
39
39
|
* { label: 'Tip', text: 'use natural language' },
|
|
40
40
|
* ],
|
|
41
|
+
* // liveboardBrandName, spotterBrandName, insightTileBrandName, insightTileViewPlanLabel and insightTileLoaderText require SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
42
|
+
* liveboardBrandName: 'Reports',
|
|
43
|
+
* spotterBrandName: 'Analyst',
|
|
44
|
+
* insightTileBrandName: 'Insight card',
|
|
45
|
+
* insightTileViewPlanLabel: 'View plan',
|
|
46
|
+
* insightTileLoaderText: 'Generating insight',
|
|
41
47
|
* },
|
|
42
48
|
* })
|
|
43
49
|
* ```
|
|
@@ -94,6 +100,34 @@ export interface SpotterVizConfig {
|
|
|
94
100
|
* @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
|
|
95
101
|
*/
|
|
96
102
|
loaderTips?: SpotterVizLoaderTip[];
|
|
103
|
+
/**
|
|
104
|
+
* Custom term used to replace "Liveboard" in the agent's responses.
|
|
105
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
106
|
+
* @default ''
|
|
107
|
+
*/
|
|
108
|
+
liveboardBrandName?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Custom term used to replace "Spotter" in the agent's responses.
|
|
111
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
112
|
+
* @default ''
|
|
113
|
+
*/
|
|
114
|
+
spotterBrandName?: string;
|
|
115
|
+
/**
|
|
116
|
+
* Custom term used to replace "Insight tile" in the UI and in the agent's responses.
|
|
117
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
118
|
+
* @default ''
|
|
119
|
+
*/
|
|
120
|
+
insightTileBrandName?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Custom term used to replace "View plan" in the insight tile menu.
|
|
123
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
124
|
+
*/
|
|
125
|
+
insightTileViewPlanLabel?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Custom loader text shown on the insight tile.
|
|
128
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
129
|
+
*/
|
|
130
|
+
insightTileLoaderText?: string;
|
|
97
131
|
}
|
|
98
132
|
|
|
99
133
|
/**
|
|
@@ -1409,6 +1409,40 @@ describe('Unit test case for ts embed', () => {
|
|
|
1409
1409
|
const { mockGetPreauthInfo } = await setup(true, 123);
|
|
1410
1410
|
expect(mockGetPreauthInfo).toHaveBeenCalledTimes(0);
|
|
1411
1411
|
});
|
|
1412
|
+
|
|
1413
|
+
test('should NOT trigger InfoSuccess when getPreauthInfo resolves with no .info field', async () => {
|
|
1414
|
+
jest.spyOn(window, 'addEventListener').mockImplementationOnce(
|
|
1415
|
+
(event, handler) => {
|
|
1416
|
+
(handler as EventListener)({
|
|
1417
|
+
data: { type: 'xyz' },
|
|
1418
|
+
ports: [3000],
|
|
1419
|
+
source: null,
|
|
1420
|
+
} as any);
|
|
1421
|
+
},
|
|
1422
|
+
);
|
|
1423
|
+
mockProcessTrigger.mockResolvedValueOnce({ session: 'test' });
|
|
1424
|
+
jest.spyOn(authService, 'fetchPreauthInfoService').mockResolvedValueOnce({
|
|
1425
|
+
ok: true,
|
|
1426
|
+
headers: new Headers({ 'content-type': 'application/json' }),
|
|
1427
|
+
json: async () => ({}), // no .info field
|
|
1428
|
+
} as any);
|
|
1429
|
+
const iFrame: any = document.createElement('div');
|
|
1430
|
+
jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(true as any);
|
|
1431
|
+
const tsEmbed = new SearchEmbed(getRootEl(), {});
|
|
1432
|
+
iFrame.contentWindow = { postMessage: jest.fn() };
|
|
1433
|
+
jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce(
|
|
1434
|
+
(event, handler) => { (handler as EventListener)({} as Event); },
|
|
1435
|
+
);
|
|
1436
|
+
jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame);
|
|
1437
|
+
await tsEmbed.render();
|
|
1438
|
+
|
|
1439
|
+
await executeAfterWait(() => {
|
|
1440
|
+
const infoSuccessCall = mockProcessTrigger.mock.calls.find(
|
|
1441
|
+
(call) => call[1] === HostEvent.InfoSuccess,
|
|
1442
|
+
);
|
|
1443
|
+
expect(infoSuccessCall).toBeUndefined();
|
|
1444
|
+
});
|
|
1445
|
+
});
|
|
1412
1446
|
});
|
|
1413
1447
|
|
|
1414
1448
|
describe('Preauth Cache for FullAppEmbed with PrimaryNavBar', () => {
|
|
@@ -2281,6 +2315,46 @@ describe('Unit test case for ts embed', () => {
|
|
|
2281
2315
|
});
|
|
2282
2316
|
});
|
|
2283
2317
|
|
|
2318
|
+
it('Sets the overrideHistoryState param', async () => {
|
|
2319
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2320
|
+
frameParams: {
|
|
2321
|
+
width: '100%',
|
|
2322
|
+
height: '100%',
|
|
2323
|
+
},
|
|
2324
|
+
overrideHistoryState: true,
|
|
2325
|
+
});
|
|
2326
|
+
await appEmbed.render();
|
|
2327
|
+
expectUrlToHaveParamsWithValues(getIFrameSrc(), {
|
|
2328
|
+
overrideHistoryState: true,
|
|
2329
|
+
});
|
|
2330
|
+
});
|
|
2331
|
+
|
|
2332
|
+
it('Sets the overrideHistoryState param to false', async () => {
|
|
2333
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2334
|
+
frameParams: {
|
|
2335
|
+
width: '100%',
|
|
2336
|
+
height: '100%',
|
|
2337
|
+
},
|
|
2338
|
+
overrideHistoryState: false,
|
|
2339
|
+
});
|
|
2340
|
+
await appEmbed.render();
|
|
2341
|
+
expectUrlToHaveParamsWithValues(getIFrameSrc(), {
|
|
2342
|
+
overrideHistoryState: false,
|
|
2343
|
+
});
|
|
2344
|
+
});
|
|
2345
|
+
|
|
2346
|
+
it('Should not add overrideHistoryState param when it is undefined', async () => {
|
|
2347
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2348
|
+
frameParams: {
|
|
2349
|
+
width: '100%',
|
|
2350
|
+
height: '100%',
|
|
2351
|
+
},
|
|
2352
|
+
});
|
|
2353
|
+
await appEmbed.render();
|
|
2354
|
+
const url = getIFrameSrc();
|
|
2355
|
+
expect(url).not.toContain('overrideHistoryState');
|
|
2356
|
+
});
|
|
2357
|
+
|
|
2284
2358
|
it('Should not add contextMenuEnabledOnWhichClick flag to the iframe src when it is not passed', async () => {
|
|
2285
2359
|
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
2286
2360
|
...defaultViewConfig,
|
|
@@ -4570,6 +4644,28 @@ describe('Trigger method edge cases', () => {
|
|
|
4570
4644
|
expect(result).toBeNull();
|
|
4571
4645
|
});
|
|
4572
4646
|
});
|
|
4647
|
+
|
|
4648
|
+
test('isValidationError catch: handleError called with embedErrorDetails and error is rethrown', async () => {
|
|
4649
|
+
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
4650
|
+
const handleErrorSpy = jest.spyOn(searchEmbed as any, 'handleError').mockImplementation(() => {});
|
|
4651
|
+
await searchEmbed.render();
|
|
4652
|
+
|
|
4653
|
+
// First processTrigger call is getAvailableUIPassthroughKeys for DrillDown
|
|
4654
|
+
mockProcessTrigger.mockResolvedValueOnce([
|
|
4655
|
+
{ value: { keys: Object.values(UIPassthroughEvent) } },
|
|
4656
|
+
]);
|
|
4657
|
+
|
|
4658
|
+
// DrillDown with no points → throwDrillDownValidationError → isValidationError=true
|
|
4659
|
+
await expect(
|
|
4660
|
+
searchEmbed.trigger(HostEvent.DrillDown, {} as any),
|
|
4661
|
+
).rejects.toThrow('DrillDown requires a valid points object');
|
|
4662
|
+
|
|
4663
|
+
expect(handleErrorSpy).toHaveBeenCalledWith(
|
|
4664
|
+
expect.objectContaining({
|
|
4665
|
+
data: expect.objectContaining({ code: EmbedErrorCodes.HOST_EVENT_VALIDATION }),
|
|
4666
|
+
}),
|
|
4667
|
+
);
|
|
4668
|
+
});
|
|
4573
4669
|
});
|
|
4574
4670
|
|
|
4575
4671
|
describe('PreRender replaceExistingPreRender scenarios', () => {
|
|
@@ -4580,6 +4676,10 @@ describe('PreRender replaceExistingPreRender scenarios', () => {
|
|
|
4580
4676
|
});
|
|
4581
4677
|
});
|
|
4582
4678
|
|
|
4679
|
+
beforeEach(() => {
|
|
4680
|
+
document.body.innerHTML = getDocumentBody();
|
|
4681
|
+
});
|
|
4682
|
+
|
|
4583
4683
|
afterEach(() => {
|
|
4584
4684
|
const rootEle = document.getElementById('myRoot');
|
|
4585
4685
|
rootEle?.remove();
|
|
@@ -4725,6 +4825,52 @@ describe('Fullscreen change handler behavior', () => {
|
|
|
4725
4825
|
);
|
|
4726
4826
|
});
|
|
4727
4827
|
});
|
|
4828
|
+
|
|
4829
|
+
test('disableFullscreenPresentation undefined defaults to true — no fullscreenchange listener registered', () => {
|
|
4830
|
+
init({
|
|
4831
|
+
thoughtSpotHost: 'tshost',
|
|
4832
|
+
authType: AuthType.None,
|
|
4833
|
+
// disableFullscreenPresentation not set → defaults to true via ?? true
|
|
4834
|
+
});
|
|
4835
|
+
|
|
4836
|
+
const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
4837
|
+
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
|
|
4838
|
+
|
|
4839
|
+
embed['setupFullscreenChangeHandler']();
|
|
4840
|
+
|
|
4841
|
+
expect(addEventListenerSpy).not.toHaveBeenCalledWith('fullscreenchange', expect.any(Function));
|
|
4842
|
+
|
|
4843
|
+
addEventListenerSpy.mockRestore();
|
|
4844
|
+
// Restore for other tests in this describe
|
|
4845
|
+
init({ thoughtSpotHost: 'tshost', authType: AuthType.None, disableFullscreenPresentation: false });
|
|
4846
|
+
});
|
|
4847
|
+
|
|
4848
|
+
test('fullscreenchange fires but iFrame.contentWindow is null — trigger NOT called, debug log emitted', () => {
|
|
4849
|
+
const embed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
4850
|
+
// Give the embed a fake iFrame with null contentWindow
|
|
4851
|
+
(embed as any).iFrame = { contentWindow: null };
|
|
4852
|
+
|
|
4853
|
+
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
|
|
4854
|
+
const loggerDebugSpy = jest.spyOn(logger, 'debug').mockImplementation(() => {});
|
|
4855
|
+
const triggerSpy = jest.spyOn(embed, 'trigger' as any).mockImplementation(() => Promise.resolve(null));
|
|
4856
|
+
|
|
4857
|
+
embed['setupFullscreenChangeHandler']();
|
|
4858
|
+
|
|
4859
|
+
// Capture the registered handler directly instead of dispatching to document
|
|
4860
|
+
const fullscreenCall = addEventListenerSpy.mock.calls.find((c) => c[0] === 'fullscreenchange');
|
|
4861
|
+
expect(fullscreenCall).toBeTruthy();
|
|
4862
|
+
const handler = fullscreenCall[1] as EventListener;
|
|
4863
|
+
|
|
4864
|
+
Object.defineProperty(document, 'fullscreenElement', { value: null, writable: true, configurable: true });
|
|
4865
|
+
handler(new Event('fullscreenchange'));
|
|
4866
|
+
|
|
4867
|
+
expect(triggerSpy).not.toHaveBeenCalled();
|
|
4868
|
+
expect(loggerDebugSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping ExitPresentMode'));
|
|
4869
|
+
|
|
4870
|
+
addEventListenerSpy.mockRestore();
|
|
4871
|
+
loggerDebugSpy.mockRestore();
|
|
4872
|
+
triggerSpy.mockRestore();
|
|
4873
|
+
});
|
|
4728
4874
|
});
|
|
4729
4875
|
|
|
4730
4876
|
describe('ShowPreRender with UpdateEmbedParams', () => {
|
|
@@ -5315,5 +5461,45 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
|
|
|
5315
5461
|
|
|
5316
5462
|
embed.destroy();
|
|
5317
5463
|
});
|
|
5464
|
+
|
|
5465
|
+
// showPreRender located the stale placeholder with a subtree-wide
|
|
5466
|
+
// querySelector but removed it with hostElement.removeChild(), which
|
|
5467
|
+
// only accepts direct children. With fullHeight the placeholder can be
|
|
5468
|
+
// nested deeper than a direct child, so removeChild threw
|
|
5469
|
+
// "NotFoundError: Failed to execute 'removeChild' on 'Node'".
|
|
5470
|
+
it('showPreRender removes a placeholder nested below a direct child without throwing', async () => {
|
|
5471
|
+
createRootEleForEmbed();
|
|
5472
|
+
const embed = new LiveboardEmbed('#tsEmbedDiv', {
|
|
5473
|
+
preRenderId: 'ph-nested-test',
|
|
5474
|
+
liveboardId: 'lb-id',
|
|
5475
|
+
fullHeight: true,
|
|
5476
|
+
} as any);
|
|
5477
|
+
await embed.preRender();
|
|
5478
|
+
await waitFor(
|
|
5479
|
+
() => !!document.querySelector('#tsEmbed-pre-render-child-ph-nested-test'),
|
|
5480
|
+
);
|
|
5481
|
+
|
|
5482
|
+
const hostElement = document.querySelector('#tsEmbedDiv') as HTMLElement;
|
|
5483
|
+
const placeHolderId = 'tsEmbed-pre-render-placeholder-ph-nested-test';
|
|
5484
|
+
// Simulate the fullHeight layout where the placeholder ends up as
|
|
5485
|
+
// a grandchild of the host element rather than a direct child.
|
|
5486
|
+
const intermediateWrapper = document.createElement('div');
|
|
5487
|
+
const staleNestedPlaceholder = document.createElement('div');
|
|
5488
|
+
staleNestedPlaceholder.id = placeHolderId;
|
|
5489
|
+
intermediateWrapper.appendChild(staleNestedPlaceholder);
|
|
5490
|
+
hostElement.appendChild(intermediateWrapper);
|
|
5491
|
+
|
|
5492
|
+
expect(hostElement.querySelector(`#${placeHolderId}`)).toBe(staleNestedPlaceholder);
|
|
5493
|
+
// Before the fix this threw NotFoundError.
|
|
5494
|
+
await expect(embed.showPreRender()).resolves.toBeDefined();
|
|
5495
|
+
// The stale nested placeholder is gone; the fresh one is a direct child.
|
|
5496
|
+
expect(staleNestedPlaceholder.isConnected).toBe(false);
|
|
5497
|
+
const currentPlaceholder = (
|
|
5498
|
+
embed as any
|
|
5499
|
+
).getPreRenderPlaceHolderElement() as HTMLDivElement;
|
|
5500
|
+
expect(currentPlaceholder.parentElement).toBe(hostElement);
|
|
5501
|
+
|
|
5502
|
+
embed.destroy();
|
|
5503
|
+
});
|
|
5318
5504
|
});
|
|
5319
5505
|
});
|