Files
Toju/toju-app/src/app/domains/server-directory/application/services/server-endpoint-state.service.spec.ts
Myx 53389ed3ad
All checks were successful
Queue Release Build / prepare (push) Successful in 23s
Deploy Web Apps / deploy (push) Successful in 5m54s
Queue Release Build / build-windows (push) Successful in 16m19s
Queue Release Build / build-linux (push) Successful in 30m13s
Queue Release Build / finalize (push) Successful in 47s
feat: Add game activity status (Experimental)
2026-04-27 05:46:33 +02:00

186 lines
6.1 KiB
TypeScript

import { Injector, runInInjectionContext } from '@angular/core';
import { environment } from '../../../../../environments/environment';
import type { ServerEndpoint } from '../../domain/models/server-directory.model';
import * as serverDirectoryStorageKeys from '../../infrastructure/constants/server-directory.infrastructure.constants';
import { ServerEndpointStorageService } from '../../infrastructure/services/server-endpoint-storage.service';
import { ServerEndpointStateService } from './server-endpoint-state.service';
function createLocalStorageMock(): Storage {
const store = new Map<string, string>();
return {
get length(): number {
return store.size;
},
clear(): void {
store.clear();
},
getItem(key: string): string | null {
return store.get(key) ?? null;
},
key(index: number): string | null {
return [...store.keys()][index] ?? null;
},
removeItem(key: string): void {
store.delete(key);
},
setItem(key: string, value: string): void {
store.set(key, value);
}
};
}
Object.defineProperty(globalThis, 'localStorage', {
value: createLocalStorageMock(),
configurable: true
});
function getConfiguredDefaultServer(key: string): { key?: string; name?: string; url?: string } {
const defaultServer = environment.defaultServers.find((server) => server.key === key);
if (!defaultServer) {
throw new Error(`Missing configured default server for key: ${key}`);
}
return defaultServer;
}
function seedStoredEndpoints(endpoints: ServerEndpoint[]): void {
localStorage.setItem(serverDirectoryStorageKeys.SERVER_ENDPOINTS_STORAGE_KEY, JSON.stringify(endpoints));
}
function createService(): ServerEndpointStateService {
const injector = Injector.create({
providers: [
{
provide: ServerEndpointStorageService,
useClass: ServerEndpointStorageService,
deps: []
}
]
});
return runInInjectionContext(injector, () => new ServerEndpointStateService());
}
function getRequiredDefaultEndpoint(service: ServerEndpointStateService, defaultKey: string | undefined): ServerEndpoint {
const endpoint = service.servers().find((candidate) => candidate.defaultKey === defaultKey);
if (!endpoint) {
throw new Error(`Expected default endpoint for key: ${defaultKey ?? 'unknown'}`);
}
return endpoint;
}
describe('ServerEndpointStateService', () => {
beforeEach(() => {
localStorage.clear();
});
it('reactivates configured default endpoints unless the user disabled them', () => {
const defaultServer = getConfiguredDefaultServer('toju-primary');
seedStoredEndpoints([
{
id: 'default-server',
name: 'Stored Default',
url: defaultServer.url ?? '',
isActive: false,
isDefault: true,
defaultKey: defaultServer.key,
status: 'unknown'
}
]);
const service = createService();
const endpoint = service.servers().find((candidate) => candidate.defaultKey === defaultServer.key);
expect(endpoint?.isActive).toBe(true);
});
it('keeps a configured default endpoint inactive after the user turned it off', () => {
const defaultServer = getConfiguredDefaultServer('toju-primary');
seedStoredEndpoints([
{
id: 'default-server',
name: 'Stored Default',
url: defaultServer.url ?? '',
isActive: true,
isDefault: true,
defaultKey: defaultServer.key,
status: 'unknown'
}
]);
localStorage.setItem(
serverDirectoryStorageKeys.DISABLED_DEFAULT_SERVER_KEYS_STORAGE_KEY,
JSON.stringify([defaultServer.key])
);
const service = createService();
const endpoint = service.servers().find((candidate) => candidate.defaultKey === defaultServer.key);
expect(endpoint?.isActive).toBe(false);
});
it('keeps configured default endpoints active even when stored as incompatible unless the user disabled them', () => {
const defaultServer = getConfiguredDefaultServer('toju-primary');
seedStoredEndpoints([
{
id: 'default-server',
name: 'Stored Default',
url: defaultServer.url ?? '',
isActive: false,
isDefault: true,
defaultKey: defaultServer.key,
status: 'incompatible'
}
]);
const service = createService();
const endpoint = service.servers().find((candidate) => candidate.defaultKey === defaultServer.key);
expect(endpoint?.isActive).toBe(true);
expect(endpoint?.status).toBe('incompatible');
});
it('does not deactivate configured default endpoints when compatibility checks fail', () => {
const defaultServer = getConfiguredDefaultServer('toju-primary');
const service = createService();
const endpoint = getRequiredDefaultEndpoint(service, defaultServer.key);
service.updateServerStatus(endpoint.id, 'incompatible');
expect(service.servers().find((candidate) => candidate.id === endpoint.id)?.isActive).toBe(true);
});
it('resolves legacy https source URLs to the local http default endpoint on the same host', () => {
const defaultServer = getConfiguredDefaultServer('default');
const service = createService();
const legacyHttpsUrl = defaultServer.url?.replace(/^http:\/\//, 'https://') ?? '';
expect(service.findServerByUrl(legacyHttpsUrl)?.url).toBe(defaultServer.url);
});
it('persists turning a configured default endpoint off and back on', () => {
const defaultServer = getConfiguredDefaultServer('toju-primary');
const service = createService();
const endpoint = getRequiredDefaultEndpoint(service, defaultServer.key);
service.deactivateServer(endpoint.id);
expect(service.servers().find((candidate) => candidate.id === endpoint.id)?.isActive).toBe(false);
expect(JSON.parse(
localStorage.getItem(serverDirectoryStorageKeys.DISABLED_DEFAULT_SERVER_KEYS_STORAGE_KEY) ?? '[]'
)).toContain(defaultServer.key);
service.setActiveServer(endpoint.id);
expect(service.servers().find((candidate) => candidate.id === endpoint.id)?.isActive).toBe(true);
expect(localStorage.getItem(serverDirectoryStorageKeys.DISABLED_DEFAULT_SERVER_KEYS_STORAGE_KEY)).toBeNull();
});
});