mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Cb 5753 u tests (#2964)
* CB-5753 add localization service test, fix grammar * CB-5753 add test for the getDomainFromUrl * CB-5753 add test for the client activity service * CB-5753 add NodeManagerUtils tests * CB-5753 add more cases * CB-5753 pass args correctly
This commit is contained in:
@@ -15,7 +15,8 @@
|
||||
"clean": "rimraf --glob dist",
|
||||
"lint": "eslint ./src/ --ext .ts,.tsx",
|
||||
"validate-dependencies": "core-cli-validate-dependencies",
|
||||
"update-ts-references": "yarn run clean && typescript-resolve-references"
|
||||
"update-ts-references": "yarn run clean && typescript-resolve-references",
|
||||
"test": "core-cli-test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cloudbeaver/core-di": "^0",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
|
||||
|
||||
import { ClientActivityService, INACTIVE_PERIOD_TIME } from './ClientActivityService.js';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
describe('ClientActivityService', () => {
|
||||
let clientActivityService: ClientActivityService;
|
||||
|
||||
beforeEach(() => {
|
||||
clientActivityService = new ClientActivityService();
|
||||
|
||||
jest.spyOn(global, 'setTimeout');
|
||||
jest.spyOn(global, 'clearTimeout');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllTimers();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should initialize with isActive set to false', () => {
|
||||
expect(clientActivityService.isActive).toBe(false);
|
||||
});
|
||||
|
||||
it('should set isActive to true when updateActivity is called', () => {
|
||||
clientActivityService.updateActivity();
|
||||
expect(clientActivityService.isActive).toBe(true);
|
||||
});
|
||||
|
||||
it('should reset activity after the timeout period', () => {
|
||||
clientActivityService.updateActivity();
|
||||
expect(clientActivityService.isActive).toBe(true);
|
||||
|
||||
jest.advanceTimersByTime(INACTIVE_PERIOD_TIME);
|
||||
|
||||
expect(clientActivityService.isActive).toBe(false);
|
||||
});
|
||||
|
||||
it('should clear previous timer if updateActivity is called multiple times', () => {
|
||||
clientActivityService.updateActivity();
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
|
||||
jest.advanceTimersByTime(Math.random() * INACTIVE_PERIOD_TIME - 1);
|
||||
|
||||
clientActivityService.updateActivity();
|
||||
expect(clearTimeout).toHaveBeenCalledTimes(1);
|
||||
expect(setTimeout).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should clear timer and reset activity when resetActivity is called', () => {
|
||||
clientActivityService.updateActivity();
|
||||
|
||||
jest.advanceTimersByTime(Math.random() * INACTIVE_PERIOD_TIME - 1);
|
||||
|
||||
clientActivityService.resetActivity();
|
||||
|
||||
expect(clientActivityService.isActive).toBe(false);
|
||||
expect(clearTimeout).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call onActiveStateChange executor with correct value', () => {
|
||||
const onActiveStateChangeSpy = jest.spyOn(clientActivityService.onActiveStateChange, 'execute');
|
||||
|
||||
clientActivityService.updateActivity();
|
||||
expect(onActiveStateChangeSpy).toHaveBeenCalledWith(true);
|
||||
|
||||
jest.advanceTimersByTime(INACTIVE_PERIOD_TIME);
|
||||
expect(onActiveStateChangeSpy).toHaveBeenCalledWith(false);
|
||||
});
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import { makeObservable, observable } from 'mobx';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { Executor, type IExecutor } from '@cloudbeaver/core-executor';
|
||||
|
||||
const INACTIVE_PERIOD_TIME = 1000 * 60;
|
||||
export const INACTIVE_PERIOD_TIME = 1000 * 60;
|
||||
|
||||
@injectable()
|
||||
export class ClientActivityService {
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 { beforeEach, describe, expect, it } from '@jest/globals';
|
||||
|
||||
import { DEFAULT_LOCALE } from './DEFAULT_LOCALE.js';
|
||||
import { type ILocale } from './ILocale.js';
|
||||
import { LocalizationService } from './LocalizationService.js';
|
||||
|
||||
describe('LocalizationService', () => {
|
||||
let service: LocalizationService;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new LocalizationService();
|
||||
});
|
||||
|
||||
it('should initialize with default locale', () => {
|
||||
service.register();
|
||||
expect(service.currentLanguage).toBe(DEFAULT_LOCALE.isoCode);
|
||||
expect(service.supportedLanguages.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should set supported languages', () => {
|
||||
const locales: ILocale[] = [
|
||||
{ isoCode: 'de', name: 'German', nativeName: 'Deutsch' },
|
||||
{ isoCode: 'es', name: 'Spanish', nativeName: 'Español' },
|
||||
];
|
||||
|
||||
service.setSupportedLanguages(locales);
|
||||
expect(service.supportedLanguages.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should set default to first supported language', () => {
|
||||
const locales: ILocale[] = [
|
||||
{ isoCode: 'de', name: 'German', nativeName: 'Deutsch' },
|
||||
{ isoCode: 'es', name: 'Spanish', nativeName: 'Español' },
|
||||
];
|
||||
|
||||
service.setSupportedLanguages(locales);
|
||||
expect(service.currentLanguage).toBe('de');
|
||||
});
|
||||
|
||||
it('should return default locale if the current language is not supported', () => {
|
||||
service.setLanguage('es');
|
||||
expect(service.currentLanguage).toBe(DEFAULT_LOCALE.isoCode);
|
||||
});
|
||||
|
||||
it('should throw error if there are no supported languages', () => {
|
||||
service.supportedLanguages = [];
|
||||
expect(() => service.currentLanguage).toThrowError('No language is available');
|
||||
});
|
||||
|
||||
it('should change the current language', async () => {
|
||||
service.register();
|
||||
await service.changeLocale('ru');
|
||||
expect(service.currentLanguage).toBe('ru');
|
||||
});
|
||||
|
||||
it('should throw an error when changing to an unsupported language', async () => {
|
||||
await expect(service.changeLocale('jp')).rejects.toThrowError("Language 'jp' is not supported");
|
||||
});
|
||||
|
||||
it('should translate a token with a fallback', () => {
|
||||
const token = 'greeting';
|
||||
const fallback = 'Hello, World!';
|
||||
|
||||
service.changeLocale('en');
|
||||
service['localeMap'].set('en', new Map([[token, 'Hello']]));
|
||||
|
||||
const translation = service.translate(token, fallback);
|
||||
expect(translation).toBe('Hello');
|
||||
});
|
||||
|
||||
it('should return fallback when translation is missing', () => {
|
||||
const token = 'nonexistent_token';
|
||||
const fallback = 'Fallback';
|
||||
|
||||
const translation = service.translate(token, fallback);
|
||||
expect(translation).toBe(fallback);
|
||||
});
|
||||
|
||||
it('should replace args in the translation string', () => {
|
||||
const token = 'welcome_message';
|
||||
const translationString = 'Welcome, {arg:name}!';
|
||||
service['localeMap'].set('en', new Map([[token, translationString]]));
|
||||
service.setLanguage('en');
|
||||
|
||||
const translation = service.translate(token, undefined, { name: 'John' });
|
||||
expect(translation).toBe('Welcome, John!');
|
||||
});
|
||||
|
||||
it('should replace multiple args in the translation string', () => {
|
||||
const token = 'greeting_message';
|
||||
const translationString = 'Hello, {arg:firstName} {arg:lastName}!';
|
||||
service['localeMap'].set('en', new Map([[token, translationString]]));
|
||||
service.setLanguage('en');
|
||||
|
||||
const translation = service.translate(token, undefined, { firstName: 'John', lastName: 'Doe' });
|
||||
expect(translation).toBe('Hello, John Doe!');
|
||||
});
|
||||
|
||||
it('should return true for supported language', () => {
|
||||
service.register();
|
||||
|
||||
expect(service.isLanguageSupported('en')).toBe(true);
|
||||
expect(service.isLanguageSupported('ru')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for unsupported language', () => {
|
||||
service.register();
|
||||
|
||||
expect(service.isLanguageSupported('n/a')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -31,7 +31,8 @@ export class LocalizationService extends Bootstrap {
|
||||
const firstLanguage = this.supportedLanguages[0];
|
||||
|
||||
if (!firstLanguage) {
|
||||
throw new Error('No language is awailable');
|
||||
//@TODO do not throw error in getter
|
||||
throw new Error('No language is available');
|
||||
}
|
||||
|
||||
return firstLanguage.isoCode;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 { describe, expect, it } from '@jest/globals';
|
||||
|
||||
import { NodeManagerUtils } from './NodeManagerUtils.js';
|
||||
|
||||
describe('NodeManagerUtils', () => {
|
||||
describe('connectionIdToConnectionNodeId', () => {
|
||||
it('should prepend "database://" to the connectionId', () => {
|
||||
const connectionId = '12345';
|
||||
const result = NodeManagerUtils.connectionIdToConnectionNodeId(connectionId);
|
||||
expect(result).toBe('database://12345');
|
||||
});
|
||||
|
||||
it('should work with different connectionId values', () => {
|
||||
expect(NodeManagerUtils.connectionIdToConnectionNodeId('abc')).toBe('database://abc');
|
||||
expect(NodeManagerUtils.connectionIdToConnectionNodeId('')).toBe('database://');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDatabaseObject', () => {
|
||||
it('should return true for objectIds starting with "database://"', () => {
|
||||
expect(NodeManagerUtils.isDatabaseObject('database://123')).toBe(true);
|
||||
expect(NodeManagerUtils.isDatabaseObject('database://abc')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for objectIds not starting with "database://"', () => {
|
||||
expect(NodeManagerUtils.isDatabaseObject('http://example.com')).toBe(false);
|
||||
expect(NodeManagerUtils.isDatabaseObject('12345')).toBe(false);
|
||||
expect(NodeManagerUtils.isDatabaseObject('')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('concatSchemaAndCatalog', () => {
|
||||
it('should concatenate schemaId and catalogId with "@" when both are provided', () => {
|
||||
const result = NodeManagerUtils.concatSchemaAndCatalog('catalog1', 'schema1');
|
||||
expect(result).toBe('schema1@catalog1');
|
||||
});
|
||||
|
||||
it('should return just schemaId if catalogId is undefined', () => {
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog(undefined, 'schema1')).toBe('schema1');
|
||||
});
|
||||
|
||||
it('should return just catalogId if schemaId is undefined', () => {
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog('catalog1', undefined)).toBe('catalog1');
|
||||
});
|
||||
|
||||
it('should return an empty string if both are undefined', () => {
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog(undefined, undefined)).toBe('');
|
||||
});
|
||||
|
||||
it('should handle cases with empty strings', () => {
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog('', 'catalog1')).toBe('catalog1');
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog('schema1', '')).toBe('schema1');
|
||||
expect(NodeManagerUtils.concatSchemaAndCatalog('', '')).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 { describe, expect, it } from '@jest/globals';
|
||||
|
||||
import { getDomainFromUrl } from './getDomainFromUrl.js';
|
||||
|
||||
describe('getDomainFromUrl', () => {
|
||||
it('should return domain for a valid URL with http protocol', () => {
|
||||
const url = 'http://example.com/path';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('example.com');
|
||||
});
|
||||
|
||||
it('should return domain for a valid URL with https protocol', () => {
|
||||
const url = 'https://example.com/path';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('example.com');
|
||||
});
|
||||
|
||||
it('should return domain for a valid URL with www', () => {
|
||||
const url = 'https://www.example.com/path';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('www.example.com');
|
||||
});
|
||||
|
||||
it('should return domain for a URL with a subdomain', () => {
|
||||
const url = 'https://blog.example.com';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('blog.example.com');
|
||||
});
|
||||
|
||||
it('should return empty string for an invalid URL', () => {
|
||||
const url = 'not-a-valid-url';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('');
|
||||
});
|
||||
|
||||
it('should return empty string for an empty string input', () => {
|
||||
const url = '';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('');
|
||||
});
|
||||
|
||||
it('should return domain for a URL with query parameters', () => {
|
||||
const url = 'https://example.com/search?q=test';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('example.com');
|
||||
});
|
||||
|
||||
it('should return domain for a URL with port number', () => {
|
||||
const url = 'https://example.com:8080/path';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('example.com');
|
||||
});
|
||||
|
||||
it('should return domain for an IP address URL', () => {
|
||||
const url = 'http://127.0.0.1:3000';
|
||||
const domain = getDomainFromUrl(url);
|
||||
expect(domain).toBe('127.0.0.1');
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,6 @@ export function getDomainFromUrl(url: string): string {
|
||||
const urlObject = new URL(url);
|
||||
return urlObject.hostname;
|
||||
} catch (e) {
|
||||
console.error('Invalid URL:', e);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user