UNPKG

@thoughtspot/visual-embed-sdk

Version:
1,047 lines 124 kB
"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&paramVal1=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