@thoughtspot/visual-embed-sdk
Version:
ThoughtSpot Embed SDK
289 lines (265 loc) • 9.61 kB
text/typescript
import { logger } from '../utils/logger';
import {
init,
AuthType,
EmbedEvent,
SearchEmbed,
PinboardEmbed,
LiveboardEmbed,
AppEmbed,
HostEvent,
} from '../index';
import {
EVENT_WAIT_TIME,
executeAfterWait,
getDocumentBody,
getIFrameEl,
getRootEl,
getRootEl2,
mockMessageChannel,
postMessageToParent,
} from '../test/test-utils';
import { LiveboardViewConfig } from './liveboard';
import * as authInstance from '../auth';
const thoughtSpotHost = 'tshost';
const defaultViewConfig = {
frameParams: {
width: 1280,
height: 720,
},
};
const PAYLOAD = 'Sample payload';
beforeAll(() => {
init({
thoughtSpotHost,
authType: AuthType.None,
});
spyOn(window, 'alert');
jest.spyOn(authInstance, 'postLoginService').mockReturnValue(true);
});
describe('test communication between host app and ThoughtSpot', () => {
beforeEach(() => {
document.body.innerHTML = getDocumentBody();
});
test('should capture event from ThoughtSpot app', (done) => {
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
searchEmbed
.on(EmbedEvent.CustomAction, (data) => {
expect(data.data).toBe(PAYLOAD);
done();
})
.render();
executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.CustomAction,
data: PAYLOAD,
});
});
});
// TODO: enable test once we are actually able to load stuff in the iframe
xtest('should trigger iframe load event', async () => {
const onLoadSpy = jest.fn();
const searchEmbed = new SearchEmbed(getRootEl(), {});
searchEmbed.on(EmbedEvent.Load, onLoadSpy).render();
await executeAfterWait(() => {
expect(onLoadSpy).toHaveBeenCalled();
}, EVENT_WAIT_TIME);
});
test('should trigger event to ThoughtSpot app', (done) => {
mockMessageChannel();
const searchEmbed = new SearchEmbed(getRootEl(), {});
searchEmbed.render();
setTimeout(() => {
searchEmbed.trigger(HostEvent.Search, {
body: PAYLOAD,
});
}, EVENT_WAIT_TIME);
executeAfterWait(() => {
const iframe = getIFrameEl();
iframe.contentWindow.addEventListener('message', (e) => {
expect(e.data.type).toBe(HostEvent.Search);
expect(e.data.data.body).toBe(PAYLOAD);
done();
});
});
});
test('should execute multiple event handlers if registered', async () => {
const handlerOne = jest.fn();
const handlerTwo = jest.fn();
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
searchEmbed
.on(EmbedEvent.CustomAction, handlerOne)
.on(EmbedEvent.CustomAction, handlerTwo)
.render();
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.CustomAction,
data: PAYLOAD,
});
});
await executeAfterWait(() => {
expect(handlerOne).toHaveBeenCalled();
expect(handlerTwo).toHaveBeenCalled();
}, EVENT_WAIT_TIME);
});
test('should capture event from correct iframe', async () => {
const spyOne = jest.fn();
const embedOne = new SearchEmbed(getRootEl(), defaultViewConfig);
embedOne.on(EmbedEvent.CustomAction, spyOne).render();
const spyTwo = jest.fn();
const embedTwo = new PinboardEmbed(getRootEl2(), {
...defaultViewConfig,
pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
const spyThree = jest.fn();
const embedThree = new LiveboardEmbed(getRootEl2(), {
...defaultViewConfig,
liveboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
embedTwo.on(EmbedEvent.CustomAction, spyTwo).render();
embedThree.on(EmbedEvent.CustomAction, spyThree).render();
await executeAfterWait(() => {
const iframeOne = getIFrameEl();
postMessageToParent(iframeOne.contentWindow, {
type: EmbedEvent.CustomAction,
data: PAYLOAD,
});
});
await executeAfterWait(() => {
expect(spyOne).toHaveBeenCalled();
expect(spyTwo).not.toHaveBeenCalled();
expect(spyThree).not.toHaveBeenCalled();
}, EVENT_WAIT_TIME);
});
test('send getIframeCenter Event without eventPort', async () => {
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
...defaultViewConfig,
fullHeight: true,
pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
liveboardEmbed.render();
const spy1 = jest.spyOn(logger, 'log');
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.EmbedIframeCenter,
data: PAYLOAD,
});
});
expect(spy1).toHaveBeenCalledWith('Event Port is not defined');
});
test('send getIframeCenter Event without eventPort - pinboard', async () => {
const pinboardEmbed = new PinboardEmbed(getRootEl(), {
...defaultViewConfig,
fullHeight: true,
pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
pinboardEmbed.render();
const spy1 = jest.spyOn(logger, 'log');
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.EmbedIframeCenter,
data: PAYLOAD,
});
});
expect(spy1).toHaveBeenCalledWith('Event Port is not defined');
});
test('send getIframeCenter Event with eventPort - pinboard', async () => {
const pinboardEmbed = new PinboardEmbed(getRootEl(), {
...defaultViewConfig,
fullHeight: true,
pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
pinboardEmbed.render();
const mockPort: any = {
postMessage: jest.fn(),
};
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(
iframe.contentWindow,
{
type: EmbedEvent.EmbedIframeCenter,
data: PAYLOAD,
},
mockPort,
);
});
const heightObj = {
data: {
iframeCenter: 0,
iframeHeight: 0,
iframeScrolled: 0,
iframeVisibleViewPort: 0,
viewPortHeight: 768,
},
type: EmbedEvent.EmbedIframeCenter,
};
expect(mockPort.postMessage).toHaveBeenCalledWith(heightObj);
});
test('send getIframeCenter Event with eventPort', async () => {
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
...defaultViewConfig,
fullHeight: true,
pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
} as LiveboardViewConfig);
liveboardEmbed.render();
const mockPort: any = {
postMessage: jest.fn(),
};
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(
iframe.contentWindow,
{
type: EmbedEvent.EmbedIframeCenter,
data: PAYLOAD,
},
mockPort,
);
});
const heightObj = {
data: {
iframeCenter: 0,
iframeHeight: 0,
iframeScrolled: 0,
iframeVisibleViewPort: 0,
viewPortHeight: 768,
},
type: EmbedEvent.EmbedIframeCenter,
};
expect(mockPort.postMessage).toHaveBeenCalledWith(heightObj);
});
test('ALL event listener should fire for all events with the event type set correctly', async () => {
const embed = new AppEmbed(getRootEl(), defaultViewConfig);
const spy = jest.fn();
embed.on(EmbedEvent.ALL, spy);
embed.render();
await executeAfterWait(() => {
const iframe = getIFrameEl();
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.CustomAction,
data: PAYLOAD,
});
postMessageToParent(iframe.contentWindow, {
type: EmbedEvent.DialogOpen,
});
});
await executeAfterWait(() => {
expect(spy).toHaveBeenCalledTimes(3);
expect(spy.mock.calls[0][0]).toMatchObject({
type: EmbedEvent.Init,
});
expect(spy.mock.calls[1][0]).toMatchObject({
type: EmbedEvent.CustomAction,
data: PAYLOAD,
});
expect(spy.mock.calls[2][0]).toMatchObject({
type: EmbedEvent.DialogOpen,
});
}, EVENT_WAIT_TIME);
});
});