Improved short URL detail redux action so that it avoids API calls when the URL is found in local state

This commit is contained in:
Alejandro Celaya
2021-03-05 16:25:20 +01:00
parent 56b3523c5b
commit 13d3a95a06
2 changed files with 47 additions and 9 deletions

View File

@@ -9,8 +9,11 @@ import reducer, {
import { ShortUrl } from '../../../src/short-urls/data';
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
import { ShlinkState } from '../../../src/container/types';
import { ShortUrlsList } from '../../../src/short-urls/reducers/shortUrlsList';
describe('shortUrlDetailReducer', () => {
beforeEach(jest.clearAllMocks);
describe('reducer', () => {
const action = (type: string) => Mock.of<ShortUrlDetailAction>({ type });
@@ -45,14 +48,12 @@ describe('shortUrlDetailReducer', () => {
getShortUrl: jest.fn(async () => returned),
});
const dispatchMock = jest.fn();
const getState = () => Mock.of<ShlinkState>();
beforeEach(() => dispatchMock.mockReset());
const buildGetState = (shortUrlsList?: ShortUrlsList) => () => Mock.of<ShlinkState>({ shortUrlsList });
it('dispatches start and error when promise is rejected', async () => {
const ShlinkApiClient = buildApiClientMock(Promise.reject());
await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, getState);
await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, buildGetState());
expect(dispatchMock).toHaveBeenCalledTimes(2);
expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START });
@@ -60,16 +61,50 @@ describe('shortUrlDetailReducer', () => {
expect(ShlinkApiClient.getShortUrl).toHaveBeenCalledTimes(1);
});
it('dispatches start and success when promise is resolved', async () => {
const resolvedShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'bar' });
it.each([
[ undefined ],
[ Mock.all<ShortUrlsList>() ],
[
Mock.of<ShortUrlsList>({
shortUrls: { data: [] },
}),
],
[
Mock.of<ShortUrlsList>({
shortUrls: {
data: [ Mock.of<ShortUrl>({ shortCode: 'this_will_not_match' }) ],
},
}),
],
])('performs API call when short URL is not found in local state', async (shortUrlsList?: ShortUrlsList) => {
const resolvedShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
const ShlinkApiClient = buildApiClientMock(Promise.resolve(resolvedShortUrl));
await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, getState);
await getShortUrlDetail(() => ShlinkApiClient)('abc123', '')(dispatchMock, buildGetState(shortUrlsList));
expect(dispatchMock).toHaveBeenCalledTimes(2);
expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START });
expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_DETAIL, shortUrl: resolvedShortUrl });
expect(ShlinkApiClient.getShortUrl).toHaveBeenCalledTimes(1);
});
it('avoids API calls when short URL is found in local state', async () => {
const foundShortUrl = Mock.of<ShortUrl>({ longUrl: 'foo', shortCode: 'abc123' });
const ShlinkApiClient = buildApiClientMock(Promise.resolve(Mock.all<ShortUrl>()));
await getShortUrlDetail(() => ShlinkApiClient)(foundShortUrl.shortCode, foundShortUrl.domain)(
dispatchMock,
buildGetState(Mock.of<ShortUrlsList>({
shortUrls: {
data: [ foundShortUrl ],
},
})),
);
expect(dispatchMock).toHaveBeenCalledTimes(2);
expect(dispatchMock).toHaveBeenNthCalledWith(1, { type: GET_SHORT_URL_DETAIL_START });
expect(dispatchMock).toHaveBeenNthCalledWith(2, { type: GET_SHORT_URL_DETAIL, shortUrl: foundShortUrl });
expect(ShlinkApiClient.getShortUrl).not.toHaveBeenCalled();
});
});
});