mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
harden
This commit is contained in:
parent
d04aa83258
commit
dcd6dc00f4
83 changed files with 1797 additions and 390 deletions
|
|
@ -1 +1,4 @@
|
|||
export { withMockLocation, withEventRegistry } from './globalGuards';
|
||||
export { renderWithProviders } from './renderWithProviders';
|
||||
export { createMockWebClient } from './mockWebClient';
|
||||
export { disconnectedState, connectedState, connectedWithRoomsState, makeUser } from './storeFixtures';
|
||||
|
|
|
|||
56
webclient/src/__test-utils__/mockWebClient.ts
Normal file
56
webclient/src/__test-utils__/mockWebClient.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import type { WebClient } from '@app/websocket';
|
||||
|
||||
/**
|
||||
* Creates a mock WebClient whose `request` property has vi.fn() stubs
|
||||
* for every service method that containers/forms call. Inject this into
|
||||
* tests via `renderWithProviders({ webClient: createMockWebClient() })`.
|
||||
*/
|
||||
export function createMockWebClient() {
|
||||
return {
|
||||
request: {
|
||||
authentication: {
|
||||
login: vi.fn(),
|
||||
register: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
activateAccount: vi.fn(),
|
||||
resetPasswordRequest: vi.fn(),
|
||||
resetPasswordChallenge: vi.fn(),
|
||||
resetPassword: vi.fn(),
|
||||
},
|
||||
session: {
|
||||
addToBuddyList: vi.fn(),
|
||||
removeFromBuddyList: vi.fn(),
|
||||
addToIgnoreList: vi.fn(),
|
||||
removeFromIgnoreList: vi.fn(),
|
||||
getUserInfo: vi.fn(),
|
||||
accountEdit: vi.fn(),
|
||||
accountPassword: vi.fn(),
|
||||
accountImage: vi.fn(),
|
||||
listUsers: vi.fn(),
|
||||
},
|
||||
rooms: {
|
||||
joinRoom: vi.fn(),
|
||||
leaveRoom: vi.fn(),
|
||||
roomSay: vi.fn(),
|
||||
createGame: vi.fn(),
|
||||
},
|
||||
game: {
|
||||
joinGame: vi.fn(),
|
||||
leaveGame: vi.fn(),
|
||||
},
|
||||
admin: {
|
||||
adjustMod: vi.fn(),
|
||||
reloadConfig: vi.fn(),
|
||||
shutdownServer: vi.fn(),
|
||||
updateServerMessage: vi.fn(),
|
||||
},
|
||||
moderator: {
|
||||
viewLogHistory: vi.fn(),
|
||||
banFromServer: vi.fn(),
|
||||
warnUser: vi.fn(),
|
||||
warnHistory: vi.fn(),
|
||||
banHistory: vi.fn(),
|
||||
},
|
||||
},
|
||||
} as unknown as WebClient;
|
||||
}
|
||||
71
webclient/src/__test-utils__/renderWithProviders.tsx
Normal file
71
webclient/src/__test-utils__/renderWithProviders.tsx
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import { ReactElement } from 'react';
|
||||
import { render, RenderOptions } from '@testing-library/react';
|
||||
import { configureStore, EnhancedStore } from '@reduxjs/toolkit';
|
||||
import { Provider } from 'react-redux';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import { gamesReducer } from '../store/game';
|
||||
import { roomsReducer } from '../store/rooms';
|
||||
import { serverReducer } from '../store/server';
|
||||
import { actionReducer } from '../store/actions';
|
||||
import { ToastProvider } from '../components/Toast/ToastContext';
|
||||
import type { RootState } from '../store/store';
|
||||
|
||||
// Minimal i18n instance for tests — returns keys as-is.
|
||||
const testI18n = i18n.createInstance();
|
||||
testI18n.use(initReactI18next).init({
|
||||
lng: 'en',
|
||||
resources: {},
|
||||
fallbackLng: 'en',
|
||||
interpolation: { escapeValue: false },
|
||||
});
|
||||
|
||||
function createTestStore(preloadedState?: Partial<RootState>) {
|
||||
return configureStore({
|
||||
reducer: {
|
||||
games: gamesReducer,
|
||||
rooms: roomsReducer,
|
||||
server: serverReducer,
|
||||
action: actionReducer,
|
||||
},
|
||||
preloadedState: preloadedState as any,
|
||||
});
|
||||
}
|
||||
|
||||
interface ExtendedRenderOptions extends Omit<RenderOptions, 'wrapper'> {
|
||||
preloadedState?: Partial<RootState>;
|
||||
store?: EnhancedStore;
|
||||
route?: string;
|
||||
}
|
||||
|
||||
export function renderWithProviders(
|
||||
ui: ReactElement,
|
||||
{
|
||||
preloadedState,
|
||||
store = createTestStore(preloadedState),
|
||||
route = '/',
|
||||
...renderOptions
|
||||
}: ExtendedRenderOptions = {},
|
||||
) {
|
||||
function Wrapper({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<I18nextProvider i18n={testI18n}>
|
||||
<ToastProvider>
|
||||
<MemoryRouter initialEntries={[route]}>
|
||||
{children}
|
||||
</MemoryRouter>
|
||||
</ToastProvider>
|
||||
</I18nextProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
store,
|
||||
...render(ui, { wrapper: Wrapper, ...renderOptions }),
|
||||
};
|
||||
}
|
||||
123
webclient/src/__test-utils__/storeFixtures.ts
Normal file
123
webclient/src/__test-utils__/storeFixtures.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { App, Data, Enriched } from '@app/types';
|
||||
import type { RootState } from '../store/store';
|
||||
|
||||
/**
|
||||
* Create a minimal ServerInfo_User object for testing.
|
||||
*/
|
||||
function makeUser(overrides: Partial<Data.ServerInfo_User> = {}): Data.ServerInfo_User {
|
||||
return {
|
||||
name: 'testUser',
|
||||
realName: '',
|
||||
country: 'us',
|
||||
userLevel: 0,
|
||||
avatarBmp: new Uint8Array(),
|
||||
accountageSecs: BigInt(0),
|
||||
$typeName: 'ServerInfo_User' as any,
|
||||
$unknown: undefined,
|
||||
gender: 0,
|
||||
...overrides,
|
||||
} as Data.ServerInfo_User;
|
||||
}
|
||||
|
||||
/**
|
||||
* A disconnected (default) store state. This is the state before any
|
||||
* connection to a server has been made.
|
||||
*/
|
||||
export const disconnectedState: Partial<RootState> = {
|
||||
server: {
|
||||
initialized: false,
|
||||
buddyList: {},
|
||||
ignoreList: {},
|
||||
status: {
|
||||
connectionAttemptMade: false,
|
||||
state: Enriched.StatusEnum.DISCONNECTED,
|
||||
description: null,
|
||||
},
|
||||
info: { message: null, name: null, version: null },
|
||||
logs: { room: [], game: [], chat: [] },
|
||||
user: null,
|
||||
users: {},
|
||||
sortUsersBy: { field: App.UserSortField.NAME, order: App.SortDirection.ASC },
|
||||
messages: {},
|
||||
userInfo: {},
|
||||
notifications: [],
|
||||
serverShutdown: null,
|
||||
banUser: '',
|
||||
banHistory: {},
|
||||
warnHistory: {},
|
||||
warnListOptions: [],
|
||||
warnUser: '',
|
||||
adminNotes: {},
|
||||
replays: {},
|
||||
backendDecks: null,
|
||||
downloadedDeck: null,
|
||||
downloadedReplay: null,
|
||||
gamesOfUser: {},
|
||||
registrationError: null,
|
||||
},
|
||||
rooms: {
|
||||
rooms: {},
|
||||
joinedRoomIds: {},
|
||||
joinedGameIds: {},
|
||||
messages: {},
|
||||
sortGamesBy: { field: App.GameSortField.START_TIME, order: App.SortDirection.DESC },
|
||||
sortUsersBy: { field: App.UserSortField.NAME, order: App.SortDirection.ASC },
|
||||
},
|
||||
games: { games: {} },
|
||||
action: { type: null, payload: null, meta: null, error: false, count: 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* A connected (logged-in) store state with a basic user and server info.
|
||||
*/
|
||||
export const connectedState: Partial<RootState> = {
|
||||
...disconnectedState,
|
||||
server: {
|
||||
...(disconnectedState.server as any),
|
||||
initialized: true,
|
||||
status: {
|
||||
connectionAttemptMade: true,
|
||||
state: Enriched.StatusEnum.LOGGED_IN,
|
||||
description: null,
|
||||
},
|
||||
info: {
|
||||
message: '<b>Welcome</b>',
|
||||
name: 'Test Server',
|
||||
version: '1.0.0',
|
||||
},
|
||||
user: makeUser(),
|
||||
users: {
|
||||
testUser: makeUser(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Connected state with rooms and a joined room containing games and users.
|
||||
*/
|
||||
export const connectedWithRoomsState: Partial<RootState> = {
|
||||
...connectedState,
|
||||
server: {
|
||||
...(connectedState.server as any),
|
||||
users: {
|
||||
testUser: makeUser(),
|
||||
otherUser: makeUser({ name: 'otherUser' }),
|
||||
},
|
||||
},
|
||||
rooms: {
|
||||
...(disconnectedState.rooms as any),
|
||||
rooms: {
|
||||
1: {
|
||||
info: { roomId: 1, name: 'Main Room', description: 'The main room', autoJoin: true, permissionLevel: 0 },
|
||||
gameList: [],
|
||||
userList: [makeUser(), makeUser({ name: 'otherUser' })],
|
||||
},
|
||||
},
|
||||
joinedRoomIds: { 1: true },
|
||||
messages: {
|
||||
1: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export { makeUser };
|
||||
Loading…
Add table
Add a link
Reference in a new issue