diff --git a/src/domains/reducers/domainRedirects.ts b/src/domains/reducers/domainRedirects.ts index aa97871b..7aea1b15 100644 --- a/src/domains/reducers/domainRedirects.ts +++ b/src/domains/reducers/domainRedirects.ts @@ -1,7 +1,6 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import { ShlinkDomainRedirects } from '../../api/types'; -import { ShlinkState } from '../../container/types'; const EDIT_DOMAIN_REDIRECTS = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS'; @@ -12,11 +11,11 @@ export interface EditDomainRedirects { export const editDomainRedirects = ( buildShlinkApiClient: ShlinkApiClientBuilder, -) => createAsyncThunk( +) => createAsyncThunk( EDIT_DOMAIN_REDIRECTS, - async ({ domain, redirects: domainRedirects }, { getState }) => { + async ({ domain, redirects: providedRedirects }: EditDomainRedirects, { getState }): Promise => { const { editDomainRedirects: shlinkEditDomainRedirects } = buildShlinkApiClient(getState); - const redirects = await shlinkEditDomainRedirects({ domain, ...domainRedirects }); + const redirects = await shlinkEditDomainRedirects({ domain, ...providedRedirects }); return { domain, redirects }; }, diff --git a/src/domains/reducers/domainsList.ts b/src/domains/reducers/domainsList.ts index bf7f8758..77b8fe72 100644 --- a/src/domains/reducers/domainsList.ts +++ b/src/domains/reducers/domainsList.ts @@ -1,7 +1,7 @@ -import { createSlice, createAsyncThunk, createAction, SliceCaseReducers, AsyncThunk } from '@reduxjs/toolkit'; +import { createSlice, createAction, SliceCaseReducers, AsyncThunk } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkDomainRedirects } from '../../api/types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; -import { ShlinkState } from '../../container/types'; import { Domain, DomainStatus } from '../data'; import { hasServerData } from '../../servers/data'; import { replaceAuthorityFromUri } from '../../utils/helpers/uri'; @@ -49,22 +49,19 @@ export const domainsListReducerCreator = ( buildShlinkApiClient: ShlinkApiClientBuilder, editDomainRedirects: AsyncThunk, ) => { - const listDomains = createAsyncThunk( - LIST_DOMAINS, - async (_, { getState }) => { - const { listDomains: shlinkListDomains } = buildShlinkApiClient(getState); - const { data, defaultRedirects } = await shlinkListDomains(); + const listDomains = createAsyncThunk(LIST_DOMAINS, async (_: void, { getState }): Promise => { + const { listDomains: shlinkListDomains } = buildShlinkApiClient(getState); + const { data, defaultRedirects } = await shlinkListDomains(); - return { - domains: data.map((domain): Domain => ({ ...domain, status: 'validating' })), - defaultRedirects, - }; - }, - ); + return { + domains: data.map((domain): Domain => ({ ...domain, status: 'validating' })), + defaultRedirects, + }; + }); - const checkDomainHealth = createAsyncThunk( + const checkDomainHealth = createAsyncThunk( VALIDATE_DOMAIN, - async (domain: string, { getState }) => { + async (domain: string, { getState }): Promise => { const { selectedServer } = getState(); if (!hasServerData(selectedServer)) { diff --git a/src/mercure/reducers/mercureInfo.ts b/src/mercure/reducers/mercureInfo.ts index 378c6fa9..75806cde 100644 --- a/src/mercure/reducers/mercureInfo.ts +++ b/src/mercure/reducers/mercureInfo.ts @@ -1,6 +1,6 @@ -import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; +import { createSlice } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../utils/helpers/redux'; import { ShlinkMercureInfo } from '../../api/types'; -import { ShlinkState } from '../../container/types'; import { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; const GET_MERCURE_INFO = 'shlink/mercure/GET_MERCURE_INFO'; @@ -17,17 +17,14 @@ const initialState: MercureInfo = { }; export const mercureInfoReducerCreator = (buildShlinkApiClient: ShlinkApiClientBuilder) => { - const loadMercureInfo = createAsyncThunk( - GET_MERCURE_INFO, - async (_, { getState }) => { - const { settings } = getState(); - if (!settings.realTimeUpdates.enabled) { - throw new Error('Real time updates not enabled'); - } + const loadMercureInfo = createAsyncThunk(GET_MERCURE_INFO, (_: void, { getState }): Promise => { + const { settings } = getState(); + if (!settings.realTimeUpdates.enabled) { + throw new Error('Real time updates not enabled'); + } - return buildShlinkApiClient(getState).mercureInfo(); - }, - ); + return buildShlinkApiClient(getState).mercureInfo(); + }); const { reducer } = createSlice({ name: 'mercureInfoReducer', diff --git a/src/reducers/index.ts b/src/reducers/index.ts index 02fb1ed3..c88fb12e 100644 --- a/src/reducers/index.ts +++ b/src/reducers/index.ts @@ -1,6 +1,6 @@ import { IContainer } from 'bottlejs'; import { combineReducers } from 'redux'; -import serversReducer from '../servers/reducers/servers'; +import { serversReducer } from '../servers/reducers/servers'; import selectedServerReducer from '../servers/reducers/selectedServer'; import shortUrlsListReducer from '../short-urls/reducers/shortUrlsList'; import shortUrlCreationReducer from '../short-urls/reducers/shortUrlCreation'; diff --git a/src/servers/CreateServer.tsx b/src/servers/CreateServer.tsx index df96e838..4ffd93ea 100644 --- a/src/servers/CreateServer.tsx +++ b/src/servers/CreateServer.tsx @@ -13,7 +13,7 @@ import { DuplicatedServersModal } from './helpers/DuplicatedServersModal'; const SHOW_IMPORT_MSG_TIME = 4000; interface CreateServerProps { - createServer: (server: ServerWithId) => void; + createServers: (servers: ServerWithId[]) => void; servers: ServersMap; } @@ -27,7 +27,7 @@ const ImportResult = ({ type }: { type: 'error' | 'success' }) => ( ); export const CreateServer = (ImportServersBtn: FC, useTimeoutToggle: TimeoutToggle) => ( - { servers, createServer }: CreateServerProps, + { servers, createServers }: CreateServerProps, ) => { const navigate = useNavigate(); const goBack = useGoBack(); @@ -43,7 +43,7 @@ export const CreateServer = (ImportServersBtn: FC, useTim const id = uuid(); - createServer({ ...serverData, id }); + createServers([{ ...serverData, id }]); navigate(`/server/${id}`); }; diff --git a/src/servers/reducers/selectedServer.ts b/src/servers/reducers/selectedServer.ts index b33f344d..78c0d69d 100644 --- a/src/servers/reducers/selectedServer.ts +++ b/src/servers/reducers/selectedServer.ts @@ -1,3 +1,4 @@ +import { PayloadAction } from '@reduxjs/toolkit'; import { identity, memoizeWith, pipe } from 'ramda'; import { Action, Dispatch } from 'redux'; import { versionToPrintable, versionToSemVer as toSemVer } from '../../utils/helpers/version'; @@ -14,9 +15,7 @@ export const MIN_FALLBACK_VERSION = '1.0.0'; export const MAX_FALLBACK_VERSION = '999.999.999'; export const LATEST_VERSION_CONSTRAINT = 'latest'; -export interface SelectServerAction extends Action { - selectedServer: SelectedServer; -} +export type SelectServerAction = PayloadAction; const versionToSemVer = pipe( (version: string) => (version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version), @@ -35,7 +34,7 @@ const initialState: SelectedServer = null; export default buildReducer({ [RESET_SELECTED_SERVER]: () => initialState, - [SELECT_SERVER]: (_, { selectedServer }) => selectedServer, + [SELECT_SERVER]: (_, { payload }) => payload, }, initialState); export const resetSelectedServer = buildActionCreator(RESET_SELECTED_SERVER); @@ -57,7 +56,7 @@ export const selectServer = ( if (!selectedServer) { dispatch({ type: SELECT_SERVER, - selectedServer: { serverNotFound: true }, + payload: { serverNotFound: true }, }); return; @@ -69,7 +68,7 @@ export const selectServer = ( dispatch({ type: SELECT_SERVER, - selectedServer: { + payload: { ...selectedServer, version, printableVersion, @@ -79,7 +78,7 @@ export const selectServer = ( } catch (e) { dispatch({ type: SELECT_SERVER, - selectedServer: { ...selectedServer, serverNotReachable: true }, + payload: { ...selectedServer, serverNotReachable: true }, }); } }; diff --git a/src/servers/reducers/servers.ts b/src/servers/reducers/servers.ts index 31cd4d13..0d5e7e0f 100644 --- a/src/servers/reducers/servers.ts +++ b/src/servers/reducers/servers.ts @@ -1,23 +1,14 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { assoc, dissoc, fromPairs, map, pipe, reduce, toPairs } from 'ramda'; import { v4 as uuid } from 'uuid'; -import { Action } from 'redux'; import { ServerData, ServersMap, ServerWithId } from '../data'; -import { buildReducer } from '../../utils/helpers/redux'; -export const EDIT_SERVER = 'shlink/servers/EDIT_SERVER'; -export const DELETE_SERVER = 'shlink/servers/DELETE_SERVER'; -export const CREATE_SERVERS = 'shlink/servers/CREATE_SERVERS'; -export const SET_AUTO_CONNECT = 'shlink/servers/SET_AUTO_CONNECT'; - -export interface CreateServersAction extends Action { - newServers: ServersMap; -} - -interface DeleteServerAction extends Action { +interface EditServer { serverId: string; + serverData: Partial; } -interface SetAutoConnectAction extends Action { +interface SetAutoConnect { serverId: string; autoConnect: boolean; } @@ -32,50 +23,57 @@ const serverWithId = (server: ServerWithId | ServerData): ServerWithId => { return assoc('id', uuid(), server); }; -export default buildReducer({ - [CREATE_SERVERS]: (state, { newServers }) => ({ ...state, ...newServers }), - [DELETE_SERVER]: (state, { serverId }) => dissoc(serverId, state), - [EDIT_SERVER]: (state, { serverId, serverData }: any) => ( - !state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state) - ), - [SET_AUTO_CONNECT]: (state, { serverId, autoConnect }) => { - if (!state[serverId]) { - return state; - } - - if (!autoConnect) { - return assoc(serverId, { ...state[serverId], autoConnect }, state); - } - - return fromPairs( - toPairs(state).map(([evaluatedServerId, server]) => [ - evaluatedServerId, - { ...server, autoConnect: evaluatedServerId === serverId }, - ]), - ); - }, -}, initialState); - const serversListToMap = reduce((acc, server) => assoc(server.id, server, acc), {}); -export const createServers = pipe( - map(serverWithId), - serversListToMap, - (newServers: ServersMap) => ({ type: CREATE_SERVERS, newServers }), -); +export const { actions, reducer } = createSlice({ + name: 'serversReducer', + initialState, + reducers: { + editServer: { + prepare: (serverId: string, serverData: Partial) => ({ + payload: { serverId, serverData }, + }), + reducer: (state, { payload }: PayloadAction) => { + const { serverId, serverData } = payload; + return ( + !state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state) + ); + }, + }, + deleteServer: (state, { payload }) => dissoc(payload.id, state), + setAutoConnect: { + prepare: ({ id: serverId }: ServerWithId, autoConnect: boolean) => ({ + payload: { serverId, autoConnect }, + }), + reducer: (state, { payload }: PayloadAction) => { + const { serverId, autoConnect } = payload; + if (!state[serverId]) { + return state; + } -export const createServer = (server: ServerWithId) => createServers([server]); + if (!autoConnect) { + return assoc(serverId, { ...state[serverId], autoConnect }, state); + } -export const editServer = (serverId: string, serverData: Partial) => ({ - type: EDIT_SERVER, - serverId, - serverData, + return fromPairs( + toPairs(state).map(([evaluatedServerId, server]) => [ + evaluatedServerId, + { ...server, autoConnect: evaluatedServerId === serverId }, + ]), + ); + }, + }, + createServers: { + prepare: pipe( + map(serverWithId), + serversListToMap, + (payload: ServersMap) => ({ payload }), + ), + reducer: (state, { payload: newServers }: PayloadAction) => ({ ...state, ...newServers }), + }, + }, }); -export const deleteServer = ({ id }: ServerWithId): DeleteServerAction => ({ type: DELETE_SERVER, serverId: id }); +export const { editServer, deleteServer, setAutoConnect, createServers } = actions; -export const setAutoConnect = ({ id }: ServerWithId, autoConnect: boolean): SetAutoConnectAction => ({ - type: SET_AUTO_CONNECT, - serverId: id, - autoConnect, -}); +export const serversReducer = reducer; diff --git a/src/servers/services/provideServices.ts b/src/servers/services/provideServices.ts index 6f56cc84..f6e03f88 100644 --- a/src/servers/services/provideServices.ts +++ b/src/servers/services/provideServices.ts @@ -6,7 +6,7 @@ import { DeleteServerButton } from '../DeleteServerButton'; import { EditServer } from '../EditServer'; import { ImportServersBtn } from '../helpers/ImportServersBtn'; import { resetSelectedServer, selectServer } from '../reducers/selectedServer'; -import { createServer, createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers'; +import { createServers, deleteServer, editServer, setAutoConnect } from '../reducers/servers'; import { fetchServers } from '../reducers/remoteServers'; import { ServerError } from '../helpers/ServerError'; import { ConnectDecorator } from '../../container/types'; @@ -38,7 +38,7 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { bottle.serviceFactory('CreateServer', CreateServer, 'ImportServersBtn', 'useTimeoutToggle'); bottle.decorator('CreateServer', withoutSelectedServer); - bottle.decorator('CreateServer', connect(['selectedServer', 'servers'], ['createServer', 'resetSelectedServer'])); + bottle.decorator('CreateServer', connect(['selectedServer', 'servers'], ['createServers', 'resetSelectedServer'])); bottle.serviceFactory('EditServer', EditServer, 'ServerError'); bottle.decorator('EditServer', connect(['selectedServer'], ['editServer', 'selectServer', 'resetSelectedServer'])); @@ -70,7 +70,6 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Actions bottle.serviceFactory('selectServer', selectServer, 'buildShlinkApiClient', 'loadMercureInfo'); - bottle.serviceFactory('createServer', () => createServer); bottle.serviceFactory('createServers', () => createServers); bottle.serviceFactory('deleteServer', () => deleteServer); bottle.serviceFactory('editServer', () => editServer); diff --git a/src/utils/helpers/redux.ts b/src/utils/helpers/redux.ts index d2607707..f8962883 100644 --- a/src/utils/helpers/redux.ts +++ b/src/utils/helpers/redux.ts @@ -1,4 +1,6 @@ +import { createAsyncThunk as baseCreateAsyncThunk, AsyncThunkPayloadCreator } from '@reduxjs/toolkit'; import { Action } from 'redux'; +import { ShlinkState } from '../../container/types'; type ActionHandler = (currentState: State, action: AT) => State; type ActionHandlerMap = Record>; @@ -15,3 +17,8 @@ export const buildReducer = (map: ActionHandlerMap(type: T) => (): Action => ({ type }); + +export const createAsyncThunk = ( + typePrefix: string, + payloadCreator: AsyncThunkPayloadCreator, +) => baseCreateAsyncThunk(typePrefix, payloadCreator); diff --git a/test/servers/CreateServer.test.tsx b/test/servers/CreateServer.test.tsx index dd559dc3..a5cbc674 100644 --- a/test/servers/CreateServer.test.tsx +++ b/test/servers/CreateServer.test.tsx @@ -8,7 +8,7 @@ import { renderWithEvents } from '../__helpers__/setUpTest'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn() })); describe('', () => { - const createServerMock = jest.fn(); + const createServersMock = jest.fn(); const navigate = jest.fn(); const servers = { foo: Mock.of({ url: 'https://existing_url.com', apiKey: 'existing_api_key' }) }; const setUp = (serversImported = false, importFailed = false) => { @@ -22,7 +22,7 @@ describe('', () => { }); const CreateServer = createCreateServer(() => <>ImportServersBtn, useTimeoutToggle); - return renderWithEvents(); + return renderWithEvents(); }; beforeEach(jest.clearAllMocks); @@ -48,18 +48,18 @@ describe('', () => { it('creates server data when form is submitted', async () => { const { user } = setUp(); - expect(createServerMock).not.toHaveBeenCalled(); + expect(createServersMock).not.toHaveBeenCalled(); await user.type(screen.getByLabelText(/^Name/), 'the_name'); await user.type(screen.getByLabelText(/^URL/), 'https://the_url.com'); await user.type(screen.getByLabelText(/^API key/), 'the_api_key'); fireEvent.submit(screen.getByRole('form')); - expect(createServerMock).toHaveBeenCalledWith(expect.objectContaining({ + expect(createServersMock).toHaveBeenCalledWith([expect.objectContaining({ name: 'the_name', url: 'https://the_url.com', apiKey: 'the_api_key', - })); + })]); expect(navigate).toHaveBeenCalledWith(expect.stringMatching(/^\/server\//)); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); }); @@ -75,7 +75,7 @@ describe('', () => { await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument()); await user.click(screen.getByRole('button', { name: 'Discard' })); - expect(createServerMock).not.toHaveBeenCalled(); + expect(createServersMock).not.toHaveBeenCalled(); expect(navigate).toHaveBeenCalledWith(-1); }); }); diff --git a/test/servers/reducers/remoteServers.test.ts b/test/servers/reducers/remoteServers.test.ts index 56310e09..708e2905 100644 --- a/test/servers/reducers/remoteServers.test.ts +++ b/test/servers/reducers/remoteServers.test.ts @@ -1,7 +1,7 @@ import { Mock } from 'ts-mockery'; import { AxiosInstance } from 'axios'; import { fetchServers } from '../../../src/servers/reducers/remoteServers'; -import { CREATE_SERVERS } from '../../../src/servers/reducers/servers'; +import { createServers } from '../../../src/servers/reducers/servers'; describe('remoteServersReducer', () => { afterEach(jest.clearAllMocks); @@ -87,7 +87,7 @@ describe('remoteServersReducer', () => { await fetchServers(axios)()(dispatch); - expect(dispatch).toHaveBeenCalledWith({ type: CREATE_SERVERS, newServers: expectedNewServers }); + expect(dispatch).toHaveBeenCalledWith({ type: createServers.toString(), payload: expectedNewServers }); expect(get).toHaveBeenCalledTimes(1); }); }); diff --git a/test/servers/reducers/selectedServer.test.ts b/test/servers/reducers/selectedServer.test.ts index 2074bcd3..f04a4eed 100644 --- a/test/servers/reducers/selectedServer.test.ts +++ b/test/servers/reducers/selectedServer.test.ts @@ -14,12 +14,12 @@ import { NonReachableServer, NotFoundServer, RegularServer } from '../../../src/ describe('selectedServerReducer', () => { describe('reducer', () => { it('returns default when action is RESET_SELECTED_SERVER', () => - expect(reducer(null, { type: RESET_SELECTED_SERVER, selectedServer: null })).toBeNull()); + expect(reducer(null, { type: RESET_SELECTED_SERVER, payload: null })).toBeNull()); it('returns selected server when action is SELECT_SERVER', () => { - const selectedServer = Mock.of({ id: 'abc123' }); + const payload = Mock.of({ id: 'abc123' }); - expect(reducer(null, { type: SELECT_SERVER, selectedServer })).toEqual(selectedServer); + expect(reducer(null, { type: SELECT_SERVER, payload })).toEqual(payload); }); }); @@ -63,7 +63,7 @@ describe('selectedServerReducer', () => { expect(dispatch).toHaveBeenCalledTimes(3); expect(dispatch).toHaveBeenNthCalledWith(1, { type: RESET_SELECTED_SERVER }); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); + expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, payload: expectedSelectedServer }); expect(loadMercureInfo).toHaveBeenCalledTimes(1); }); @@ -87,7 +87,7 @@ describe('selectedServerReducer', () => { await selectServer(buildApiClient, loadMercureInfo)(id)(dispatch, getState); expect(apiClientMock.health).toHaveBeenCalled(); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); + expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, payload: expectedSelectedServer }); expect(loadMercureInfo).not.toHaveBeenCalled(); }); @@ -100,7 +100,7 @@ describe('selectedServerReducer', () => { expect(getState).toHaveBeenCalled(); expect(apiClientMock.health).not.toHaveBeenCalled(); - expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer }); + expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, payload: expectedSelectedServer }); expect(loadMercureInfo).not.toHaveBeenCalled(); }); }); diff --git a/test/servers/reducers/servers.test.ts b/test/servers/reducers/servers.test.ts index e39d3561..81695779 100644 --- a/test/servers/reducers/servers.test.ts +++ b/test/servers/reducers/servers.test.ts @@ -1,19 +1,15 @@ import { dissoc, values } from 'ramda'; import { Mock } from 'ts-mockery'; -import reducer, { - createServer, +import { deleteServer, createServers, editServer, setAutoConnect, - EDIT_SERVER, - DELETE_SERVER, - CREATE_SERVERS, - SET_AUTO_CONNECT, + serversReducer, } from '../../../src/servers/reducers/servers'; import { RegularServer } from '../../../src/servers/data'; -describe('serverReducer', () => { +describe('serversReducer', () => { const list = { abc123: Mock.of({ id: 'abc123' }), def456: Mock.of({ id: 'def456' }), @@ -23,35 +19,38 @@ describe('serverReducer', () => { describe('reducer', () => { it('returns edited server when action is EDIT_SERVER', () => - expect(reducer( - list, - { type: EDIT_SERVER, serverId: 'abc123', serverData: { foo: 'foo' } } as any, - )).toEqual({ + expect(serversReducer(list, { + type: editServer.toString(), + payload: { serverId: 'abc123', serverData: { foo: 'foo' } }, + })).toEqual({ abc123: { id: 'abc123', foo: 'foo' }, def456: { id: 'def456' }, })); it('returns as it is when action is EDIT_SERVER and server does not exist', () => - expect(reducer( - list, - { type: EDIT_SERVER, serverId: 'invalid', serverData: { foo: 'foo' } } as any, - )).toEqual({ + expect(serversReducer(list, { + type: editServer.toString(), + payload: { serverId: 'invalid', serverData: { foo: 'foo' } }, + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); it('removes server when action is DELETE_SERVER', () => - expect(reducer(list, { type: DELETE_SERVER, serverId: 'abc123' } as any)).toEqual({ + expect(serversReducer(list, { + type: deleteServer.toString(), + payload: { id: 'abc123' }, + })).toEqual({ def456: { id: 'def456' }, })); it('appends server when action is CREATE_SERVERS', () => - expect(reducer(list, { - type: CREATE_SERVERS, - newServers: { + expect(serversReducer(list, { + type: createServers.toString(), + payload: { ghi789: { id: 'ghi789' }, }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, ghi789: { id: 'ghi789' }, @@ -61,11 +60,10 @@ describe('serverReducer', () => { [true], [false], ])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) => - expect(reducer(list, { - type: SET_AUTO_CONNECT, - serverId: 'invalid', - autoConnect, - } as any)).toEqual({ + expect(serversReducer(list, { + type: setAutoConnect.toString(), + payload: { serverId: 'invalid', autoConnect }, + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); @@ -76,11 +74,10 @@ describe('serverReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithDisabledAutoConnect, { - type: SET_AUTO_CONNECT, - serverId: 'abc123', - autoConnect: false, - } as any)).toEqual({ + expect(serversReducer(listWithDisabledAutoConnect, { + type: setAutoConnect.toString(), + payload: { serverId: 'abc123', autoConnect: false }, + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456' }, }); @@ -92,11 +89,10 @@ describe('serverReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithEnabledAutoConnect, { - type: SET_AUTO_CONNECT, - serverId: 'def456', - autoConnect: true, - } as any)).toEqual({ + expect(serversReducer(listWithEnabledAutoConnect, { + type: setAutoConnect.toString(), + payload: { serverId: 'def456', autoConnect: true }, + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456', autoConnect: true }, }); @@ -104,21 +100,15 @@ describe('serverReducer', () => { }); describe('action creators', () => { - describe('createServer', () => { - it('returns expected action', () => { - const serverToCreate = Mock.of({ id: 'abc123' }); - const result = createServer(serverToCreate); - - expect(result).toEqual(expect.objectContaining({ type: CREATE_SERVERS })); - }); - }); - describe('editServer', () => { it('returns expected action', () => { const serverData = { name: 'edited' }; const result = editServer('123', serverData); - expect(result).toEqual({ type: EDIT_SERVER, serverId: '123', serverData }); + expect(result).toEqual({ + type: editServer.toString(), + payload: { serverId: '123', serverData }, + }); }); }); @@ -127,7 +117,10 @@ describe('serverReducer', () => { const serverToDelete = Mock.of({ id: 'abc123' }); const result = deleteServer(serverToDelete); - expect(result).toEqual({ type: DELETE_SERVER, serverId: 'abc123' }); + expect(result).toEqual({ + type: deleteServer.toString(), + payload: { id: 'abc123' }, + }); }); }); @@ -136,14 +129,14 @@ describe('serverReducer', () => { const newServers = values(list); const result = createServers(newServers); - expect(result).toEqual(expect.objectContaining({ type: CREATE_SERVERS })); + expect(result).toEqual(expect.objectContaining({ type: createServers.toString() })); }); it('generates an id for every provided server if they do not have it', () => { const servers = values(list).map(dissoc('id')); - const { newServers } = createServers(servers); + const { payload } = createServers(servers); - expect(values(newServers).every(({ id }) => !!id)).toEqual(true); + expect(values(payload).every(({ id }) => !!id)).toEqual(true); }); }); @@ -155,7 +148,10 @@ describe('serverReducer', () => { const serverToEdit = Mock.of({ id: 'abc123' }); const result = setAutoConnect(serverToEdit, autoConnect); - expect(result).toEqual({ type: SET_AUTO_CONNECT, serverId: 'abc123', autoConnect }); + expect(result).toEqual({ + type: setAutoConnect.toString(), + payload: { serverId: 'abc123', autoConnect }, + }); }); }); });