• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thoughtspot / visual-embed-sdk / #1933

06 Jun 2025 01:26PM UTC coverage: 93.519% (-0.3%) from 93.827%
#1933

Pull #215

yinstardev
logger test failure
Pull Request #215: SCAL-256749 present-event

1096 of 1250 branches covered (87.68%)

Branch coverage included in aggregate %.

22 of 25 new or added lines in 3 files covered. (88.0%)

15 existing lines in 3 files now uncovered.

2656 of 2762 relevant lines covered (96.16%)

67.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.13
/src/utils/processTrigger.ts
1
import { ERROR_MESSAGE } from '../errors';
16✔
2
import { HostEvent } from '../types';
16✔
3
import { logger } from '../utils/logger';
4

16✔
5
/**
6
 * Handle the Present event locally before forwarding
7
 * @param iFrame - The iframe element to make fullscreen
8
 */
9
function handlePresentEvent(iFrame: HTMLIFrameElement) {
10
    const iframe = iFrame;
16✔
11
    
1✔
12
    if (!iframe) {
1✔
13
        logger.warn('No iframe found on the page');
1✔
14
        return;
1✔
15
    }
16

17
    // Check if already in fullscreen mode
18
    const isInFullscreen = !!(
19
        document.fullscreenElement ||
20
        (document as any).webkitFullscreenElement ||
21
        (document as any).mozFullScreenElement ||
22
        (document as any).msFullscreenElement
23
    );
24

25
    if (isInFullscreen) {
26
        // Already in fullscreen, nothing to do
27
        return;
28
    }
29

30
    // Try to request fullscreen with vendor prefixes and error handling
31
    const fullscreenMethods = [
32
        'requestFullscreen',
33
        'webkitRequestFullscreen', 
12!
34
        'mozRequestFullScreen',
35
        'msRequestFullscreen'
36
    ];
16✔
37

38
    let fullscreenRequested = false;
39
    
40
    for (const method of fullscreenMethods) {
41
        if (typeof (iframe as any)[method] === 'function') {
42
            try {
43
                const result = (iframe as any)[method]();
44
                if (result && typeof result.catch === 'function') {
45
                    result.catch((error: any) => {
16✔
46
                        logger.warn(`Failed to enter fullscreen using ${method}:`, error);
47
                    });
48
                }
49
                fullscreenRequested = true;
50
                break;
51
            } catch (error) {
13✔
52
                logger.warn(`Failed to enter fullscreen using ${method}:`, error);
13✔
53
            }
1✔
54
        }
1✔
55
    }
56

57
    if (!fullscreenRequested) {
12!
NEW
58
        logger.error('Fullscreen API is not supported by this browser.');
×
59
    }
60
}
61

12✔
62
/**
12✔
63
 * Reloads the ThoughtSpot iframe.
2✔
64
 * @param iFrame
2!
65
 */
2✔
66
export const reload = (iFrame: HTMLIFrameElement) => {
1✔
67
    const src = iFrame.src;
68
    iFrame.src = '';
1✔
69
    setTimeout(() => {
70
        iFrame.src = src;
71
    }, 100);
72
};
73

12✔
74
/**
3✔
75
 * Post iframe message.
3✔
76
 * @param iFrame
77
 * @param message
78
 * @param message.type
12✔
79
 * @param message.data
80
 * @param thoughtSpotHost
81
 * @param channel
82
 */
83
function postIframeMessage(
84
    iFrame: HTMLIFrameElement,
85
    message: { type: HostEvent; data: any },
86
    thoughtSpotHost: string,
87
    channel?: MessageChannel,
88
) {
89
    return iFrame.contentWindow.postMessage(message, thoughtSpotHost, [channel?.port2]);
90
}
91

92
export const TRIGGER_TIMEOUT = 30000;
93

94
/**
95
 *
96
 * @param iFrame
97
 * @param messageType
98
 * @param thoughtSpotHost
99
 * @param data
100
 */
101
export function processTrigger(
102
    iFrame: HTMLIFrameElement,
103
    messageType: HostEvent,
104
    thoughtSpotHost: string,
105
    data: any,
106
): Promise<any> {
107
    return new Promise<any>((res, rej) => {
108
        if (messageType === HostEvent.Reload) {
109
            reload(iFrame);
110
            return res(null);
111
        }
112
        
113
        if (messageType === HostEvent.Present) {
114
            handlePresentEvent(iFrame);
115
        }
116
        
117
        const channel = new MessageChannel();
118
        channel.port1.onmessage = ({ data: responseData }) => {
119
            channel.port1.close();
120
            const error = responseData.error || responseData?.data?.error;
121
            if (error) {
122
                rej(error);
123
            } else {
124
                res(responseData);
125
            }
126
        };
127

128
        // Close the messageChannel and resolve the promise if timeout.
129
        setTimeout(() => {
130
            channel.port1.close();
131
            res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
132
        }, TRIGGER_TIMEOUT);
133

134
        return postIframeMessage(iFrame, { type: messageType, data }, thoughtSpotHost, channel);
135
    });
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc