Skip to content

Commit

Permalink
test: popup.ts & minor changes
Browse files Browse the repository at this point in the history
JIRA: UUI-767
  • Loading branch information
michal-oleniacz-stp committed Feb 27, 2024
1 parent bb5b223 commit 4375980
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 57 deletions.
114 changes: 80 additions & 34 deletions __tests__/popup.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,137 @@
'use strict';

// @ts-nocheck

import * as popup from '../src/utils/popup';
import { ENDPOINTS } from '../src/config/config';
import { ForceMutable } from './utils';

const TEST_URL_INVALID = 'invalid url';
const TEST_URL_VALID = ENDPOINTS.SPiD.DEV;

const SCREEN: Screen = {
availHeight: 0,
availWidth: 0,
colorDepth: 0,
height: 0,
orientation: screen.orientation,
pixelDepth: 0,
width: 0,
};

describe('Popup — open', () => {
let mockWindow: ForceMutable<Window>;
beforeEach(() => {
// shallow copy of window
mockWindow = { ...window };
});

const defaultFeatures = 'scrollbars=yes,location=yes,status=no,menubar=no,toolbar=no,resizable=yes';

test('Fails if window undefined', () => {
// @ts-expect-error
expect(() => popup.open())
.toThrow(/window was supposed to be an object but it is undefined/);
});

test('Fails if window lacks "screen"', () => {
const window = {};
expect(() => popup.open(window))
delete (mockWindow as Partial<ForceMutable<Window>>).screen;

expect(() => popup.open(mockWindow, TEST_URL_VALID))
.toThrow(/window should be a valid Window object but it lacks a 'screen' property/);
});

test('Fails if window lacks "open"', () => {
const window = { screen: {} };
expect(() => popup.open(window))
mockWindow.screen = SCREEN;
delete (mockWindow as Partial<ForceMutable<Window>>).open;

expect(() => popup.open(mockWindow, TEST_URL_VALID))
.toThrow(/window should be a valid Window object but it lacks an 'open' function/);
});

test('Fails if url not valid', () => {
const window = { screen: {}, open: () => {} };
expect(() => popup.open(window)).toThrow(/Invalid URL for popup/);
mockWindow.screen = SCREEN;

expect(() => popup.open(mockWindow, TEST_URL_INVALID)).toThrow(/Invalid URL for popup/);
});

test('Works with valid window and url', () => {
return new Promise((resolve) => {
const open = (url, windowName, features) => {
expect(url).toBe('http://example.com');
const open = (url: string, windowName: string, features: string) => {
expect(url).toBe(TEST_URL_VALID);
expect(windowName).toBe('');
expect(features)
.toBe(defaultFeatures);
resolve();
resolve('');
};
const window = { screen: {}, open };
popup.open(window, 'http://example.com');
const spy = jest.fn().mockImplementation(open);

mockWindow.screen = SCREEN;
mockWindow.open = spy;
popup.open(mockWindow, TEST_URL_VALID);
});
});

test('Works with valid window, url and windowName', () => {
const EXPECTED_WINDOW_NAME = 'FooBar';

return new Promise((resolve) => {
const open = (url, windowName, features) => {
expect(url).toBe('http://example.com');
expect(windowName).toBe('FooBar');
const open = (url: string, windowName: string, features: string) => {
expect(url).toBe(TEST_URL_VALID);
expect(windowName).toBe(EXPECTED_WINDOW_NAME);
expect(features)
.toBe(defaultFeatures);
resolve();
resolve('');
};
const window = { screen: {}, open };
popup.open(window, 'http://example.com', 'FooBar');
const spy = jest.fn().mockImplementation(open);

mockWindow.screen = SCREEN;
mockWindow.open = spy;
popup.open(mockWindow, TEST_URL_VALID, EXPECTED_WINDOW_NAME);
});
});

test('Works with valid window, url, windowName and features', () => {
const EXPECTED_WINDOW_NAME = 'FooBar';
const FEATURES = { foo: 'bar' };

return new Promise((resolve) => {
const open = (url, windowName, features) => {
expect(url).toBe('http://example.com');
expect(windowName).toBe('FooBar');
const open = (url: string, windowName: string, features: string) => {
expect(url).toBe(TEST_URL_VALID);
expect(windowName).toBe(EXPECTED_WINDOW_NAME);
expect(features)
.toBe(defaultFeatures + ',foo=bar');
resolve();
resolve('');
};
const window = { screen: {}, open };
popup.open(window, 'http://example.com', 'FooBar', { foo: 'bar' });
const spy = jest.fn().mockImplementation(open);

mockWindow.screen = SCREEN;
mockWindow.open = spy;
popup.open(mockWindow, TEST_URL_VALID, EXPECTED_WINDOW_NAME, FEATURES);
});
});

test('Works with valid window, url, windowName, features and setting left+right', () => {
const EXPECTED_WINDOW_NAME = 'FooBar';

return new Promise((resolve) => {
const screen = { width: 400, height: 300 };
const screenSetup = { width: 400, height: 300 };
const desiredFeatures = { width: 100, height: 200 };
const open = (url, windowName, features) => {
expect(url).toBe('http://example.com');
expect(windowName).toBe('FooBar');
const left = (screen.width - desiredFeatures.width) / 2;
const top = (screen.height - desiredFeatures.height) / 2;
const open = (url: string, windowName: string, features: string) => {
expect(url).toBe(TEST_URL_VALID);
expect(windowName).toBe(EXPECTED_WINDOW_NAME);
const left = (screenSetup.width - desiredFeatures.width) / 2;
const top = (screenSetup.height - desiredFeatures.height) / 2;
expect(features)
.toBe(defaultFeatures + `,width=100,height=200,left=${left},top=${top}`);
resolve();
resolve('');
};
const spy = jest.fn().mockImplementation(open);

mockWindow.screen = {
...SCREEN,
...screenSetup,
};
const window = { screen, open };
popup.open(window, 'http://example.com', 'FooBar', desiredFeatures);
mockWindow.open = spy;
popup.open(mockWindow, TEST_URL_VALID, EXPECTED_WINDOW_NAME, desiredFeatures);
});
});
});
19 changes: 12 additions & 7 deletions __tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
* See LICENSE.md in the project root.
*/

// @ts-nocheck
export type ForceMutable<T> = {
-readonly [K in keyof T]: T[K];
};

export const throwingFnMsg = 'TEST THROW';
export const throwingFn = () => { throw new Error(throwingFnMsg);};

function stringify(search) {
function stringifySearchParams(search: URLSearchParams): string {
const keys = [...new Set(search.keys())];
keys.sort();
return keys.map(k => {
Expand All @@ -20,7 +25,7 @@ function stringify(search) {
* @param {string} second - the second url
* @return {Array} - returns the URL objects that are made from first and second
*/
export function compareUrls(first, second) {
export function compareUrls(first: string, second: string): URL[] {
const firstUrl = new URL(first);
const secondUrl = new URL(second);
expect(firstUrl).toBeDefined();
Expand All @@ -35,7 +40,7 @@ export function compareUrls(first, second) {
expect(firstUrl.pathname).toBe(secondUrl.pathname);
expect(firstUrl.port).toBe(secondUrl.port);
expect(firstUrl.protocol).toBe(secondUrl.protocol);
expect(stringify(firstUrl.searchParams)).toEqual(stringify(secondUrl.searchParams));
expect(stringifySearchParams(firstUrl.searchParams)).toEqual(stringifySearchParams(secondUrl.searchParams));
return [firstUrl, secondUrl];
}

Expand All @@ -62,11 +67,11 @@ const sessionResponse = {
};
const sessionServiceAccess = {
entitled: true,
allowedFeatures: ["existing"],
allowedFeatures: ['existing'],
ttl: 10,
userId: 12345,
uuid: 'aaaaaaaa-de42-5c4b-80ee-eeeeeeeeeeee',
sig: 'ZUtX5e7WJcLl69m-puKJlFc413ZPi7wnMLTa_M9TFiU.eyJlbnRpdGxlZCI6dHJ1ZSwiYWxsb3dlZEZlYXR1cmVzIjpbImZlYXR1cmUtMSIsInByb2R1Y3RpZC0xIl0sInR0bCI6MTAsInVzZXJJZCI6MTIzNDUsInV1aWQiOiJ1c2VyVXVpZCIsImFsZ29yaXRobSI6IkhNQUMtU0hBMjU2In0'
sig: 'ZUtX5e7WJcLl69m-puKJlFc413ZPi7wnMLTa_M9TFiU.eyJlbnRpdGxlZCI6dHJ1ZSwiYWxsb3dlZEZlYXR1cmVzIjpbImZlYXR1cmUtMSIsInByb2R1Y3RpZC0xIl0sInR0bCI6MTAsInVzZXJJZCI6MTIzNDUsInV1aWQiOiJ1c2VyVXVpZCIsImFsZ29yaXRobSI6IkhNQUMtU0hBMjU2In0',
};

const sessionServiceNoAccess = {
Expand All @@ -75,7 +80,7 @@ const sessionServiceNoAccess = {
ttl: 0,
userId: 12345,
uuid: 'aaaaaaaa-de42-5c4b-80ee-eeeeeeeeeeee',
sig: 'Rqf5fQ-gXNOdrsegajNgTOzju5z9-0v92v-PGCnL5P8.eyJlbnRpdGxlZCI6ZmFsc2UsImFsbG93ZWRGZWF0dXJlcyI6W10sInR0bCI6MCwidXNlcklkIjoxMjM0NSwidXVpZCI6InVzZXJVdWlkIiwiYWxnb3JpdGhtIjoiSE1BQy1TSEEyNTYifQ'
sig: 'Rqf5fQ-gXNOdrsegajNgTOzju5z9-0v92v-PGCnL5P8.eyJlbnRpdGxlZCI6ZmFsc2UsImFsbG93ZWRGZWF0dXJlcyI6W10sInR0bCI6MCwidXNlcklkIjoxMjM0NSwidXVpZCI6InVzZXJVdWlkIiwiYWxnb3JpdGhtIjoiSE1BQy1TSEEyNTYifQ',
};

export const Fixtures = {
Expand Down
7 changes: 4 additions & 3 deletions src/clients/RESTClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,13 @@ export class RESTClient {
logFn(this.log!, 'Request:', fetchOptions.method?.toUpperCase(), fullUrl);
logFn(this.log!, 'Request Headers:', fetchOptions.headers);
logFn(this.log!, 'Request Body:', fetchOptions.body);

try {
const response = await this.fetch!(fullUrl, fetchOptions);
logFn(this.log!, 'Response Code:', response.status, response.statusText);
if (!response.ok) {
// status code not in range 200-299
throw new SDKError(`API call failed with: ${response.code} ${response.statusText}`);
throw new SDKError(`API call failed with: ${response.code} ${response.statusText}`, { code: response.code});

Check failure on line 169 in src/clients/RESTClient.ts

View workflow job for this annotation

GitHub Actions / Run js tests

A space is required before '}'
}
const responseObject = await response.json();
logFn(this.log!, 'Response Parsed:', responseObject);
Expand Down Expand Up @@ -213,8 +214,8 @@ export class RESTClient {
* @param {object} defaultParams - Default params
* @returns {string} Query string
*/
static search(query: GenericObject, useDefaultParams: boolean, defaultParams: GenericObject) {
const params = useDefaultParams ? cloneDefined(defaultParams, query) : cloneDefined(query);
static search(query: GenericObject, useDefaultParams?: boolean, defaultParams?: GenericObject) {
const params = useDefaultParams ? cloneDefined(defaultParams || {}, query) : cloneDefined(query);
return Object.keys(params)
.filter(p => params[p] !== '')
.map(p => `${encode(p)}=${encode(params[p] as string)}`)
Expand Down
28 changes: 15 additions & 13 deletions src/utils/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
import { assert, isObject, isUrl, isFunction } from './validate';
import { GenericObject } from './types';

type FeatureActivation = 'yes' | 'no';

interface WindowFeatures {
left?: number;
top?: number;
width?: number;
height?: number;
menubar?: boolean;
toolbar?: boolean;
location?: boolean;
status?: boolean;
resizable?: boolean;
scrollbars?: boolean;
menubar?: FeatureActivation;
toolbar?: FeatureActivation;
location?: FeatureActivation;
status?: FeatureActivation;
resizable?: FeatureActivation;
scrollbars?: FeatureActivation;
[key: string]: unknown
}

Expand All @@ -33,12 +35,12 @@ function serialize(obj: GenericObject) {
}

const defaultWindowFeatures: WindowFeatures = {
scrollbars: true,
location: true,
status: false,
menubar: false,
toolbar: false,
resizable: true,
scrollbars: 'yes',
location: 'yes',
status: 'no',
menubar: 'no',
toolbar: 'no',
resizable: 'yes',
};

/**
Expand Down Expand Up @@ -66,6 +68,6 @@ export function open(parentWindow: Window, url: string, windowName = '', windowF
if (Number.isFinite(windowFeatures.height) && Number.isFinite(height)) {
windowFeatures.top = (height - (windowFeatures.height || 0)) / 2;
}
const features = serialize(windowFeatures);
const features = serialize({ ...defaultWindowFeatures, ...windowFeatures });
return parentWindow.open(url, windowName, features);
}

0 comments on commit 4375980

Please sign in to comment.