UNPKG

@thoughtspot/visual-embed-sdk

Version:
1,048 lines 103 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 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")); 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: [], 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: [], 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], 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: [], 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: [], 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: [], 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: [], 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: [], 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: [], 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: [], 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: [], hostConfig: undefined, reorderedHomepageModules: [], customVariablesForThirdPartyTools: {}, }, }); }); jest.spyOn(authService, 'verifyTokenService').mockClear(); }); }); 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.AuthType.None, loginFailedMessage: 'Failed to Login', }); }); const setup = async (isLoggedIn = false) => { jest.spyOn(window, 'addEventListener').mockImplementationOnce((event, handler, options) => { handler({ data: { type: 'xyz', }, ports: [3000], source: null, }); }); const iFrame = document.createElement('div'); jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(isLoggedIn); const tsEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {}); iFrame.contentWindow = null; tsEmbed.on(index_1.EmbedEvent.CustomAction, jest.fn()); jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce((event, handler, options) => { handler({}); }); jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame); await tsEmbed.render(); }; test('mixpanel should call with VISUAL_SDK_RENDER_COMPLETE', async () => { await setup(true); expect(mockMixPanelEvent).toBeCalledWith(mixpanel_service_1.MIXPANEL_EVENT.VISUAL_SDK_RENDER_START); expect(mockMixPanelEvent).toBeCalledWith(mixpanel_service_1.MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE, expect.objectContaining({ elWidth: 0, elHeight: 0, })); }); test('Should remove prefetch iframe', async () => { await setup(true); const prefetchIframe = document.querySelectorAll('.prefetchIframe'); expect(prefetchIframe.length).toBe(0); }); test('Should render failure when login fails', async (done) => { setup(false); (0, test_utils_1.executeAfterWait)(() => { expect((0, test_utils_1.getRootEl)().innerHTML).toContain('Failed to Login'); done(); }); }); }); describe('Trigger infoSuccess event on iframe load', () => { beforeAll(() => { jest.clearAllMocks(); (0, index_1.init)({ thoughtSpotHost, authType: index_1.AuthType.None, loginFailedMessage: 'Failed to Login', }); }); const setup = async (isLoggedIn = false, overrideOrgId = undefined) => { jest.spyOn(window, 'addEventListener').mockImplementationOnce((event, handler, options) => { handler({ data: { type: 'xyz', }, ports: [3000], source: null, }); }); mockProcessTrigger.mockResolvedValueOnce({ session: 'test' }); // resetCachedPreauthInfo(); let mockGetPreauthInfo = null; if (overrideOrgId) { mockGetPreauthInfo = jest.spyOn(sessionInfoService, 'getPreauthInfo').mockImplementation(jest.fn()); } const mockPreauthInfoFetch = jest.spyOn(authService, 'fetchPreauthInfoService').mockResolvedValueOnce({ ok: true, headers: new Headers({ 'content-type': 'application/json' }), json: async () => ({ info: { configInfo: { mixpanelConfig: { devSdkKey: 'devSdkKey', }, }, userGUID: 'userGUID', }, }), // Mock JSON response }); const iFrame = document.createElement('div'); jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(isLoggedIn); const tsEmbed = new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), { overrideOrgId, }); iFrame.contentWindow = { postMessage: jest.fn(), }; tsEmbed.on(index_1.EmbedEvent.CustomAction, jest.fn()); jest.spyOn(iFrame, 'addEventListener').mockImplementationOnce((event, handler, options) => { handler({}); }); jest.spyOn(document, 'createElement').mockReturnValueOnce(iFrame); await tsEmbed.render(); return { mockPreauthInfoFetch, mockGetPreauthInfo, iFrame, }; }; test('should call InfoSuccess Event on preauth call success', async () => { const { mockPreauthInfoFetch, iFrame, } = await setup(true); expect(mockPreauthInfoFetch).toHaveBeenCalledTimes(1); await (0, test_utils_1.executeAfterWait)(() => { expect(mockProcessTrigger).toHaveBeenCalledWith(iFrame, types_1.HostEvent.InfoSuccess, 'http://tshost', expect.objectContaining({ info: expect.any(Object) })); }); }); test('should not call InfoSuccess Event if overrideOrgId is true', async () => { const { mockGetPreauthInfo, } = await setup(true, 123); expect(moc