fix unit tests and refactor types

This commit is contained in:
seavor 2026-04-16 12:45:47 -05:00
parent decebc25c7
commit fea21b5057
75 changed files with 908 additions and 501 deletions

View file

@ -1,6 +1,7 @@
import { Selectors } from './rooms.selectors';
import { RoomsState } from './rooms.interfaces';
import { makeGame, makeMessage, makeRoom, makeRoomsState, makeUser } from './__mocks__/rooms-fixtures';
import { App } from '@app/types';
function rootState(rooms: RoomsState) {
return { rooms };
@ -111,13 +112,23 @@ describe('Selectors', () => {
expect(Selectors.getRoomUsers(rootState(state), 1)).toBe(room.users);
});
it('getSortedRoomGames → returns sorted array view of games map', () => {
const game1 = makeGame({ gameId: 1, description: 'beta' });
const game2 = makeGame({ gameId: 2, description: 'alpha' });
it('getSortedRoomGames → returns games sorted by the active sort config', () => {
const game1 = makeGame({ gameId: 1, description: 'Beta' });
const game2 = makeGame({ gameId: 2, description: 'Alpha' });
const room = makeRoom({ roomId: 1, games: { 1: game1, 2: game2 } });
const state = makeRoomsState({ rooms: { 1: room } });
const state = makeRoomsState({
rooms: { 1: room },
sortGamesBy: { field: 'info.description' as App.GameSortField, order: App.SortDirection.ASC },
});
const result = Selectors.getSortedRoomGames(rootState(state), 1);
expect(result).toHaveLength(2);
expect(result[0].info.description).toBe('Alpha');
expect(result[1].info.description).toBe('Beta');
});
it('getSortedRoomGames → returns EMPTY_GAMES for unknown roomId', () => {
const state = makeRoomsState({ rooms: {} });
expect(Selectors.getSortedRoomGames(rootState(state), 999)).toHaveLength(0);
});
it('getSortedRoomUsers → returns sorted user array sorted by name', () => {
@ -129,4 +140,40 @@ describe('Selectors', () => {
expect(result[0].name).toBe('Alice');
expect(result[1].name).toBe('Zane');
});
it('getSortedRoomUsers → returns EMPTY_USERS for unknown roomId', () => {
const state = makeRoomsState({ rooms: {} });
expect(Selectors.getSortedRoomUsers(rootState(state), 999)).toHaveLength(0);
});
// ── createSelector reference stability ──────────────────────────────
it('getSortedRoomGames → returns same array reference for identical state', () => {
const game = makeGame({ gameId: 1 });
const room = makeRoom({ roomId: 1, games: { 1: game } });
const state = makeRoomsState({ rooms: { 1: room } });
const root = rootState(state);
const a = Selectors.getSortedRoomGames(root, 1);
const b = Selectors.getSortedRoomGames(root, 1);
expect(a).toBe(b);
});
it('getSortedRoomUsers → returns same array reference for identical state', () => {
const user = makeUser({ name: 'Alice' });
const room = makeRoom({ roomId: 1, users: { Alice: user } });
const state = makeRoomsState({ rooms: { 1: room } });
const root = rootState(state);
const a = Selectors.getSortedRoomUsers(root, 1);
const b = Selectors.getSortedRoomUsers(root, 1);
expect(a).toBe(b);
});
it('getJoinedRooms → returns same array reference for identical state', () => {
const room = makeRoom({ roomId: 1 });
const state = makeRoomsState({ rooms: { 1: room }, joinedRoomIds: { 1: true } });
const root = rootState(state);
const a = Selectors.getJoinedRooms(root);
const b = Selectors.getJoinedRooms(root);
expect(a).toBe(b);
});
});

View file

@ -6,7 +6,7 @@ import {
makeServerState,
makeUser,
} from './__mocks__/server-fixtures';
import { App } from '@app/types';
import { App, Data } from '@app/types';
function rootState(server: ServerState) {
return { server };
@ -149,4 +149,86 @@ describe('Selectors', () => {
const state = makeServerState({ registrationError: 'bad input' });
expect(Selectors.getRegistrationError(rootState(state))).toBe('bad input');
});
// ── derived selectors (createSelector) ──────────────────────────────
it('getIsConnected → true when state is LOGGED_IN', () => {
const state = makeServerState({ status: { connectionAttemptMade: true, state: App.StatusEnum.LOGGED_IN, description: null } });
expect(Selectors.getIsConnected(rootState(state))).toBe(true);
});
it('getIsConnected → false when state is CONNECTED', () => {
const state = makeServerState({ status: { connectionAttemptMade: true, state: App.StatusEnum.CONNECTED, description: null } });
expect(Selectors.getIsConnected(rootState(state))).toBe(false);
});
it('getIsConnected → false when state is DISCONNECTED', () => {
const state = makeServerState({ status: { connectionAttemptMade: false, state: App.StatusEnum.DISCONNECTED, description: null } });
expect(Selectors.getIsConnected(rootState(state))).toBe(false);
});
it('getIsUserModerator → true when user has IsModerator flag', () => {
const Flag = Data.ServerInfo_User_UserLevelFlag;
const user = makeUser({ userLevel: Flag.IsUser | Flag.IsModerator });
const state = makeServerState({ user });
expect(Selectors.getIsUserModerator(rootState(state))).toBe(true);
});
it('getIsUserModerator → false when user lacks IsModerator flag', () => {
const Flag = Data.ServerInfo_User_UserLevelFlag;
const user = makeUser({ userLevel: Flag.IsUser | Flag.IsRegistered });
const state = makeServerState({ user });
expect(Selectors.getIsUserModerator(rootState(state))).toBe(false);
});
it('getIsUserModerator → false when user is null', () => {
const state = makeServerState({ user: null });
expect(Selectors.getIsUserModerator(rootState(state))).toBe(false);
});
// ── createSelector reference stability ──────────────────────────────
it('getIsConnected → returns same value reference for identical state', () => {
const state = makeServerState({ status: { connectionAttemptMade: true, state: App.StatusEnum.LOGGED_IN, description: null } });
const root = rootState(state);
const a = Selectors.getIsConnected(root);
const b = Selectors.getIsConnected(root);
expect(a).toBe(b);
});
it('getSortedUsers → returns same array reference for identical state', () => {
const users = { Alice: makeUser({ name: 'Alice' }), Bob: makeUser({ name: 'Bob' }) };
const state = makeServerState({ users });
const root = rootState(state);
const a = Selectors.getSortedUsers(root);
const b = Selectors.getSortedUsers(root);
expect(a).toBe(b);
});
it('getSortedBuddyList → returns same array reference for identical state', () => {
const buddyList = { Alice: makeUser({ name: 'Alice' }) };
const state = makeServerState({ buddyList });
const root = rootState(state);
const a = Selectors.getSortedBuddyList(root);
const b = Selectors.getSortedBuddyList(root);
expect(a).toBe(b);
});
it('getSortedIgnoreList → returns same array reference for identical state', () => {
const ignoreList = { Troll: makeUser({ name: 'Troll' }) };
const state = makeServerState({ ignoreList });
const root = rootState(state);
const a = Selectors.getSortedIgnoreList(root);
const b = Selectors.getSortedIgnoreList(root);
expect(a).toBe(b);
});
it('getReplaysList → returns same array reference for identical state', () => {
const replays = { 1: makeReplayMatch({ gameId: 1 }) };
const state = makeServerState({ replays });
const root = rootState(state);
const a = Selectors.getReplaysList(root);
const b = Selectors.getReplaysList(root);
expect(a).toBe(b);
});
});