Cb 5198 unit tests (#2674)

* CB-5198 adds errorOf unit test

* CB-5198 adds unit tests for metadata map

* CB-5198 open centered popup covered with unit tests

* CB-5198 removed unused utils helper

* CB-5198 adds unit tests for utf8 to base64 helper

* СB-5198 adds unit tests fro TempMap

* СB-5198 adds unit tests for GlobalConstants

* CB-5198 removes unused helper

* CB-5198 fix: unit tests for global consts

* СB-5198 adds unit tests for ILoadableState

* СB-5198 adds unit tests for CancellablePromise and cancellableTimeout

* CB-5198 unit tests cleanup

* CB-5198 unit tests cleanup

* CB-5198 updates TS references

* CB-5198 adds PR fixes

* CB-5186 cleanup

* CB-5198 adds correct window object mock for global consts tests

* Revert "CB-5198 updates TS references"

This reverts commit 9388477a79.

* CB-5198 fixes PR comments

* CB-5198 fixes PR comments

* CB-4760 fix: metadatamap return non observed values correctly

---------

Co-authored-by: Alexey <wrouds@gmail.com>
This commit is contained in:
sergeyteleshev
2024-06-10 16:52:08 +03:00
committed by GitHub
co-authored by Alexey
parent f04c2b1452
commit dc0e3075fa
16 changed files with 1016 additions and 83 deletions
@@ -0,0 +1,129 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { GlobalConstants } from './GlobalConstants';
jest.mock('./isValidUrl', () => ({
isValidUrl: jest.fn().mockReturnValue(false),
}));
jest.mock('./pathJoin', () => ({
pathJoin: jest.fn((...args: string[]) => args.reduce((acc, arg) => acc + arg, '')),
}));
describe('GlobalConstants', () => {
let windowSpy: jest.SpyInstance;
beforeEach(() => {
windowSpy = jest.spyOn(window, 'window', 'get');
});
afterEach(() => {
windowSpy.mockRestore();
});
beforeEach(() => {
(global as any)._DEV_ = true;
(global as any)._VERSION_ = '1.0.0';
(global as any)._ROOT_URI_ = '{ROOT_URI}';
windowSpy.mockImplementation(
() =>
({
location: {
protocol: 'http:',
host: 'localhost',
},
}) as any,
);
});
it('should return correct dev value', () => {
expect(GlobalConstants.dev).toBe(true);
});
it('should return correct version value', () => {
expect(GlobalConstants.version).toBe('1.0.0');
});
it('should return correct protocol value', () => {
expect(GlobalConstants.protocol).toBe('http:');
});
it('should return correct host value', () => {
expect(GlobalConstants.host).toBe('localhost');
});
it('should return correct websocket protocol', () => {
expect(GlobalConstants.wsProtocol).toBe('ws:');
windowSpy.mockImplementationOnce(
() =>
({
location: {
protocol: 'https:',
},
}) as any,
);
expect(GlobalConstants.wsProtocol).toBe('wss:');
});
it('should return correct rootURI value', () => {
expect(GlobalConstants.rootURI).toBe('/');
(global as any)._ROOT_URI_ = 'http://localhost:8080';
(require('./isValidUrl').isValidUrl as jest.Mock).mockReturnValueOnce(true);
expect(GlobalConstants.rootURI).toBe('/');
(global as any)._ROOT_URI_ = '/dbeaver';
expect(GlobalConstants.rootURI).toBe('/dbeaver/');
});
it('should return correct serviceURI value', () => {
expect(GlobalConstants.serviceURI).toBe('/api');
});
it('should return correct health check url', () => {
expect(GlobalConstants.getHealthCheckUrl('http://localhost')).toBe('http://localhost/status');
expect(GlobalConstants.getHealthCheckUrl('')).toBe('/status');
});
it('should generate absolute root url', () => {
expect(GlobalConstants.absoluteRootUrl('test/', 'test2')).toBe('/test/test2');
});
it('should generate absolute service url', () => {
expect(GlobalConstants.absoluteServiceUrl('/test/', 'test2')).toBe('/api/test/test2');
});
it('should generate absoluteServiceHTTPUrl', () => {
expect(GlobalConstants.absoluteServiceHTTPUrl('/test/', 'test2')).toBe('http://localhost/api/test/test2');
});
it('should generate absoluteServiceWSUrl', () => {
expect(GlobalConstants.absoluteServiceWSUrl('/test/', 'test2')).toBe('ws://localhost/api/test/test2');
windowSpy.mockImplementationOnce(
() =>
({
location: {
protocol: 'https:',
host: 'localhost',
},
}) as any,
);
expect(GlobalConstants.absoluteServiceWSUrl('/test/', 'test2')).toBe('wss://localhost/api/test/test2');
});
it('should generate absolute url', () => {
expect(GlobalConstants.absoluteUrl('test/', 'test2')).toBe('/test/test2');
expect(GlobalConstants.absoluteUrl('platform:test/', 'test2')).toBe('/apiimagesplatform:test/test2');
});
});
@@ -0,0 +1,135 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { getFirstException, ILoadableState, isContainsException, isLoadableStateHasException } from './ILoadableState';
const getMockedLoadableState = (state: Partial<ILoadableState>): ILoadableState => ({
exception: null,
isLoading: () => false,
isLoaded: () => false,
isError: () => false,
load: () => undefined,
...state,
});
describe('isContainsException', () => {
it('should return true if exception is present', () => {
expect(isContainsException(new Error())).toBe(true);
});
it('should return false if exception is not present', () => {
expect(isContainsException(null)).toBe(false);
});
it('should check array of exceptions', () => {
expect(isContainsException([null, new Error()])).toBe(true);
expect(isContainsException([null, null])).toBe(false);
expect(isContainsException([])).toBe(false);
});
});
describe('getFirstException', () => {
it('should return first exception', () => {
const error = new Error();
const error2 = new Error('error2');
expect(getFirstException([null, error, error2])).toBe(error);
expect(getFirstException([null, error])).toBe(error);
expect(getFirstException([error])).toBe(error);
expect(getFirstException(error)).toBe(error);
});
it('should not get exception', () => {
expect(getFirstException([null, null])).toBe(null);
expect(getFirstException([null])).toBe(null);
expect(getFirstException([])).toBe(null);
expect(getFirstException(null)).toBe(null);
});
});
describe('isLoadableStateHasException', () => {
it('should return true if exception is present', () => {
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: [new Error(), new Error('error2')],
isError() {
return true;
},
}),
),
).toBe(true);
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: [new Error()],
isError() {
return true;
},
}),
),
).toBe(true);
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: new Error(),
isError() {
return true;
},
}),
),
).toBe(true);
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: [null, new Error()],
isError() {
return true;
},
}),
),
).toBe(true);
});
it('should return false if exception is not present', () => {
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: [],
isError() {
return false;
},
}),
),
).toBe(false);
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: null,
isError() {
return false;
},
}),
),
).toBe(false);
expect(
isLoadableStateHasException(
getMockedLoadableState({
exception: [null, null],
isError() {
return false;
},
}),
),
).toBe(false);
});
});
@@ -21,10 +21,6 @@ export interface ILoadableState {
cancel?: () => void;
}
// export function composeLoadableState(...states: ILoadableState[]): ILoadableState {
// }
export function isLoadableStateHasException(state: ILoadableState): boolean {
return isContainsException(state.exception);
}
@@ -0,0 +1,219 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { z } from 'zod';
import { MetadataMap } from './MetadataMap';
describe('MetadataMap', () => {
it('should create an empty map', () => {
const map = new MetadataMap<number, string>();
expect(map.size).toBe(0);
});
it('should sync items', () => {
const map = new MetadataMap<number, string>();
const emptyMap = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
[Infinity, 'infinity'],
[NaN, 'nan'],
];
map.sync(data);
emptyMap.sync([]);
data.forEach(([key, value]) => {
expect(map.get(key)).toBe(value);
});
expect(emptyMap.size).toBe(0);
});
it('should set items', () => {
const map = new MetadataMap<number, string>();
map.set(1, 'one');
map.set(2, 'two');
map.set(3, 'three');
map.set(Infinity, 'infinity');
map.set(NaN, 'nan');
expect(map.get(1)).toBe('one');
expect(map.get(2)).toBe('two');
expect(map.get(3)).toBe('three');
expect(map.get(Infinity)).toBe('infinity');
expect(map.get(NaN)).toBe('nan');
});
it('should throw an error if validation failed and no default value getter', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
expect(() => map.get(1, undefined, z.object({}))).toThrow();
});
it('should get function default value if validation failed', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
expect(map.get(1, key => `default ${key}`, z.object({}))).toBe('default 1');
});
it('should return default value for non existing element using default getter in constructor', () => {
const map = new MetadataMap<number, string>(key => `default ${key}`);
expect(map.get(1)).toBe('default 1');
expect(map.get(Infinity)).toBe('default Infinity');
expect(map.get(NaN)).toBe('default NaN');
});
it('should return size', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
expect(map.size).toBe(3);
});
it('should return iterator', () => {
const map = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
];
map.sync(data);
for (const [key, value] of map) {
expect(map.get(key)).toBe(value);
}
});
it('should iterate keys', () => {
const map = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
];
const keys = data.map(([key]) => key);
map.sync(data);
for (const key of map.keys()) {
expect(key).toBe(keys.shift());
}
});
it('should iterate values', () => {
const map = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
];
const values = data.map(([, value]) => value);
map.sync(data);
for (const value of map.values()) {
expect(value).toBe(values.shift());
}
});
it('should iterate entries', () => {
const map = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
];
map.sync(data);
for (const [key, value] of map.entries()) {
expect([key, value]).toStrictEqual(data.shift());
}
});
it('should check if key exists', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
expect(map.has(1)).toBeTruthy();
expect(map.has(2)).toBeTruthy();
expect(map.has(3)).toBeTruthy();
expect(map.has(4)).toBeFalsy();
});
it('should clear', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
map.clear();
expect(map.size).toBe(0);
});
it('should delete items', () => {
const map = new MetadataMap<number, string>();
const data: [number, string][] = [
[1, 'one'],
[2, 'two'],
[3, 'three'],
];
map.sync(data);
map.delete(2);
map.delete(4);
data.splice(1, 1);
expect(map.has(2)).toBeFalsy();
expect(Array.from(map)).toEqual(data);
});
it('should forEach', () => {
const map = new MetadataMap<number, string>();
map.sync([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
map.forEach((value, key) => {
expect(map.get(key)).toBe(value);
});
});
it('has to string tag', () => {
const map = new MetadataMap<number, string>();
expect(map[Symbol.toStringTag]).toBe('MetadataMap');
});
});
@@ -75,6 +75,8 @@ export class MetadataMap<TKey, TValue> implements Map<TKey, TValue> {
return this;
}
// TODO replace zod schema with just validation callback returning true/false.
// In case we use something else than zod
get(key: TKey, defaultValue?: DefaultValueGetter<TKey, TValue>, schema?: schema.AnyZodObject): TValue {
const value = this.temp.get(key);
let invalidate = !this.temp.has(key);
@@ -95,7 +97,9 @@ export class MetadataMap<TKey, TValue> implements Map<TKey, TValue> {
}
const value = provider(key, this);
this.temp.set(key, observable(value as any));
const isNotPrimitiveValue = typeof value === 'object' && value !== null;
this.temp.set(key, isNotPrimitiveValue ? observable(value) : value);
}
return this.temp.get(key)!;
@@ -0,0 +1,52 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { CancellablePromise } from './CancellablePromise';
import { PromiseCancelledError } from './PromiseCancelledError';
describe('CancellablePromise', () => {
jest.mock('./PromiseCancelledError', () => ({
PromiseCancelledError: jest.fn(),
}));
it('cancels promise', async () => {
const PromiseCancelledErrorMockInstance = new PromiseCancelledError();
const promise = new CancellablePromise<void>(resolve => {
const token = setTimeout(() => resolve(), 0);
return () => {
clearTimeout(token);
};
});
promise.cancel();
await expect(promise).rejects.toThrow(PromiseCancelledErrorMockInstance);
});
it('should resolve promise', async () => {
const promise = new CancellablePromise<number>(resolve => {
const token = setTimeout(() => resolve(777), 0);
return () => {
clearTimeout(token);
};
});
await expect(promise).resolves.toBe(777);
});
it('should reject promise', async () => {
const error = new Error('test');
const promise = new CancellablePromise<number>((resolve, reject) => {
const token = setTimeout(() => reject(error), 0);
return () => {
clearTimeout(token);
};
});
await expect(promise).rejects.toThrow(error);
});
});
@@ -0,0 +1,31 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { cancellableTimeout } from './cancellableTimeout';
jest.mock('./CancellablePromise', () => ({
CancellablePromise: jest.fn().mockImplementation(() => ({
cancel: jest.fn(),
})),
}));
describe('cancellableTimeout', () => {
jest.useFakeTimers();
it('resolves after the specified timeout', async () => {
const timeout = 0;
const start = Date.now();
const promise = cancellableTimeout(timeout);
await promise;
jest.advanceTimersByTime(timeout);
expect(Date.now() - start).toBe(timeout);
});
});
@@ -0,0 +1,17 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { CancellablePromise } from './CancellablePromise';
export function cancellableTimeout(timeout: number): CancellablePromise<void> {
return new CancellablePromise<void>(resolve => {
const token = setTimeout(() => resolve(), timeout);
return () => {
clearTimeout(token);
};
});
}
@@ -1,35 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { CancellablePromise } from './CancellablePromise';
type PromiseExecutor<T> = (resolve: (value: T) => void, reject: (reason?: any) => void) => void;
/**
* wait timeout milliseconds then start to execute promise.
* During the timeout the execution of promise can be cancelled.
*
* @param executor
* @param timeout
*/
export function deferPromise<T>(executor: PromiseExecutor<T>, timeout: number): CancellablePromise<T> {
return new CancellablePromise<T>((resolve, reject) => {
const token = setTimeout(() => executor(resolve, reject), timeout);
return () => {
clearTimeout(token);
};
});
}
export function cancellableTimeout(timeout: number): CancellablePromise<void> {
return new CancellablePromise<void>(resolve => {
const token = setTimeout(() => resolve(), timeout);
return () => {
clearTimeout(token);
};
});
}
@@ -0,0 +1,283 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { TempMap } from './TempMap';
describe('TempMap', () => {
it('should create empty map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
expect(map.size).toBe(0);
expect(target.size).toBe(0);
expect(Array.from(map.entries()).length).toBe(0);
});
it('should set and get values', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
expect(map.get('test')).toBe('test value');
expect(map.get('test2')).toBe('test value2');
});
it('should delete values', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.delete('test');
expect(map.get('test')).toBeUndefined();
expect(map.isDeleted('test')).toBe(true);
});
it('should clear values', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
map.clear();
expect(map.get('test')).toBeUndefined();
expect(map.get('test2')).toBeUndefined();
});
it('should delete deleted values after map being cleared', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.delete('test');
expect(map.isDeleted('test')).toBe(true);
map.clear();
expect(map.get('test')).toBeUndefined();
expect(map.isDeleted('test')).toBe(false);
});
it('should remove item from deleted map if it was set again', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.delete('test');
expect(map.isDeleted('test')).toBe(true);
map.set('test', 'test value2');
expect(map.get('test')).toBe('test value2');
expect(map.isDeleted('test')).toBe(false);
});
it('should have for each items', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
const values: string[] = [];
const keys: string[] = [];
map.forEach((value, key) => {
values.push(value);
keys.push(key);
});
expect(values).toEqual(['test value', 'test value2']);
expect(keys).toEqual(['test', 'test2']);
});
it('should for each items and not include deleted', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
map.delete('test');
const values: string[] = [];
const keys: string[] = [];
map.forEach((value, key) => {
values.push(value);
keys.push(key);
});
expect(values).toEqual(['test value2']);
expect(keys).toEqual(['test2']);
expect(map.isDeleted('test')).toBe(true);
});
it('should check if key exists in the map', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
map.delete('test');
expect(map.has('test')).toBe(false);
expect(map.has('test2')).toBe(true);
});
it('should get keys', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
expect(Array.from(map.keys())).toEqual(['test', 'test2']);
});
it('should get values', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
expect(Array.from(map.values())).toEqual(['test value', 'test value2']);
});
it('should get entries', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
expect(Array.from(map.entries())).toEqual([
['test', 'test value'],
['test2', 'test value2'],
]);
});
it('should get size', () => {
const map = new TempMap<string, string>(new Map());
map.set('test', 'test value');
map.set('test2', 'test value2');
expect(map.size).toBe(2);
});
it('should only delete target value', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
map.set('test', 'test value');
target.delete('test');
expect(map.get('test')).toBe('test value');
expect(target.get('test')).toBeUndefined();
});
it('should set target value and also be available in temp map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
expect(map.get('test')).toBe('test value2');
expect(target.get('test')).toBe('test value2');
});
it('should combine keys from target and temp map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
map.set('test2', 'test value');
expect(Array.from(map.keys())).toEqual(['test', 'test2']);
});
it('should combine entries from target and temp map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
map.set('test2', 'test value');
expect(Array.from(map.entries())).toEqual([
['test', 'test value2'],
['test2', 'test value'],
]);
});
it('should combine values from target and temp map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
map.set('test2', 'test value');
expect(Array.from(map.values())).toEqual(['test value2', 'test value']);
});
it('should has target value in temp map', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
expect(map.has('test')).toBe(true);
});
it('should be iterable', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
target.set('test', 'test value2');
map.set('test2', 'test value');
const values: string[] = [];
const keys: string[] = [];
for (const [key, value] of map) {
values.push(value);
keys.push(key);
}
expect(values).toEqual(['test value2', 'test value']);
expect(keys).toEqual(['test', 'test2']);
});
it('should not get deleted keys', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
map.set('test', 'test value2');
map.set('test2', 'test value');
map.delete('test2');
expect(Array.from(map.keys())).toEqual(['test']);
});
it('should not get deleted values', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
map.set('test', 'test value2');
map.set('test2', 'test value');
map.delete('test2');
expect(Array.from(map.values())).toEqual(['test value2']);
});
it('should not get deleted entries', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
map.set('test', 'test value2');
map.set('test2', 'test value');
map.delete('test2');
expect(Array.from(map.entries())).toEqual([['test', 'test value2']]);
});
it('should has toStringTag', () => {
const target = new Map();
const map = new TempMap<string, string>(target);
expect(map[Symbol.toStringTag]).toBe('TempMap');
});
});
@@ -0,0 +1,56 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { errorOf } from './errorOf';
describe('errorOf', () => {
it('should return error of the specified type', () => {
class TestError extends Error {}
const error = new TestError('test');
const result = errorOf(error, TestError);
expect(result).toBe(error);
expect(result).toBeInstanceOf(TestError);
expect(result?.message).toBe('test');
});
it('should return error of the specified type from the cause', () => {
class TestError extends Error {}
class AnotherError extends Error {
cause: Error;
constructor(message: string, cause: Error) {
super(message);
this.cause = cause;
}
}
const error = new TestError('test');
const testError = new AnotherError('another', error);
const result = errorOf(testError, TestError);
expect(result).toBeInstanceOf(TestError);
});
it('should return undefined if error is not of the specified type', () => {
const error = new Error('test');
const result = errorOf(error, TypeError);
expect(result).toBeUndefined();
});
it('should return undefined if error is not an instance of Error', () => {
expect(errorOf({ message: 'test' }, Error)).toBeUndefined();
expect(errorOf(undefined, Error)).toBeUndefined();
expect(errorOf(null, Error)).toBeUndefined();
expect(errorOf(0, Error)).toBeUndefined();
expect(errorOf('', Error)).toBeUndefined();
expect(errorOf(true, Error)).toBeUndefined();
expect(errorOf(Symbol(), Error)).toBeUndefined();
});
});
+1 -3
View File
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
export * from './Promises/CancellablePromise';
export * from './Promises/deferPromise';
export * from './Promises/cancellableTimeout';
export * from './Promises/Deferred';
export * from './Promises/PromiseCancelledError';
export * from './Promises/PromiseExecutor';
@@ -72,7 +72,6 @@ export * from './createPath';
export * from './debounce';
export * from './schema';
export * from './schemaValidationError';
export * from './setByPath';
export * from './svgToDataUri';
export * from './TempMap';
export * from './textToHex';
@@ -80,7 +79,6 @@ export * from './uriToBlob';
export * from './utf8ToBase64';
export * from './createLastPromiseGetter';
export * from './removeMetadataFromDataURL';
export * from './renamePathName';
export * from './removeLineBreak';
export * from './replaceSubstring';
export * from './formatNumber';
@@ -0,0 +1,67 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { openCenteredPopup } from './openCenteredPopup';
describe('openCenteredPopup', () => {
let windowSpy: jest.SpyInstance;
const params = {
url: 'http://localhost:3000',
target: 'target',
width: 500,
height: 500,
features: 'features',
};
beforeEach(() => {
windowSpy = jest.spyOn(window, 'window', 'get');
});
afterEach(() => {
windowSpy.mockRestore();
});
it('should open centered popup', () => {
const windowMock = {
top: {
outerWidth: 1000,
screenY: 100,
screenX: 100,
outerHeight: 1000,
},
screen: {
availWidth: 1000,
},
open: jest.fn(),
};
windowSpy.mockImplementation(() => windowMock);
const { url, target, width, height, features } = params;
const result = openCenteredPopup({ url, target, width, height, features });
expect(result).toBe(windowMock.open());
expect(windowMock.open).toHaveBeenCalledWith(
url,
target,
`toolbar=no, menubar=no, width=${width}, height=${height}, top=350, left=350${features}`,
);
});
it('should return null if window.top is null', () => {
const { url, target, width, height, features } = params;
windowSpy.mockImplementation(() => ({
top: null,
}));
const result = openCenteredPopup({ url, target, width, height, features });
expect(result).toBe(null);
});
});
@@ -1,13 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createPath } from './createPath';
import { getPathParent } from './getPathParent';
export function renamePathName(path: string, name: string): string {
return createPath(getPathParent(path), name);
}
@@ -1,27 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export function setByPath(object: any, path: string, value: any) {
const parts = path.split('.');
const last = parts.pop();
if (!last) {
return;
}
let current = object;
for (const part of parts) {
if (current[part] === undefined) {
current[part] = {};
}
current = current[part];
}
current[last] = value;
}
@@ -0,0 +1,21 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { utf8ToBase64 } from './utf8ToBase64';
describe('utf8ToBase64', () => {
it('should convert utf8 to base64', () => {
expect(utf8ToBase64('test')).toBe('dGVzdA==');
expect(utf8ToBase64('')).toBe('');
expect(utf8ToBase64('test test')).toBe('dGVzdCB0ZXN0');
});
it('should convert utf8 to base64 with special characters', () => {
expect(utf8ToBase64('test % test')).toBe('dGVzdCAlIHRlc3Q=');
expect(utf8ToBase64('%')).toBe('JQ==');
});
});