From fa4664e583451f5482e1b7e2095cee285b5661e0 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 24 Apr 2021 17:58:37 +0200 Subject: [PATCH] Ensured edited short URLs are reflected in redux state when needed --- src/short-urls/reducers/shortUrlsList.ts | 11 ++++++ .../short-urls/reducers/shortUrlsList.test.ts | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/short-urls/reducers/shortUrlsList.ts b/src/short-urls/reducers/shortUrlsList.ts index 6ae5765f..9fa4b2fa 100644 --- a/src/short-urls/reducers/shortUrlsList.ts +++ b/src/short-urls/reducers/shortUrlsList.ts @@ -9,6 +9,7 @@ import { ShlinkShortUrlsResponse } from '../../api/types'; import { DeleteShortUrlAction, SHORT_URL_DELETED } from './shortUrlDeletion'; import { ShortUrlsListParams } from './shortUrlsListParams'; import { CREATE_SHORT_URL, CreateShortUrlAction } from './shortUrlCreation'; +import { SHORT_URL_EDITED, ShortUrlEditedAction } from './shortUrlEdition'; /* eslint-disable padding-line-between-statements */ export const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START'; @@ -32,6 +33,7 @@ export type ListShortUrlsCombinedAction = ( & CreateVisitsAction & CreateShortUrlAction & DeleteShortUrlAction + & ShortUrlEditedAction ); const initialState: ShortUrlsList = { @@ -87,6 +89,15 @@ export default buildReducer({ state, ), ), + [SHORT_URL_EDITED]: (state, { shortUrl: editedShortUrl }) => !state.shortUrls ? state : assocPath( + [ 'shortUrls', 'data' ], + state.shortUrls.data.map((shortUrl) => { + const { shortCode, domain } = editedShortUrl; + + return shortUrlMatches(shortUrl, shortCode, domain) ? editedShortUrl : shortUrl; + }), + state, + ), }, initialState); export const listShortUrls = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( diff --git a/test/short-urls/reducers/shortUrlsList.test.ts b/test/short-urls/reducers/shortUrlsList.test.ts index 761cf0b1..e4ae692d 100644 --- a/test/short-urls/reducers/shortUrlsList.test.ts +++ b/test/short-urls/reducers/shortUrlsList.test.ts @@ -11,6 +11,7 @@ import { ShortUrl } from '../../../src/short-urls/data'; import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient'; import { ShlinkPaginator, ShlinkShortUrlsResponse } from '../../../src/api/types'; import { CREATE_SHORT_URL } from '../../../src/short-urls/reducers/shortUrlCreation'; +import { SHORT_URL_EDITED } from '../../../src/short-urls/reducers/shortUrlEdition'; describe('shortUrlsListReducer', () => { describe('reducer', () => { @@ -124,6 +125,40 @@ describe('shortUrlsListReducer', () => { error: false, }); }); + + it.each([ + ((): [ShortUrl, ShortUrl[], ShortUrl[]] => { + const editedShortUrl = Mock.of({ shortCode: 'notMatching' }); + const list = [ Mock.of({ shortCode: 'foo' }), Mock.of({ shortCode: 'bar' }) ]; + + return [ editedShortUrl, list, list ]; + })(), + ((): [ShortUrl, ShortUrl[], ShortUrl[]] => { + const editedShortUrl = Mock.of({ shortCode: 'matching', longUrl: 'new_one' }); + const list = [ + Mock.of({ shortCode: 'matching', longUrl: 'old_one' }), + Mock.of({ shortCode: 'bar' }), + ]; + const expectedList = [ editedShortUrl, list[1] ]; + + return [ editedShortUrl, list, expectedList ]; + })(), + ])('updates matching short URL on SHORT_URL_EDITED', (editedShortUrl, initialList, expectedList) => { + const state = { + shortUrls: Mock.of({ + data: initialList, + pagination: Mock.of({ + totalItems: 15, + }), + }), + loading: false, + error: false, + }; + + const result = reducer(state, { type: SHORT_URL_EDITED, shortUrl: editedShortUrl } as any); + + expect(result.shortUrls?.data).toEqual(expectedList); + }); }); describe('listShortUrls', () => {