@thoughtspot/visual-embed-sdk
Version:
ThoughtSpot Embed SDK
1,047 lines • 124 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultParams = exports.defaultParamsWithoutHiddenActions = void 0;
const tslib_1 = require("tslib");
/* eslint-disable dot-notation */
const utils_1 = require("../utils");
const errors_1 = require("../errors");
const authToken_1 = require("../authToken");
const index_1 = require("../index");
const types_1 = require("../types");
const test_utils_1 = require("../test/test-utils");
const config = tslib_1.__importStar(require("../config"));
const embedConfig = tslib_1.__importStar(require("./embedConfig"));
const tsEmbedInstance = tslib_1.__importStar(require("./ts-embed"));
const mixpanelInstance = tslib_1.__importStar(require("../mixpanel-service"));
const authInstance = tslib_1.__importStar(require("../auth"));
const baseInstance = tslib_1.__importStar(require("./base"));
const mixpanel_service_1 = require("../mixpanel-service");
const authService = tslib_1.__importStar(require("../utils/authService"));
const logger_1 = require("../utils/logger");
const package_json_1 = require("../../package.json");
const search_1 = require("./search");
const processTrigger_1 = require("../utils/processTrigger");
const contracts_1 = require("./hostEventClient/contracts");
const sessionInfoService = tslib_1.__importStar(require("../utils/sessionInfoService"));
const authToken = tslib_1.__importStar(require("../authToken"));
jest.mock('../utils/processTrigger');
const mockProcessTrigger = processTrigger_1.processTrigger;
const defaultViewConfig = {
frameParams: {
width: 1280,
height: 720,
},
};
const pinboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
const liveboardId = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
const tabId1 = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
const tabId2 = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
const thoughtSpotHost = 'tshost';
const defaultParamsPost = '';
exports.defaultParamsWithoutHiddenActions = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${package_json_1.version}&authType=${index_1.AuthType.None}&blockNonEmbedFullAppAccess=true`;
exports.defaultParams = `&${exports.defaultParamsWithoutHiddenActions}&hideAction=[%22${types_1.Action.ReportError}%22]`;
const hideBydefault = `&hideAction=${(0, test_utils_1.fixedEncodeURI)(JSON.stringify([types_1.Action.ReportError, ...search_1.HiddenActionItemByDefaultForSearchEmbed]))}`;
const defaultParamsWithHiddenActions = exports.defaultParamsWithoutHiddenActions + hideBydefault;
beforeAll(() => {
spyOn(window, 'alert');
});
const customisations = {
style: {
customCSS: {},
},
content: {},
};
const customisationsView = {
style: {
customCSS: {},
},
content: {
strings: {
DATA: 'data',
},
},
};
const customVariablesForThirdPartyTools = {
key1: '!@#',
key2: '*%^',
};
describe('Unit test case for ts embed', () => {
const mockMixPanelEvent = jest.spyOn(mixpanelInstance, 'uploadMixpanelEvent');
beforeEach(() => {
document.body.innerHTML = (0, test_utils_1.getDocumentBody)();
});
afterEach(() => {
jest.clearAllMocks();
(0, authToken_1.resetCachedAuthToken)();
});
beforeAll(() => {
jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
});
describe('Vaidate iframe properties', () => {
beforeAll(() => {
(0, index_1.init)({
thoughtSpotHost: 'tshost',
authType: index_1.AuthType.None,
});
});
test('should set proper allow policies', async () => {
// we dont have origin specific policies so just checking if
// policies are ending with ;
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
const policiesAdded = iframe.allow.split(' ');
policiesAdded.forEach((policy) => {
expect(policy.endsWith(';')).toBe(true);
});
});
});
test('should get answer service', async () => {
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
mockProcessTrigger.mockResolvedValue({ session: 'test' });
await (0, test_utils_1.executeAfterWait)(async () => {
expect(await searchEmbed.getAnswerService()).toBeInstanceOf(index_1.AnswerService);
});
});
test('triggerUIPassThrough with params', async () => {
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
mockProcessTrigger.mockResolvedValue({ session: 'test' });
await (0, test_utils_1.executeAfterWait)(async () => {
const payload = { newVizName: 'test' };
await searchEmbed.triggerUIPassThrough(contracts_1.UIPassthroughEvent.PinAnswerToLiveboard, payload);
expect(mockProcessTrigger).toHaveBeenCalledWith((0, test_utils_1.getIFrameEl)(), types_1.HostEvent.UIPassthrough, 'http://tshost', {
parameters: payload,
type: contracts_1.UIPassthroughEvent.PinAnswerToLiveboard,
});
});
});
test('Host event with empty param', async () => {
const liveboardEmbed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), {
liveboardId: '123',
...defaultViewConfig,
});
liveboardEmbed.render();
mockProcessTrigger.mockResolvedValue({ session: 'test' });
await (0, test_utils_1.executeAfterWait)(async () => {
await liveboardEmbed.trigger(types_1.HostEvent.Save);
expect(mockProcessTrigger).toHaveBeenCalledWith((0, test_utils_1.getIFrameEl)(), types_1.HostEvent.Save, 'http://tshost', {});
});
});
test('Host event with falsy param', async () => {
const liveboardEmbed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), {
liveboardId: '123',
...defaultViewConfig,
});
liveboardEmbed.render();
mockProcessTrigger.mockResolvedValue({ session: 'test' });
await (0, test_utils_1.executeAfterWait)(async () => {
await liveboardEmbed.trigger(types_1.HostEvent.Save, false);
expect(mockProcessTrigger).toHaveBeenCalledWith((0, test_utils_1.getIFrameEl)(), types_1.HostEvent.Save, 'http://tshost', false);
});
});
test('should set proper height, width and min-height to iframe', async () => {
// we dont have origin specific policies so just checking if
// policies are ending with ;
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
expect(iframe.style.width).toBe(`${defaultViewConfig.frameParams.width}px`);
expect(iframe.style.height).toBe(`${defaultViewConfig.frameParams.height}px`);
expect(iframe.style.minHeight).toBe(`${defaultViewConfig.frameParams.height}px`);
});
});
});
describe('AuthExpire embedEvent in cookieless authentication authType', () => {
beforeAll(() => {
jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthTokenCookieless,
getAuthToken: () => Promise.resolve('test_auth_token2'),
});
});
test('check for new authToken based on getAuthToken function', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
jest.spyOn(baseInstance, 'notifyAuthFailure');
jest.spyOn(baseInstance, 'handleAuth');
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(baseInstance.handleAuth).not.toHaveBeenCalled();
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.AuthExpire,
data: { authToken: 'test_auth_token2' },
});
});
});
test('check for new authToken based on getAuthToken function', async () => {
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthToken,
getAuthToken: () => Promise.resolve('test_auth_token2'),
autoLogin: true,
});
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
jest.spyOn(baseInstance, 'notifyAuthFailure');
jest.spyOn(baseInstance, 'handleAuth');
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(mockPort.postMessage).not.toHaveBeenCalledWith({
type: index_1.EmbedEvent.AuthExpire,
data: { authToken: 'test_auth_token2' },
});
expect(baseInstance.handleAuth).toHaveBeenCalled();
});
});
});
describe('Called Embed event status for start and end', () => {
beforeAll(() => {
(0, index_1.init)({
thoughtSpotHost: 'tshost',
authType: index_1.AuthType.None,
customizations: customisations,
customVariablesForThirdPartyTools,
});
});
test('verify Customisations', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('verify Customisations from viewConfig', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
customizations: customisationsView,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations: customisationsView,
authToken: '',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('hide home page modules from view Config should be part of app_init payload', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockedHiddenHomepageModules = [
types_1.HomepageModule.MyLibrary,
types_1.HomepageModule.Learning,
];
const searchEmbed = new index_1.AppEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
hiddenHomepageModules: mockedHiddenHomepageModules,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
hostConfig: undefined,
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [types_1.HomepageModule.MyLibrary, types_1.HomepageModule.Learning],
hiddenListColumns: [],
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('customVariablesForThirdPartyTools should be part of the app_init payload', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.AppEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
hostConfig: undefined,
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('Reordering the home page modules from view Config should be part of app_init payload', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockedReorderedHomepageModules = [
types_1.HomepageModule.MyLibrary,
types_1.HomepageModule.Watchlist,
];
const searchEmbed = new index_1.AppEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
reorderedHomepageModules: mockedReorderedHomepageModules,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
hostConfig: undefined,
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
reorderedHomepageModules: [types_1.HomepageModule.MyLibrary, types_1.HomepageModule.Watchlist],
customVariablesForThirdPartyTools,
},
});
});
});
test('Runtime parameters from view Config should be part of app_init payload when excludeRuntimeParametsfromURL is true', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockRuntimeParameters = [
{
name: 'color',
value: 'blue',
},
];
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
excludeRuntimeParametersfromURL: true,
runtimeParameters: mockRuntimeParameters,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
runtimeFilterParams: null,
runtimeParameterParams: 'param1=color¶mVal1=blue',
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('Runtime filters from view Config should be part of app_init payload when excludeRuntimeFiltersfromURL is true', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockRuntimeFilters = [
{
columnName: 'color',
operator: types_1.RuntimeFilterOp.EQ,
values: ['blue'],
},
];
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
excludeRuntimeFiltersfromURL: true,
runtimeFilters: mockRuntimeFilters,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
runtimeFilterParams: 'col1=color&op1=EQ&val1=blue',
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('Runtime filters from view Config should be not part of app_init payload when excludeRuntimeFiltersfromURL is undefined', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockRuntimeFilters = [
{
columnName: 'color',
operator: types_1.RuntimeFilterOp.EQ,
values: ['blue'],
},
];
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
runtimeFilters: mockRuntimeFilters,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('Runtime filters from view Config should not be part of app_init payload when excludeRuntimeFiltersfromURL is false', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockRuntimeFilters = [
{
columnName: 'color',
operator: types_1.RuntimeFilterOp.EQ,
values: ['blue'],
},
];
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
excludeRuntimeFiltersfromURL: false,
runtimeFilters: mockRuntimeFilters,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('homeLeftNav from view Config should be part of app_init payload', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const mockedHiddenHomeLeftNavItems = [
types_1.HomeLeftNavItem.Home,
types_1.HomeLeftNavItem.MonitorSubscription,
];
const searchEmbed = new index_1.AppEmbed((0, test_utils_1.getRootEl)(), {
...defaultViewConfig,
hiddenHomeLeftNavItems: mockedHiddenHomeLeftNavItems,
});
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: '',
hostConfig: undefined,
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [types_1.HomeLeftNavItem.Home, types_1.HomeLeftNavItem.MonitorSubscription],
hiddenHomepageModules: [],
hiddenListColumns: [],
reorderedHomepageModules: [],
customVariablesForThirdPartyTools,
},
});
});
});
test('when Embed event status have start status', (done) => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.Save,
data: { answerId: '123' },
status: 'start',
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed
.on(index_1.EmbedEvent.Save, (payload) => {
expect(payload).toEqual(mockEmbedEventPayload);
done();
}, { start: true })
.render();
(0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
});
});
test('should not called post message, when Embed event status have start and start option as false', () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.Save,
data: { answerId: '123' },
status: 'start',
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed
.on(index_1.EmbedEvent.Save, () => {
logger_1.logger.log('non callable');
})
.render();
(0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
iframe.contentWindow.postMessage = jest.fn();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledTimes(0);
});
});
test('when Embed event status have end status', (done) => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.Save,
data: { answerId: '123' },
status: 'end',
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed
.on(index_1.EmbedEvent.Save, (payload) => {
expect(payload).toEqual(mockEmbedEventPayload);
done();
})
.render();
(0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
}, 1000);
});
test('should not called post message, when Embed event status have end status and start is true', () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.Save,
data: { answerId: '123' },
status: 'end',
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed
.on(index_1.EmbedEvent.Save, () => {
logger_1.logger.log('non callable');
}, { start: true })
.render();
(0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
iframe.contentWindow.postMessage = jest.fn();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
expect(iframe.contentWindow.postMessage).toHaveBeenCalledTimes(0);
}, 1000);
});
test('should remove event listener when called off method', async (done) => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.Save,
data: { answerId: '123' },
status: 'end',
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
const mockFn = jest.fn();
searchEmbed.on(index_1.EmbedEvent.Save, mockFn).render();
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
});
searchEmbed.off(index_1.EmbedEvent.Save, mockFn);
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockFn).toHaveBeenCalledTimes(1);
done();
}, 100);
});
});
describe('Appinit embedEvent in cookieless authentication authType', () => {
beforeAll(() => {
jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthTokenCookieless,
getAuthToken: () => Promise.resolve('test_auth_token1'),
});
});
afterEach(() => {
baseInstance.reset();
});
test('check for authToken based on getAuthToken function', async () => {
const a = jest.spyOn(authService, 'verifyTokenService');
a.mockResolvedValue(true);
// authVerifyMock.mockResolvedValue(true);
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations,
authToken: 'test_auth_token1',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools: {},
},
});
});
jest.spyOn(authService, 'verifyTokenService').mockClear();
});
});
describe('StringIDs and StringIDsUrl in customisations', () => {
const customisationWithStringIds = {
style: {
customCSS: {},
},
content: {
strings: {
Liveboard: 'Dashboard',
},
stringIDsUrl: 'https://sample-string-ids-url.com',
stringIDs: {
'liveboard.header.title': 'Dashboard name',
},
},
};
beforeEach(() => {
jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
jest.spyOn(authService, 'verifyTokenService').mockResolvedValue(true);
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisationWithStringIds,
authType: index_1.AuthType.TrustedAuthTokenCookieless,
getAuthToken: () => Promise.resolve('test_auth_token1'),
});
});
afterEach(() => {
baseInstance.reset();
jest.clearAllMocks();
});
test('should pass stringIDsUrl and stringIDs in customisations during APP_INIT', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
expect(iframe.src).toContain('overrideStringIDsUrl=https://sample-string-ids-url.com');
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).toHaveBeenCalledWith({
type: index_1.EmbedEvent.APP_INIT,
data: {
customisations: {
content: {
strings: {
Liveboard: 'Dashboard',
},
stringIDsUrl: 'https://sample-string-ids-url.com',
stringIDs: {
'liveboard.header.title': 'Dashboard name',
},
},
style: {
customCSS: {},
customCSSUrl: undefined,
},
},
authToken: 'test_auth_token1',
runtimeFilterParams: null,
runtimeParameterParams: null,
hiddenHomeLeftNavItems: [],
hiddenHomepageModules: [],
hiddenListColumns: [],
hostConfig: undefined,
reorderedHomepageModules: [],
customVariablesForThirdPartyTools: {},
},
});
const customisationContent = mockPort.postMessage.mock.calls[0][0].data.customisations.content;
expect(customisationContent.stringIDsUrl)
.toBe('https://sample-string-ids-url.com');
expect(customisationContent.stringIDs)
.toEqual({
'liveboard.header.title': 'Dashboard name',
});
});
});
test('should allow passing exposeTranslationIDs in viewConfig', async () => {
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), { ...defaultViewConfig, exposeTranslationIDs: true });
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
expect(iframe.src).toContain('exposeTranslationIDs=true');
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
});
});
describe('Token fetch fails in cookieless authentication authType', () => {
beforeEach(() => {
jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthTokenCookieless,
getAuthToken: () => Promise.reject(),
});
jest.spyOn(logger_1.logger, 'error').mockResolvedValue(true);
});
afterEach(() => {
jest.clearAllMocks();
baseInstance.reset();
});
test('should show login failure message if token failed during app_init', async () => {
const a = jest.spyOn(authService, 'verifyTokenService');
a.mockResolvedValue(true);
// authVerifyMock.mockResolvedValue(true);
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).not.toHaveBeenCalled();
expect((0, test_utils_1.getRootEl)().innerHTML).toContain('Not logged in');
});
jest.spyOn(authService, 'verifyTokenService').mockClear();
});
test('should show login failure message if token failed during app_init prerender', async () => {
const a = jest.spyOn(authService, 'verifyTokenService');
a.mockResolvedValue(true);
// authVerifyMock.mockResolvedValue(true);
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.APP_INIT,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), { ...defaultViewConfig, preRenderId: 'test' });
searchEmbed.preRender();
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
const preRenderWrapper = document.getElementById('tsEmbed-pre-render-wrapper-test');
await (0, test_utils_1.executeAfterWait)(() => {
expect(mockPort.postMessage).not.toHaveBeenCalled();
expect(preRenderWrapper.innerHTML).toContain('Not logged in');
});
jest.spyOn(authService, 'verifyTokenService').mockClear();
});
test('should show login failure message if update token failed', async () => {
const a = jest.spyOn(authService, 'verifyTokenService');
a.mockResolvedValue(true);
// authVerifyMock.mockResolvedValue(true);
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
jest.spyOn(baseInstance, 'notifyAuthFailure');
searchEmbed.render();
const mockPort = {
postMessage: jest.fn(),
};
const loggerSpy = jest.spyOn(logger_1.logger, 'error').mockResolvedValueOnce(true);
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect((0, test_utils_1.getRootEl)().innerHTML).toContain('Not logged in');
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(loggerSpy).toHaveBeenCalledTimes(1);
});
jest.spyOn(authService, 'verifyTokenService').mockClear();
jest.spyOn(baseInstance, 'notifyAuthFailure').mockClear();
});
test('should show login failure message if update token failed prerender', async () => {
const a = jest.spyOn(authService, 'verifyTokenService');
a.mockResolvedValue(true);
// authVerifyMock.mockResolvedValue(true);
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), { ...defaultViewConfig, preRenderId: 'test' });
jest.spyOn(baseInstance, 'notifyAuthFailure');
searchEmbed.preRender();
const loggerSpy = jest.spyOn(logger_1.logger, 'error').mockResolvedValueOnce(true);
const mockPort = {
postMessage: jest.fn(),
};
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload, mockPort);
});
const preRenderWrapper = document.getElementById('tsEmbed-pre-render-wrapper-test');
await (0, test_utils_1.executeAfterWait)(() => {
expect(preRenderWrapper.innerHTML).toContain('Not logged in');
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(loggerSpy).toHaveBeenCalledTimes(1);
});
jest.spyOn(authService, 'verifyTokenService').mockClear();
jest.spyOn(baseInstance, 'notifyAuthFailure').mockClear();
});
});
xdescribe('AuthExpire embedEvent in TrustedAuthToken authType', () => {
test('AutoLogin true scenario', async () => {
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthToken,
username: 'tsadmin',
getAuthToken: () => Promise.resolve('test_auth_token3'),
autoLogin: true,
});
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
jest.spyOn(baseInstance, 'notifyAuthFailure');
jest.spyOn(baseInstance, 'handleAuth');
searchEmbed.render();
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(baseInstance.handleAuth).toHaveBeenCalled();
});
});
test('AutoLogin false scenario', async () => {
(0, index_1.init)({
thoughtSpotHost: 'tshost',
customizations: customisations,
authType: index_1.AuthType.TrustedAuthToken,
username: 'tsadmin',
getAuthToken: () => Promise.resolve('test_auth_token4'),
});
const mockEmbedEventPayload = {
type: index_1.EmbedEvent.AuthExpire,
data: {},
};
const searchEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), defaultViewConfig);
jest.spyOn(baseInstance, 'notifyAuthFailure');
jest.spyOn(baseInstance, 'handleAuth');
searchEmbed.render();
await (0, test_utils_1.executeAfterWait)(() => {
const iframe = (0, test_utils_1.getIFrameEl)();
(0, test_utils_1.postMessageToParent)(iframe.contentWindow, mockEmbedEventPayload);
});
await (0, test_utils_1.executeAfterWait)(() => {
expect(baseInstance.notifyAuthFailure).toBeCalledWith(authInstance.AuthFailureType.EXPIRY);
expect(baseInstance.handleAuth).not.toHaveBeenCalled();
});
});
});
describe('when thoughtSpotHost have value and authPromise return response true/false', () => {
beforeAll(() => {
(0, index_1.init)({
thoughtSpotHost,
authType: index_1.AuthT