diff --git a/src/embed/base.spec.ts b/src/embed/base.spec.ts index eb431cf5..da2b3508 100644 --- a/src/embed/base.spec.ts +++ b/src/embed/base.spec.ts @@ -506,4 +506,20 @@ describe('Init tests', () => { }); expect(resetService.resetAllCachedServices).toBeCalled(); }); + + test('returns empty object when not in browser environment', () => { + const originalWindow = global.window; + + // Delete window to simulate non-browser environment + delete global.window; + + const result = base.init({ + thoughtSpotHost, + authType: index.AuthType.None, + }); + + expect(result).toEqual({}); + + global.window = originalWindow; + }); }); diff --git a/src/embed/base.ts b/src/embed/base.ts index be19d011..4a12eb54 100644 --- a/src/embed/base.ts +++ b/src/embed/base.ts @@ -33,7 +33,7 @@ import { import '../utils/with-resolvers-polyfill'; import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service'; import { getEmbedConfig, setEmbedConfig } from './embedConfig'; -import { getQueryParamString, getValueFromWindow, storeValueInWindow } from '../utils'; +import { getQueryParamString, getValueFromWindow, isBrowser, storeValueInWindow } from '../utils'; import { resetAllCachedServices } from '../utils/resetServices'; const CONFIG_DEFAULTS: Partial = { @@ -197,7 +197,9 @@ export const createAndSetInitPromise = (): void => { }); }; -createAndSetInitPromise(); +if (isBrowser()) { + createAndSetInitPromise(); +} export const getInitPromise = (): Promise< @@ -227,6 +229,10 @@ export const getIsInitCalled = (): boolean => !!getValueFromWindow(initFlagKey)? * @group Authentication / Init */ export const init = (embedConfig: EmbedConfig): AuthEventEmitter => { + if (!isBrowser()) { + return {} as AuthEventEmitter; + } + sanity(embedConfig); resetAllCachedServices(); embedConfig = setEmbedConfig( diff --git a/src/utils.spec.ts b/src/utils.spec.ts index 0d9a0c6e..8223c824 100644 --- a/src/utils.spec.ts +++ b/src/utils.spec.ts @@ -13,6 +13,8 @@ import { isUndefined, storeValueInWindow, getValueFromWindow, + isBrowser, + resetValueFromWindow, } from './utils'; import { RuntimeFilterOp } from './types'; @@ -292,5 +294,74 @@ describe('unit test for utils', () => { test('Return undefined if key is not found', () => { expect(getValueFromWindow('notFound')).toBe(undefined); }); + + test('storeValueInWindow returns value when not in browser environment', () => { + const originalWindow = global.window; + delete global.window; + + const testValue = 'test-non-browser'; + const result = storeValueInWindow('testKey', testValue); + + expect(result).toBe(testValue); + + global.window = originalWindow; + }); + + test('getValueFromWindow returns undefined when not in browser environment', () => { + const originalWindow = global.window; + delete global.window; + + const result = getValueFromWindow('anyKey'); + + expect(result).toBeUndefined(); + + global.window = originalWindow; + }); + }); + + describe('resetValueFromWindow', () => { + test('returns true when key exists and is reset', () => { + storeValueInWindow('testResetKey', 'value-to-reset'); + + const result = resetValueFromWindow('testResetKey'); + + expect(result).toBe(true); + expect(getValueFromWindow('testResetKey')).toBeUndefined(); + }); + + test('returns false when key does not exist', () => { + const result = resetValueFromWindow('nonExistentKey'); + + expect(result).toBe(false); + }); + + test('returns false when not in browser environment', () => { + const originalWindow = global.window; + delete global.window; + + const result = resetValueFromWindow('anyKey'); + + expect(result).toBe(false); + + global.window = originalWindow; + }); + }); +}); + +describe('isBrowser', () => { + test('returns true when window is defined', () => { + // In Jest's JSDOM environment, window is defined + expect(isBrowser()).toBe(true); + }); + + test('returns false when window is undefined', () => { + const originalWindow = global.window; + + // Simulate non-browser environment by setting window to undefined + delete global.window; + + expect(isBrowser()).toBe(false); + + global.window = originalWindow; }); }); diff --git a/src/utils.ts b/src/utils.ts index 974d7eb7..578e45a2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -354,6 +354,10 @@ export function storeValueInWindow( value: T, options: { ignoreIfAlreadyExists?: boolean } = {}, ): T { + if (!isBrowser()) { + return value; + } + if (!window[sdkWindowKey]) { (window as any)[sdkWindowKey] = {}; } @@ -371,8 +375,12 @@ export function storeValueInWindow( * @param key - The key whose value needs to be retrieved. * @returns The stored value or `undefined` if the key is not found. */ -export const getValueFromWindow = - (key: string): T => (window as any)?.[sdkWindowKey]?.[key]; +export const getValueFromWindow = (key: string): T | undefined => { + if (!isBrowser()) { + return undefined; + } + return (window as any)?.[sdkWindowKey]?.[key]; +}; /** * Resets the key if it exists in the `window` object under the `_tsEmbedSDK` key. @@ -381,9 +389,14 @@ export const getValueFromWindow = * @returns - boolean indicating if the key was reset */ export function resetValueFromWindow(key: string): boolean { + if (!isBrowser()) { + return false; + } if (key in window[sdkWindowKey]) { delete (window as any)[sdkWindowKey][key]; return true; } return false; } + +export const isBrowser = () => typeof window !== 'undefined'; \ No newline at end of file