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

thoughtspot / visual-embed-sdk / #2421

16 Sep 2025 08:56AM UTC coverage: 93.944% (-0.1%) from 94.081%
#2421

Pull #311

shivam-kumar-ts
SCAL-116862 added console log
Pull Request #311: SCAL-116862 FOR TEST added console log

1176 of 1335 branches covered (88.09%)

Branch coverage included in aggregate %.

47 of 50 new or added lines in 6 files covered. (94.0%)

54 existing lines in 6 files now uncovered.

2888 of 2991 relevant lines covered (96.56%)

84.19 hits per line

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

88.68
/src/embed/hostEventClient/host-event-client.ts
1
import { HostEvent } from '../../types';
15✔
2
import { logger } from '../../utils/logger';
15✔
3
import { processTrigger as processTriggerService } from '../../utils/processTrigger';
15✔
4
import { getEmbedConfig } from '../embedConfig';
15✔
5
import {
15✔
6
    UIPassthroughArrayResponse,
7
    UIPassthroughEvent, HostEventRequest, HostEventResponse,
8
    UIPassthroughRequest,
9
    UIPassthroughResponse,
10
    TriggerPayload,
11
    TriggerResponse,
12
} from './contracts';
13

14
export class HostEventClient {
15✔
15
  iFrame: HTMLIFrameElement;
16

17
  constructor(iFrame?: HTMLIFrameElement) {
18
      this.iFrame = iFrame;
398✔
19
  }
20

21
  /**
22
   * A wrapper over process trigger to
23
   * @param {HostEvent} message Host event to send
24
   * @param {any} data Data to send with the host event
25
   * @returns {Promise<any>} - the response from the process trigger
26
   */
27
  protected async processTrigger(message: HostEvent, data: any): Promise<any> {
28
      logger.log("8. Processing trigger");
39✔
29
      if (!this.iFrame) {
39!
NEW
30
          logger.log("9. Iframe element is not set");
×
UNCOV
31
          throw new Error('Iframe element is not set');
×
32
      }
33

34
      const thoughtspotHost = getEmbedConfig().thoughtSpotHost;
39✔
35
      logger.log("10. Thoughtspot host is set");
39✔
36
      return processTriggerService(
39✔
37
          this.iFrame,
38
          message,
39
          thoughtspotHost,
40
          data,
41
      );
42
  }
43

44
  public async handleHostEventWithParam<UIPassthroughEventT extends UIPassthroughEvent>(
45
      apiName: UIPassthroughEventT,
46
      parameters: UIPassthroughRequest<UIPassthroughEventT>,
47
  ): Promise<UIPassthroughResponse<UIPassthroughEventT>> {
48
      const response = (await this.triggerUIPassthroughApi(apiName, parameters))
8!
49
          ?.filter?.((r) => r.error || r.value)[0];
6✔
50

51
      if (!response) {
8✔
52
          const error = `No answer found${parameters.vizId ? ` for vizId: ${parameters.vizId}` : ''}.`;
2✔
53
          // eslint-disable-next-line no-throw-literal
54
          throw { error };
2✔
55
      }
56

57
      const errors = response.error
6✔
58
        || (response.value as any)?.errors
15!
59
        || (response.value as any)?.error;
15!
60

61
      if (errors) {
6✔
62
      // eslint-disable-next-line no-throw-literal
63
          throw { error: response.error };
1✔
64
      }
65

66
      return { ...response.value };
5✔
67
  }
68

69
  public async hostEventFallback(
70
      hostEvent: HostEvent,
71
      data: any,
72
  ): Promise<any> {
73
      logger.log("7. Host event fallback");
29✔
74
      return this.processTrigger(hostEvent, data);
29✔
75
  }
76

77
  /**
78
   * Setter for the iframe element used for host events
79
   * @param {HTMLIFrameElement} iFrame - the iframe element to set
80
   */
81
  public setIframeElement(iFrame: HTMLIFrameElement): void {
82
      this.iFrame = iFrame;
349✔
83
  }
84

85
  public async triggerUIPassthroughApi<UIPassthroughEventT extends UIPassthroughEvent>(
86
      apiName: UIPassthroughEventT,
87
      parameters: UIPassthroughRequest<UIPassthroughEventT>,
88
  ): Promise<UIPassthroughArrayResponse<UIPassthroughEventT>> {
89
      const res = await this.processTrigger(HostEvent.UIPassthrough, {
10✔
90
          type: apiName,
91
          parameters,
92
      });
93

94
      return res;
10✔
95
  }
96

97
  protected async handlePinEvent(
98
      payload: HostEventRequest<HostEvent.Pin>,
99
  ): Promise<HostEventResponse<HostEvent.Pin>> {
100
      if (!payload || !('newVizName' in payload)) {
5✔
101
          return this.hostEventFallback(HostEvent.Pin, payload);
2✔
102
      }
103

104
      const formattedPayload = {
3✔
105
          ...payload,
106
          pinboardId: payload.liveboardId ?? (payload as any).pinboardId,
9✔
107
          newPinboardName: payload.newLiveboardName ?? (payload as any).newPinboardName,
9✔
108
      };
109

110
      const data = await this.handleHostEventWithParam(
3✔
111
          UIPassthroughEvent.PinAnswerToLiveboard, formattedPayload,
112
      );
113

114
      return {
3✔
115
          ...data,
116
          liveboardId: (data as any).pinboardId,
117
      };
118
  }
119

120
  protected async handleSaveAnswerEvent(
121
      payload: HostEventRequest<HostEvent.SaveAnswer>,
122
  ): Promise<any> {
123
      if (!payload || !('name' in payload) || !('description' in payload)) {
2✔
124
          // Save is the fallback for SaveAnswer
125
          return this.hostEventFallback(HostEvent.Save, payload);
1✔
126
      }
127

128
      const data = await this.handleHostEventWithParam(
1✔
129
          UIPassthroughEvent.SaveAnswer, payload,
130
      );
131
      return {
1✔
132
          ...data,
133
          answerId: data?.saveResponse?.data?.Answer__save?.answer?.id,
15!
134
      };
135
  }
136

137
  public async triggerHostEvent<
138
    HostEventT extends HostEvent,
139
    PayloadT,
140
  >(
141
      hostEvent: HostEventT,
142
      payload?: TriggerPayload<PayloadT, HostEventT>,
143
  ): Promise<TriggerResponse<PayloadT, HostEventT>> {
144
      logger.log("6. Triggering host event");
34✔
145
      switch (hostEvent) {
34✔
146
          case HostEvent.Pin:
147
              return this.handlePinEvent(payload as HostEventRequest<HostEvent.Pin>) as any;
5✔
148
          case HostEvent.SaveAnswer:
149
              return this.handleSaveAnswerEvent(
2✔
150
                  payload as HostEventRequest<HostEvent.SaveAnswer>,
151
              ) as any;
152
          default:
153
              return this.hostEventFallback(hostEvent, payload);
27✔
154
      }
155
  }
156
}
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