Skip to content

window undefined errors #200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/embed/base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
});
10 changes: 8 additions & 2 deletions src/embed/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<EmbedConfig> = {
Expand Down Expand Up @@ -197,7 +197,9 @@ export const createAndSetInitPromise = (): void => {
});
};

createAndSetInitPromise();
if (isBrowser()) {
createAndSetInitPromise();
}

export const getInitPromise = ():
Promise<
Expand Down Expand Up @@ -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(
Expand Down
71 changes: 71 additions & 0 deletions src/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
isUndefined,
storeValueInWindow,
getValueFromWindow,
isBrowser,
resetValueFromWindow,
} from './utils';
import { RuntimeFilterOp } from './types';

Expand Down Expand Up @@ -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;
});
});
17 changes: 15 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ export function storeValueInWindow<T>(
value: T,
options: { ignoreIfAlreadyExists?: boolean } = {},
): T {
if (!isBrowser()) {
return value;
}

if (!window[sdkWindowKey]) {
(window as any)[sdkWindowKey] = {};
}
Expand All @@ -371,8 +375,12 @@ export function storeValueInWindow<T>(
* @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 = <T = any>
(key: string): T => (window as any)?.[sdkWindowKey]?.[key];
export const getValueFromWindow = <T = any>(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.
Expand All @@ -381,9 +389,14 @@ export const getValueFromWindow = <T = any>
* @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';
Loading