@thoughtspot/visual-embed-sdk
Version:
ThoughtSpot Embed SDK
1,268 lines (1,162 loc) • 66.4 kB
text/typescript
/**
* Unit tests for HostEvents that had no prior coverage.
* Covers: postMessage type correctness, !isRendered guard (returns null + handleError),
* and vizId injection on LiveboardEmbed when viewConfig.vizId is set.
*/
import {
init,
AuthType,
LiveboardEmbed,
HostEvent,
EmbedErrorCodes,
} from '../index';
import {
executeAfterWait,
getDocumentBody,
getIFrameEl,
getRootEl,
mockMessageChannel,
messageChannelMock,
} from '../test/test-utils';
import * as authInstance from '../auth';
const thoughtSpotHost = 'https://tshost';
const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
const vizId = '6e73f724-660e-11eb-ae93-0242ac130002';
beforeAll(() => {
init({ thoughtSpotHost, authType: AuthType.None });
jest.spyOn(authInstance, 'postLoginService').mockImplementation(() => Promise.resolve(true as any));
});
beforeEach(() => {
document.body.innerHTML = getDocumentBody();
});
// ---------------------------------------------------------------------------
// Helper: render a LiveboardEmbed and return it with the iframe spy
// ---------------------------------------------------------------------------
async function renderLiveboard(extraConfig: Record<string, any> = {}) {
const lb = new LiveboardEmbed(getRootEl(), {
frameParams: { width: '100%', height: '100%' },
liveboardId,
...extraConfig,
});
await lb.render();
const iframe = getIFrameEl();
jest.spyOn(iframe.contentWindow, 'postMessage');
return { lb, iframe };
}
// Helper: create a LiveboardEmbed that has NOT been rendered, with handleError
// mocked to prevent the jest-setup console.error → throw.
function unrenderedLiveboard() {
const lb = new LiveboardEmbed(getRootEl(), {
frameParams: { width: '100%', height: '100%' },
liveboardId,
});
jest.spyOn(lb as any, 'handleError').mockImplementation(() => {});
return lb;
}
// ---------------------------------------------------------------------------
// 3 – Filter
// ---------------------------------------------------------------------------
describe('HostEvent.Filter', () => {
test('postMessage type is filter (all lowercase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Filter, { columnName: 'col', operator: 'EQ', values: ['v'] } as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'filter' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null and calls handleError when !isRendered', async () => {
const lb = unrenderedLiveboard();
const handleErrorSpy = (lb as any).handleError as jest.Mock;
const result = await lb.trigger(HostEvent.Filter, {} as any);
expect(result).toBeNull();
expect(handleErrorSpy).toHaveBeenCalledWith(
expect.objectContaining({ code: EmbedErrorCodes.RENDER_NOT_CALLED }),
);
});
});
// ---------------------------------------------------------------------------
// 8 – UpdateRuntimeFilters
// ---------------------------------------------------------------------------
describe('HostEvent.UpdateRuntimeFilters', () => {
test('postMessage type is UpdateRuntimeFilters (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.UpdateRuntimeFilters, [] as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'UpdateRuntimeFilters' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.UpdateRuntimeFilters, [] as any);
expect(result).toBeNull();
});
test('vizId is injected when viewConfig.vizId is set and payload is object', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard({ vizId });
await executeAfterWait(() => {
lb.trigger(HostEvent.UpdateRuntimeFilters, [{}] as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'UpdateRuntimeFilters' }),
thoughtSpotHost,
expect.anything(),
);
});
});
});
// ---------------------------------------------------------------------------
// 10 – OpenFilter
// ---------------------------------------------------------------------------
describe('HostEvent.OpenFilter', () => {
test('postMessage type is openFilter (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.OpenFilter, { columnId: 'col1' } as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'openFilter' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.OpenFilter, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 11 – AddColumns
// ---------------------------------------------------------------------------
describe('HostEvent.AddColumns', () => {
test('postMessage type is addColumns (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AddColumns, { columnIds: ['c1'] } as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'addColumns' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AddColumns, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 12 – RemoveColumn
// ---------------------------------------------------------------------------
describe('HostEvent.RemoveColumn', () => {
test('postMessage type is removeColumn (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.RemoveColumn, { columnId: 'c1' } as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'removeColumn' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.RemoveColumn, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 15 – LiveboardInfo
// ---------------------------------------------------------------------------
describe('HostEvent.LiveboardInfo', () => {
test('postMessage type is pinboardInfo', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.LiveboardInfo);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'pinboardInfo' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.LiveboardInfo);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 16 – Schedule
// ---------------------------------------------------------------------------
describe('HostEvent.Schedule', () => {
test('postMessage type is subscription', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Schedule);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'subscription' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Schedule);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 17 – SchedulesList
// ---------------------------------------------------------------------------
describe('HostEvent.SchedulesList', () => {
test('postMessage type is schedule-list (hyphenated)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SchedulesList);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'schedule-list' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SchedulesList);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 18 – ExportTML
// ---------------------------------------------------------------------------
describe('HostEvent.ExportTML', () => {
test('postMessage type is exportTSL (uses TSL abbreviation)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ExportTML);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'exportTSL' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ExportTML);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 19 – EditTML
// ---------------------------------------------------------------------------
describe('HostEvent.EditTML', () => {
test('postMessage type is editTSL', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.EditTML);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'editTSL' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.EditTML);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 20 – UpdateTML
// ---------------------------------------------------------------------------
describe('HostEvent.UpdateTML', () => {
test('postMessage type is updateTSL', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.UpdateTML);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'updateTSL' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.UpdateTML);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 21 – DownloadAsPdf
// ---------------------------------------------------------------------------
describe('HostEvent.DownloadAsPdf', () => {
test('postMessage type is downloadAsPdf (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DownloadAsPdf);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'downloadAsPdf' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DownloadAsPdf);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 22 – DownloadLiveboardAsContinuousPDF
// ---------------------------------------------------------------------------
describe('HostEvent.DownloadLiveboardAsContinuousPDF', () => {
test('postMessage type is downloadLiveboardAsContinuousPDF', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DownloadLiveboardAsContinuousPDF);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'downloadLiveboardAsContinuousPDF' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DownloadLiveboardAsContinuousPDF);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 23 – AIHighlights
// ---------------------------------------------------------------------------
describe('HostEvent.AIHighlights', () => {
test('postMessage type is AIHighlights (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AIHighlights);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'AIHighlights' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AIHighlights);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 24 – MakeACopy
// ---------------------------------------------------------------------------
describe('HostEvent.MakeACopy', () => {
test('postMessage type is makeACopy (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.MakeACopy);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'makeACopy' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.MakeACopy);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 25 – Remove (maps to 'delete' string)
// ---------------------------------------------------------------------------
describe('HostEvent.Remove', () => {
test("postMessage type is 'delete' (NOT 'Remove')", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Remove);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'delete' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Remove);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 26 – Explore
// ---------------------------------------------------------------------------
describe('HostEvent.Explore', () => {
test('postMessage type is explore (all lowercase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Explore, { vizId: 'v1' } as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'explore' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Explore, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 27 – CreateMonitor
// ---------------------------------------------------------------------------
describe('HostEvent.CreateMonitor', () => {
test('postMessage type is createMonitor (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.CreateMonitor);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'createMonitor' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.CreateMonitor);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 28 – ManageMonitor
// ---------------------------------------------------------------------------
describe('HostEvent.ManageMonitor', () => {
test('postMessage type is manageMonitor (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ManageMonitor);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'manageMonitor' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ManageMonitor);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 29 – Edit
// ---------------------------------------------------------------------------
describe('HostEvent.Edit', () => {
test('postMessage type is edit (all lowercase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Edit);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'edit' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Edit);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 30 – CopyLink (maps to 'embedDocument')
// ---------------------------------------------------------------------------
describe('HostEvent.CopyLink', () => {
test("postMessage type is 'embedDocument' (NOT 'CopyLink')", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.CopyLink);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'embedDocument' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.CopyLink);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 33 – ShowUnderlyingData
// ---------------------------------------------------------------------------
describe('HostEvent.ShowUnderlyingData', () => {
test('postMessage type is showUnderlyingData (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ShowUnderlyingData);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'showUnderlyingData' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ShowUnderlyingData);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 34 – Delete (maps to 'onDeleteAnswer')
// ---------------------------------------------------------------------------
describe('HostEvent.Delete', () => {
test("postMessage type is 'onDeleteAnswer' (NOT 'delete' or 'Delete')", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Delete);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'onDeleteAnswer' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Delete);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 35 – SpotIQAnalyze
// ---------------------------------------------------------------------------
describe('HostEvent.SpotIQAnalyze', () => {
test('postMessage type is spotIQAnalyze (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SpotIQAnalyze);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'spotIQAnalyze' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SpotIQAnalyze);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 36 – Download (maps to 'downloadAsPng', same as DownloadAsPng)
// ---------------------------------------------------------------------------
describe('HostEvent.Download', () => {
test("postMessage type is 'downloadAsPng' (same string as DownloadAsPng)", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Download);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'downloadAsPng' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('Download and DownloadAsPng share the identical string value', () => {
expect(HostEvent.Download).toBe(HostEvent.DownloadAsPng);
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Download);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 37 – DownloadAsPng
// ---------------------------------------------------------------------------
describe('HostEvent.DownloadAsPng', () => {
test('postMessage type is downloadAsPng', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DownloadAsPng);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'downloadAsPng' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DownloadAsPng);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 39 – DownloadAsXlsx
// ---------------------------------------------------------------------------
describe('HostEvent.DownloadAsXlsx', () => {
test('postMessage type is downloadAsXLSX (capital X-L-S-X)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DownloadAsXlsx);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'downloadAsXLSX' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DownloadAsXlsx);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 40 – Share
// ---------------------------------------------------------------------------
describe('HostEvent.Share', () => {
test('postMessage type is share (all lowercase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.Share);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'share' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.Share);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 42 – SyncToSheets
// ---------------------------------------------------------------------------
describe('HostEvent.SyncToSheets', () => {
test('postMessage type is sync-to-sheets (hyphenated, all lowercase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SyncToSheets);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'sync-to-sheets' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SyncToSheets);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 43 – SyncToOtherApps
// ---------------------------------------------------------------------------
describe('HostEvent.SyncToOtherApps', () => {
test('postMessage type is sync-to-other-apps (hyphenated)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SyncToOtherApps);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'sync-to-other-apps' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SyncToOtherApps);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 44 – ManagePipelines
// ---------------------------------------------------------------------------
describe('HostEvent.ManagePipelines', () => {
test("postMessage type is 'manage-pipeline' (singular, hyphenated)", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ManagePipelines);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'manage-pipeline' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ManagePipelines);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 45 – ResetSearch
// ---------------------------------------------------------------------------
describe('HostEvent.ResetSearch', () => {
test('postMessage type is resetSearch (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ResetSearch);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'resetSearch' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ResetSearch);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 49 – SetVisibleTabs
// ---------------------------------------------------------------------------
describe('HostEvent.SetVisibleTabs', () => {
test("postMessage type is 'SetPinboardVisibleTabs' (NOT 'SetVisibleTabs')", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SetVisibleTabs, ['tab1'] as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'SetPinboardVisibleTabs' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SetVisibleTabs, [] as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 50 – SetHiddenTabs
// ---------------------------------------------------------------------------
describe('HostEvent.SetHiddenTabs', () => {
test("postMessage type is 'SetPinboardHiddenTabs' (NOT 'SetHiddenTabs')", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SetHiddenTabs, ['tab1'] as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'SetPinboardHiddenTabs' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SetHiddenTabs, [] as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 52 – AskSage
// ---------------------------------------------------------------------------
describe('HostEvent.AskSage', () => {
test('postMessage type is AskSage (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AskSage);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'AskSage' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AskSage);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 53 – UpdateCrossFilter
// ---------------------------------------------------------------------------
describe('HostEvent.UpdateCrossFilter', () => {
test('postMessage type is UpdateCrossFilter (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.UpdateCrossFilter, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'UpdateCrossFilter' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.UpdateCrossFilter, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 56 – UpdateParameters
// ---------------------------------------------------------------------------
describe('HostEvent.UpdateParameters', () => {
test('postMessage type is UpdateParameters (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.UpdateParameters, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'UpdateParameters' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.UpdateParameters, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 60 – SelectPersonalizedView (maps to British spelling)
// ---------------------------------------------------------------------------
describe('HostEvent.SelectPersonalizedView', () => {
test("postMessage type is 'SelectPersonalisedView' (British spelling)", async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SelectPersonalizedView, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'SelectPersonalisedView' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SelectPersonalizedView, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 64 – TransformTableVizData
// ---------------------------------------------------------------------------
describe('HostEvent.TransformTableVizData', () => {
test('postMessage type is TransformTableVizData (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.TransformTableVizData, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'TransformTableVizData' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.TransformTableVizData, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 65 – SpotterSearch
// ---------------------------------------------------------------------------
describe('HostEvent.SpotterSearch', () => {
test('postMessage type is SpotterSearch (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SpotterSearch, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'SpotterSearch' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.SpotterSearch, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 66 – EditLastPrompt
// ---------------------------------------------------------------------------
describe('HostEvent.EditLastPrompt', () => {
test('postMessage type is EditLastPrompt (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.EditLastPrompt, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'EditLastPrompt' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.EditLastPrompt, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 67 – PreviewSpotterData
// ---------------------------------------------------------------------------
describe('HostEvent.PreviewSpotterData', () => {
test('postMessage type is PreviewSpotterData (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.PreviewSpotterData, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'PreviewSpotterData' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.PreviewSpotterData, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 68 – AddToCoaching
// ---------------------------------------------------------------------------
describe('HostEvent.AddToCoaching', () => {
test('postMessage type is addToCoaching (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AddToCoaching, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'addToCoaching' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AddToCoaching, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 69 – DataModelInstructions
// ---------------------------------------------------------------------------
describe('HostEvent.DataModelInstructions', () => {
test('postMessage type is DataModelInstructions (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DataModelInstructions, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'DataModelInstructions' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DataModelInstructions, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 70 – ResetSpotterConversation
// ---------------------------------------------------------------------------
describe('HostEvent.ResetSpotterConversation', () => {
test('postMessage type is ResetSpotterConversation (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.ResetSpotterConversation, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'ResetSpotterConversation' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.ResetSpotterConversation, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 71 – DeleteLastPrompt
// ---------------------------------------------------------------------------
describe('HostEvent.DeleteLastPrompt', () => {
test('postMessage type is DeleteLastPrompt (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.DeleteLastPrompt, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'DeleteLastPrompt' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.DeleteLastPrompt, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 72 – AnswerChartSwitcher
// ---------------------------------------------------------------------------
describe('HostEvent.AnswerChartSwitcher', () => {
test('postMessage type is answerChartSwitcher (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AnswerChartSwitcher, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'answerChartSwitcher' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AnswerChartSwitcher, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 75 – AskSpotter
// ---------------------------------------------------------------------------
describe('HostEvent.AskSpotter', () => {
test('postMessage type is AskSpotter (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.AskSpotter, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'AskSpotter' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.AskSpotter, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 78 – StartNewSpotterConversation
// ---------------------------------------------------------------------------
describe('HostEvent.StartNewSpotterConversation', () => {
test('postMessage type is StartNewSpotterConversation (PascalCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.StartNewSpotterConversation, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ type: 'StartNewSpotterConversation' }),
thoughtSpotHost,
expect.anything(),
);
});
});
test('returns null when !isRendered', async () => {
const lb = unrenderedLiveboard();
const result = await lb.trigger(HostEvent.StartNewSpotterConversation, {} as any);
expect(result).toBeNull();
});
});
// ---------------------------------------------------------------------------
// 80 – SendTestScheduleEmail
// ---------------------------------------------------------------------------
describe('HostEvent.SendTestScheduleEmail', () => {
test('postMessage type is sendTestScheduleEmail (camelCase)', async () => {
mockMessageChannel();
const { lb, iframe } = await renderLiveboard();
await executeAfterWait(() => {
lb.trigger(HostEvent.SendTestScheduleEmail, {} as any);
expect(iframe.contentWindow.postMessage).toHaveBeenCalle