Files
HIPCTF2/tests/frontend/admin-players.pure.spec.ts
T

100 lines
3.5 KiB
TypeScript

import {
adminPlayerApiErrorMessage,
extractFieldErrors,
isLastAdminError,
lastAdminMessage,
removePlayer,
replacePlayer,
toggleEnabled,
toggleRole,
} from '../../frontend/src/app/features/admin/admin-players.pure';
import { AdminUser } from '../../frontend/src/app/core/services/admin.service';
describe('admin-players.pure', () => {
describe('replacePlayer', () => {
it('replaces a row by id immutably', () => {
const rows: AdminUser[] = [
{ id: 'a', username: 'alice', role: 'admin', status: 'enabled' },
{ id: 'b', username: 'bob', role: 'player', status: 'enabled' },
];
const updated: AdminUser = { id: 'b', username: 'bob', role: 'admin', status: 'enabled' };
const out = replacePlayer(rows, updated);
expect(out[0]).toEqual(rows[0]);
expect(out[1]).toEqual(updated);
expect(out).not.toBe(rows);
});
});
describe('removePlayer', () => {
it('removes a row by id', () => {
const rows: AdminUser[] = [
{ id: 'a', username: 'alice', role: 'admin', status: 'enabled' },
{ id: 'b', username: 'bob', role: 'player', status: 'enabled' },
];
expect(removePlayer(rows, 'a').map((u) => u.id)).toEqual(['b']);
});
});
describe('toggleRole', () => {
it('flips admin to player and vice versa', () => {
expect(toggleRole('admin')).toBe('player');
expect(toggleRole('player')).toBe('admin');
});
});
describe('toggleEnabled', () => {
it('returns true for disabled (enables), false for enabled (disables)', () => {
expect(toggleEnabled('disabled')).toBe(true);
expect(toggleEnabled('enabled')).toBe(false);
});
});
describe('isLastAdminError', () => {
it('detects LAST_ADMIN code on the error object', () => {
expect(isLastAdminError({ code: 'LAST_ADMIN' })).toBe(true);
expect(isLastAdminError({ error: { code: 'LAST_ADMIN' } })).toBe(true);
expect(isLastAdminError({ response: { data: { code: 'LAST_ADMIN' } } })).toBe(true);
expect(isLastAdminError({ code: 'NOT_FOUND' })).toBe(false);
expect(isLastAdminError(null)).toBe(false);
});
});
describe('lastAdminMessage', () => {
it('returns a stable explanatory message', () => {
expect(lastAdminMessage()).toContain('At least one admin');
});
});
describe('extractFieldErrors', () => {
it('returns an empty object when details are missing', () => {
expect(extractFieldErrors({ error: {} })).toEqual({});
expect(extractFieldErrors(null)).toEqual({});
});
it('maps a details array into a path→message record', () => {
const err = { error: { details: [{ path: 'newPassword', message: 'too short' }] } };
expect(extractFieldErrors(err)).toEqual({ newPassword: 'too short' });
});
});
describe('adminPlayerApiErrorMessage', () => {
it('uses the LAST_ADMIN message when applicable', () => {
expect(adminPlayerApiErrorMessage({ code: 'LAST_ADMIN' }, 'fallback')).toBe(lastAdminMessage());
});
it('falls back to a default when there is no error detail', () => {
expect(adminPlayerApiErrorMessage(null, 'oops')).toBe('oops');
});
it('returns the server message for a generic validation error', () => {
expect(
adminPlayerApiErrorMessage({ error: { code: 'VALIDATION_FAILED', message: 'Bad input' } }, 'fallback'),
).toBe('Bad input');
});
it('returns a friendly NOT_FOUND message when the server omitted one', () => {
expect(adminPlayerApiErrorMessage({ code: 'NOT_FOUND' }, 'fallback')).toBe('User not found.');
});
});
});