From 10d4419387b0f993956ac16afe80c57e0ad12a5a Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 5 Nov 2022 10:08:24 +0100 Subject: [PATCH] Migrated servers reducer to RTK --- src/reducers/index.ts | 2 +- src/servers/reducers/servers.ts | 111 ++++++++++---------- test/servers/reducers/remoteServers.test.ts | 4 +- test/servers/reducers/servers.test.ts | 61 +++++------ 4 files changed, 86 insertions(+), 92 deletions(-) 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/reducers/servers.ts b/src/servers/reducers/servers.ts index 872c450e..0d5e7e0f 100644 --- a/src/servers/reducers/servers.ts +++ b/src/servers/reducers/servers.ts @@ -1,24 +1,17 @@ -import { PayloadAction } from '@reduxjs/toolkit'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { assoc, dissoc, fromPairs, map, pipe, reduce, toPairs } from 'ramda'; import { v4 as uuid } from 'uuid'; 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 type CreateServersAction = PayloadAction; - -type DeleteServerAction = PayloadAction<{ +interface EditServer { serverId: string; -}>; + serverData: Partial; +} -type SetAutoConnectAction = PayloadAction<{ +interface SetAutoConnect { serverId: string; autoConnect: boolean; -}>; +} const initialState: ServersMap = {}; @@ -30,53 +23,57 @@ const serverWithId = (server: ServerWithId | ServerData): ServerWithId => { return assoc('id', uuid(), server); }; -export default buildReducer({ - [CREATE_SERVERS]: (state, { payload: newServers }) => ({ ...state, ...newServers }), - [DELETE_SERVER]: (state, { payload }) => dissoc(payload.serverId, state), - [EDIT_SERVER]: (state, { payload }: any) => { - const { serverId, serverData } = payload; - return ( - !state[serverId] ? state : assoc(serverId, { ...state[serverId], ...serverData }, state) - ); - }, - [SET_AUTO_CONNECT]: (state, { payload }) => { - const { serverId, autoConnect } = payload; - 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, payload: 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 editServer = (serverId: string, serverData: Partial) => ({ - type: EDIT_SERVER, - payload: { serverId, serverData }, + if (!autoConnect) { + return assoc(serverId, { ...state[serverId], autoConnect }, state); + } + + 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, - payload: { serverId: id }, -}); +export const { editServer, deleteServer, setAutoConnect, createServers } = actions; -export const setAutoConnect = ({ id }: ServerWithId, autoConnect: boolean): SetAutoConnectAction => ({ - type: SET_AUTO_CONNECT, - payload: { serverId: id, autoConnect }, -}); +export const serversReducer = reducer; diff --git a/test/servers/reducers/remoteServers.test.ts b/test/servers/reducers/remoteServers.test.ts index 815e5490..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, payload: expectedNewServers }); + expect(dispatch).toHaveBeenCalledWith({ type: createServers.toString(), payload: expectedNewServers }); expect(get).toHaveBeenCalledTimes(1); }); }); diff --git a/test/servers/reducers/servers.test.ts b/test/servers/reducers/servers.test.ts index c24ef6aa..81695779 100644 --- a/test/servers/reducers/servers.test.ts +++ b/test/servers/reducers/servers.test.ts @@ -1,14 +1,11 @@ import { dissoc, values } from 'ramda'; import { Mock } from 'ts-mockery'; -import reducer, { +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'; @@ -22,38 +19,38 @@ describe('serversReducer', () => { describe('reducer', () => { it('returns edited server when action is EDIT_SERVER', () => - expect(reducer(list, { - type: EDIT_SERVER, + expect(serversReducer(list, { + type: editServer.toString(), payload: { serverId: 'abc123', serverData: { foo: 'foo' } }, - } as any)).toEqual({ + })).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, + expect(serversReducer(list, { + type: editServer.toString(), payload: { serverId: 'invalid', serverData: { foo: 'foo' } }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); it('removes server when action is DELETE_SERVER', () => - expect(reducer(list, { - type: DELETE_SERVER, - payload: { 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, + expect(serversReducer(list, { + type: createServers.toString(), payload: { ghi789: { id: 'ghi789' }, }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, ghi789: { id: 'ghi789' }, @@ -63,10 +60,10 @@ describe('serversReducer', () => { [true], [false], ])('returns state as it is when trying to set auto-connect on invalid server', (autoConnect) => - expect(reducer(list, { - type: SET_AUTO_CONNECT, + expect(serversReducer(list, { + type: setAutoConnect.toString(), payload: { serverId: 'invalid', autoConnect }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123' }, def456: { id: 'def456' }, })); @@ -77,10 +74,10 @@ describe('serversReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithDisabledAutoConnect, { - type: SET_AUTO_CONNECT, + expect(serversReducer(listWithDisabledAutoConnect, { + type: setAutoConnect.toString(), payload: { serverId: 'abc123', autoConnect: false }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456' }, }); @@ -92,10 +89,10 @@ describe('serversReducer', () => { abc123: { ...list.abc123, autoConnect: true }, }; - expect(reducer(listWithEnabledAutoConnect, { - type: SET_AUTO_CONNECT, + expect(serversReducer(listWithEnabledAutoConnect, { + type: setAutoConnect.toString(), payload: { serverId: 'def456', autoConnect: true }, - } as any)).toEqual({ + })).toEqual({ abc123: { id: 'abc123', autoConnect: false }, def456: { id: 'def456', autoConnect: true }, }); @@ -109,7 +106,7 @@ describe('serversReducer', () => { const result = editServer('123', serverData); expect(result).toEqual({ - type: EDIT_SERVER, + type: editServer.toString(), payload: { serverId: '123', serverData }, }); }); @@ -121,8 +118,8 @@ describe('serversReducer', () => { const result = deleteServer(serverToDelete); expect(result).toEqual({ - type: DELETE_SERVER, - payload: { serverId: 'abc123' }, + type: deleteServer.toString(), + payload: { id: 'abc123' }, }); }); }); @@ -132,7 +129,7 @@ describe('serversReducer', () => { 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', () => { @@ -152,7 +149,7 @@ describe('serversReducer', () => { const result = setAutoConnect(serverToEdit, autoConnect); expect(result).toEqual({ - type: SET_AUTO_CONNECT, + type: setAutoConnect.toString(), payload: { serverId: 'abc123', autoConnect }, }); });