mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 08:14:47 -07:00
Fix various issues
This commit is contained in:
parent
3001925430
commit
c3ae4cffd6
21 changed files with 130 additions and 121 deletions
|
|
@ -149,6 +149,7 @@ export function makeServerState(overrides: Partial<ServerState> = {}): ServerSta
|
|||
adminNotes: {},
|
||||
replays: [],
|
||||
backendDecks: null,
|
||||
gamesOfUser: {},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ describe('Actions', () => {
|
|||
});
|
||||
|
||||
it('registrationSuccess', () => {
|
||||
expect(Actions.registrationSuccess()).toEqual({ type: Types.REGISTRATION_SUCCES });
|
||||
expect(Actions.registrationSuccess()).toEqual({ type: Types.REGISTRATION_SUCCESS });
|
||||
});
|
||||
|
||||
it('registrationFailed', () => {
|
||||
|
|
@ -203,14 +203,6 @@ describe('Actions', () => {
|
|||
expect(Actions.accountImageChanged(user)).toEqual({ type: Types.ACCOUNT_IMAGE_CHANGED, user });
|
||||
});
|
||||
|
||||
it('directMessageSent', () => {
|
||||
expect(Actions.directMessageSent('Eve', 'hi')).toEqual({
|
||||
type: Types.DIRECT_MESSAGE_SENT,
|
||||
userName: 'Eve',
|
||||
message: 'hi',
|
||||
});
|
||||
});
|
||||
|
||||
it('getUserInfo', () => {
|
||||
const userInfo = makeUser({ name: 'Frank' });
|
||||
expect(Actions.getUserInfo(userInfo)).toEqual({ type: Types.GET_USER_INFO, userInfo });
|
||||
|
|
@ -353,4 +345,9 @@ describe('Actions', () => {
|
|||
it('deckDelete', () => {
|
||||
expect(Actions.deckDelete(42)).toEqual({ type: Types.DECK_DELETE, deckId: 42 });
|
||||
});
|
||||
|
||||
it('gamesOfUser', () => {
|
||||
const games = [{ gameId: 1 }] as any;
|
||||
expect(Actions.gamesOfUser('alice', games)).toEqual({ type: Types.GAMES_OF_USER, userName: 'alice', games });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DeckList, DeckStorageTreeItem, ReplayMatch, WebSocketConnectOptions } from 'types';
|
||||
import { DeckList, DeckStorageTreeItem, Game, ReplayMatch, WebSocketConnectOptions } from 'types';
|
||||
import { Types } from './server.types';
|
||||
|
||||
export const Actions = {
|
||||
|
|
@ -91,7 +91,7 @@ export const Actions = {
|
|||
type: Types.REGISTRATION_REQUIRES_EMAIL,
|
||||
}),
|
||||
registrationSuccess: () => ({
|
||||
type: Types.REGISTRATION_SUCCES,
|
||||
type: Types.REGISTRATION_SUCCESS,
|
||||
}),
|
||||
registrationFailed: (error) => ({
|
||||
type: Types.REGISTRATION_FAILED,
|
||||
|
|
@ -157,11 +157,6 @@ export const Actions = {
|
|||
type: Types.ACCOUNT_IMAGE_CHANGED,
|
||||
user,
|
||||
}),
|
||||
directMessageSent: (userName, message) => ({
|
||||
type: Types.DIRECT_MESSAGE_SENT,
|
||||
userName,
|
||||
message,
|
||||
}),
|
||||
getUserInfo: (userInfo) => ({
|
||||
type: Types.GET_USER_INFO,
|
||||
userInfo,
|
||||
|
|
@ -239,4 +234,5 @@ export const Actions = {
|
|||
deckDelDir: (path: string) => ({ type: Types.DECK_DEL_DIR, path }),
|
||||
deckUpload: (path: string, treeItem: DeckStorageTreeItem) => ({ type: Types.DECK_UPLOAD, path, treeItem }),
|
||||
deckDelete: (deckId: number) => ({ type: Types.DECK_DELETE, deckId }),
|
||||
gamesOfUser: (userName: string, games: Game[]) => ({ type: Types.GAMES_OF_USER, userName, games }),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,11 +250,6 @@ describe('Dispatch', () => {
|
|||
expect(store.dispatch).toHaveBeenCalledWith(Actions.accountImageChanged(user));
|
||||
});
|
||||
|
||||
it('directMessageSent dispatches correctly', () => {
|
||||
Dispatch.directMessageSent('Eve', 'hi');
|
||||
expect(store.dispatch).toHaveBeenCalledWith(Actions.directMessageSent('Eve', 'hi'));
|
||||
});
|
||||
|
||||
it('getUserInfo dispatches correctly', () => {
|
||||
const userInfo = makeUser({ name: 'Frank' });
|
||||
Dispatch.getUserInfo(userInfo);
|
||||
|
|
@ -385,4 +380,10 @@ describe('Dispatch', () => {
|
|||
Dispatch.deckDelete(42);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(Actions.deckDelete(42));
|
||||
});
|
||||
|
||||
it('gamesOfUser dispatches correctly', () => {
|
||||
const games = [{ gameId: 1 }] as any;
|
||||
Dispatch.gamesOfUser('alice', games);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(Actions.gamesOfUser('alice', games));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { reset } from 'redux-form';
|
||||
import { Actions } from './server.actions';
|
||||
import { store } from 'store';
|
||||
import { DeckList, DeckStorageTreeItem, ReplayMatch, WebSocketConnectOptions } from 'types';
|
||||
import { DeckList, DeckStorageTreeItem, Game, ReplayMatch, WebSocketConnectOptions } from 'types';
|
||||
|
||||
export const Dispatch = {
|
||||
initialized: () => {
|
||||
|
|
@ -141,9 +141,6 @@ export const Dispatch = {
|
|||
accountImageChanged: (user) => {
|
||||
store.dispatch(Actions.accountImageChanged(user));
|
||||
},
|
||||
directMessageSent: (userName, message) => {
|
||||
store.dispatch(Actions.directMessageSent(userName, message));
|
||||
},
|
||||
getUserInfo: (userInfo) => {
|
||||
store.dispatch(Actions.getUserInfo(userInfo));
|
||||
},
|
||||
|
|
@ -216,4 +213,7 @@ export const Dispatch = {
|
|||
deckDelete: (deckId: number) => {
|
||||
store.dispatch(Actions.deckDelete(deckId));
|
||||
},
|
||||
gamesOfUser: (userName: string, games: Game[]) => {
|
||||
store.dispatch(Actions.gamesOfUser(userName, games));
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {
|
||||
WarnHistoryItem, BanHistoryItem, DeckList, LogItem, ReplayMatch, SortBy, User, UserSortField, WebSocketConnectOptions, WarnListItem
|
||||
WarnHistoryItem, BanHistoryItem, DeckList, Game, LogItem, ReplayMatch, SortBy, User, UserSortField, WebSocketConnectOptions, WarnListItem
|
||||
} from 'types';
|
||||
import { NotifyUserData, ServerShutdownData, UserMessageData } from 'websocket/events/session/interfaces';
|
||||
|
||||
|
|
@ -72,6 +72,7 @@ export interface ServerState {
|
|||
adminNotes: { [userName: string]: string };
|
||||
replays: ReplayMatch[];
|
||||
backendDecks: DeckList | null;
|
||||
gamesOfUser: { [userName: string]: Game[] };
|
||||
}
|
||||
|
||||
export interface ServerStateStatus {
|
||||
|
|
|
|||
|
|
@ -332,31 +332,39 @@ describe('Moderation', () => {
|
|||
describe('ADJUST_MOD', () => {
|
||||
const baseUserLevel = UserLevelFlag.IsUser | UserLevelFlag.IsRegistered | UserLevelFlag.IsModerator | UserLevelFlag.IsJudge;
|
||||
|
||||
it('shouldBeMod=true, shouldBeJudge=true → keeps IsModerator and IsJudge bits', () => {
|
||||
it('shouldBeMod=true, shouldBeJudge=true → sets both bits, preserves IsUser|IsRegistered', () => {
|
||||
const state = makeServerState({ users: [makeUser({ name: 'Dan', userLevel: baseUserLevel })] });
|
||||
const result = serverReducer(state, { type: Types.ADJUST_MOD, userName: 'Dan', shouldBeMod: true, shouldBeJudge: true });
|
||||
// IsModerator(4) | IsJudge(16)
|
||||
expect(result.users[0].userLevel).toBe(20);
|
||||
// IsUser(1) | IsRegistered(2) | IsModerator(4) | IsJudge(16) = 23
|
||||
expect(result.users[0].userLevel).toBe(23);
|
||||
});
|
||||
|
||||
it('shouldBeMod=true, shouldBeJudge=false → keeps only IsModerator bit', () => {
|
||||
it('shouldBeMod=true, shouldBeJudge=false → sets IsModerator, clears IsJudge, preserves others', () => {
|
||||
const state = makeServerState({ users: [makeUser({ name: 'Dan', userLevel: baseUserLevel })] });
|
||||
const result = serverReducer(state, { type: Types.ADJUST_MOD, userName: 'Dan', shouldBeMod: true, shouldBeJudge: false });
|
||||
// IsModerator(4)
|
||||
expect(result.users[0].userLevel).toBe(4);
|
||||
// IsUser(1) | IsRegistered(2) | IsModerator(4) = 7
|
||||
expect(result.users[0].userLevel).toBe(7);
|
||||
});
|
||||
|
||||
it('shouldBeMod=false, shouldBeJudge=true → keeps only IsJudge bit', () => {
|
||||
it('shouldBeMod=false, shouldBeJudge=true → clears IsModerator, sets IsJudge, preserves others', () => {
|
||||
const state = makeServerState({ users: [makeUser({ name: 'Dan', userLevel: baseUserLevel })] });
|
||||
const result = serverReducer(state, { type: Types.ADJUST_MOD, userName: 'Dan', shouldBeMod: false, shouldBeJudge: true });
|
||||
// IsJudge(16)
|
||||
expect(result.users[0].userLevel).toBe(16);
|
||||
// IsUser(1) | IsRegistered(2) | IsJudge(16) = 19
|
||||
expect(result.users[0].userLevel).toBe(19);
|
||||
});
|
||||
|
||||
it('shouldBeMod=false, shouldBeJudge=false → clears both bits', () => {
|
||||
it('shouldBeMod=false, shouldBeJudge=false → clears both bits, preserves IsUser|IsRegistered', () => {
|
||||
const state = makeServerState({ users: [makeUser({ name: 'Dan', userLevel: baseUserLevel })] });
|
||||
const result = serverReducer(state, { type: Types.ADJUST_MOD, userName: 'Dan', shouldBeMod: false, shouldBeJudge: false });
|
||||
expect(result.users[0].userLevel).toBe(0);
|
||||
// IsUser(1) | IsRegistered(2) = 3
|
||||
expect(result.users[0].userLevel).toBe(3);
|
||||
});
|
||||
|
||||
it('shouldBeMod=true on IsUser|IsRegistered only → produces 7, not 4', () => {
|
||||
const state = makeServerState({ users: [makeUser({ name: 'Dan', userLevel: UserLevelFlag.IsUser | UserLevelFlag.IsRegistered })] });
|
||||
const result = serverReducer(state, { type: Types.ADJUST_MOD, userName: 'Dan', shouldBeMod: true, shouldBeJudge: false });
|
||||
// IsUser(1) | IsRegistered(2) | IsModerator(4) = 7
|
||||
expect(result.users[0].userLevel).toBe(7);
|
||||
});
|
||||
|
||||
it('non-matching users are left unchanged', () => {
|
||||
|
|
@ -524,3 +532,29 @@ describe('Deck Storage', () => {
|
|||
expect(result.backendDecks.root.items[0].folder.items).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
// ── GAMES_OF_USER ─────────────────────────────────────────────────────────────
|
||||
|
||||
describe('GAMES_OF_USER', () => {
|
||||
it('stores games keyed by userName', () => {
|
||||
const games = [{ gameId: 5, roomId: 1 }] as any;
|
||||
const state = makeServerState();
|
||||
const result = serverReducer(state, { type: Types.GAMES_OF_USER, userName: 'alice', games });
|
||||
expect(result.gamesOfUser['alice']).toBe(games);
|
||||
});
|
||||
|
||||
it('overwrites previous games for same user', () => {
|
||||
const old = [{ gameId: 1 }] as any;
|
||||
const fresh = [{ gameId: 2 }] as any;
|
||||
const state = makeServerState({ gamesOfUser: { alice: old } });
|
||||
const result = serverReducer(state, { type: Types.GAMES_OF_USER, userName: 'alice', games: fresh });
|
||||
expect(result.gamesOfUser['alice']).toBe(fresh);
|
||||
});
|
||||
|
||||
it('does not affect other users\' entries', () => {
|
||||
const bobGames = [{ gameId: 3 }] as any;
|
||||
const state = makeServerState({ gamesOfUser: { bob: bobGames } });
|
||||
const result = serverReducer(state, { type: Types.GAMES_OF_USER, userName: 'alice', games: [] });
|
||||
expect(result.gamesOfUser['bob']).toBe(bobGames);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ const initialState: ServerState = {
|
|||
adminNotes: {},
|
||||
replays: [],
|
||||
backendDecks: null,
|
||||
gamesOfUser: {},
|
||||
};
|
||||
|
||||
export const serverReducer = (state = initialState, action: any) => {
|
||||
|
|
@ -401,11 +402,12 @@ export const serverReducer = (state = initialState, action: any) => {
|
|||
if (user.name !== userName) {
|
||||
return user;
|
||||
}
|
||||
const judgeFlag = shouldBeJudge ? UserLevelFlag.IsJudge : UserLevelFlag.IsNothing;
|
||||
const modFlag = shouldBeMod ? UserLevelFlag.IsModerator : UserLevelFlag.IsNothing;
|
||||
let newLevel = user.userLevel;
|
||||
newLevel = shouldBeMod ? (newLevel | UserLevelFlag.IsModerator) : (newLevel & ~UserLevelFlag.IsModerator);
|
||||
newLevel = shouldBeJudge ? (newLevel | UserLevelFlag.IsJudge) : (newLevel & ~UserLevelFlag.IsJudge);
|
||||
return {
|
||||
...user,
|
||||
userLevel: user.userLevel & (judgeFlag | modFlag)
|
||||
userLevel: newLevel,
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
@ -475,6 +477,16 @@ export const serverReducer = (state = initialState, action: any) => {
|
|||
},
|
||||
};
|
||||
}
|
||||
case Types.GAMES_OF_USER: {
|
||||
const { userName, games } = action;
|
||||
return {
|
||||
...state,
|
||||
gamesOfUser: {
|
||||
...state.gamesOfUser,
|
||||
[userName]: games,
|
||||
},
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const Types = {
|
|||
VIEW_LOGS: '[Server] View Logs',
|
||||
CLEAR_LOGS: '[Server] Clear Logs',
|
||||
REGISTRATION_REQUIRES_EMAIL: '[Server] Registration Requires Email',
|
||||
REGISTRATION_SUCCES: '[Server] Registration Success',
|
||||
REGISTRATION_SUCCESS: '[Server] Registration Success',
|
||||
REGISTRATION_FAILED: '[Server] Registration Failed',
|
||||
REGISTRATION_EMAIL_ERROR: '[Server] Registration Email Error',
|
||||
REGISTRATION_PASSWORD_ERROR: '[Server] Registration Password Error',
|
||||
|
|
@ -42,7 +42,6 @@ export const Types = {
|
|||
ACCOUNT_PASSWORD_CHANGE: '[Server] Account Password Change',
|
||||
ACCOUNT_EDIT_CHANGED: '[Server] Account Edit Changed',
|
||||
ACCOUNT_IMAGE_CHANGED: '[Server] Account Image Changed',
|
||||
DIRECT_MESSAGE_SENT: '[Server] Direct Message Sent',
|
||||
GET_USER_INFO: '[Server] Get User Info',
|
||||
NOTIFY_USER: '[Server] Notify User',
|
||||
SERVER_SHUTDOWN: '[Server] Server Shutdown',
|
||||
|
|
@ -69,4 +68,6 @@ export const Types = {
|
|||
DECK_DEL_DIR: '[Server] Deck Del Dir',
|
||||
DECK_UPLOAD: '[Server] Deck Upload',
|
||||
DECK_DELETE: '[Server] Deck Delete',
|
||||
// User games
|
||||
GAMES_OF_USER: '[Server] Games Of User',
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue