Migrated tagDelete reducer to RTK

This commit is contained in:
Alejandro Celaya
2022-11-07 22:41:02 +01:00
parent 692eaf7dc9
commit 033df3c3d6
6 changed files with 63 additions and 71 deletions

View File

@@ -1,19 +1,18 @@
import { Mock } from 'ts-mockery';
import reducer, {
DELETE_TAG_START,
DELETE_TAG_ERROR,
DELETE_TAG,
TAG_DELETED,
tagDeleted,
deleteTag,
} from '../../../src/tags/reducers/tagDelete';
import { tagDeleted, tagDeleteReducerCreator } from '../../../src/tags/reducers/tagDelete';
import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient';
import { ShlinkState } from '../../../src/container/types';
describe('tagDeleteReducer', () => {
const deleteTagsCall = jest.fn();
const buildShlinkApiClient = () => Mock.of<ShlinkApiClient>({ deleteTags: deleteTagsCall });
const { reducer, deleteTag } = tagDeleteReducerCreator(buildShlinkApiClient);
beforeEach(jest.clearAllMocks);
describe('reducer', () => {
it('returns loading on DELETE_TAG_START', () => {
expect(reducer(undefined, { type: DELETE_TAG_START })).toEqual({
expect(reducer(undefined, { type: deleteTag.pending.toString() })).toEqual({
deleting: true,
deleted: false,
error: false,
@@ -21,7 +20,7 @@ describe('tagDeleteReducer', () => {
});
it('returns error on DELETE_TAG_ERROR', () => {
expect(reducer(undefined, { type: DELETE_TAG_ERROR })).toEqual({
expect(reducer(undefined, { type: deleteTag.rejected.toString() })).toEqual({
deleting: false,
deleted: false,
error: true,
@@ -29,7 +28,7 @@ describe('tagDeleteReducer', () => {
});
it('returns tag names on DELETE_TAG', () => {
expect(reducer(undefined, { type: DELETE_TAG })).toEqual({
expect(reducer(undefined, { type: deleteTag.fulfilled.toString() })).toEqual({
deleting: false,
deleted: true,
error: false,
@@ -40,53 +39,46 @@ describe('tagDeleteReducer', () => {
describe('tagDeleted', () => {
it('returns action based on provided params', () =>
expect(tagDeleted('foo')).toEqual({
type: TAG_DELETED,
type: tagDeleted.toString(),
payload: 'foo',
}));
});
describe('deleteTag', () => {
const createApiClientMock = (result: Promise<any>) => Mock.of<ShlinkApiClient>({
deleteTags: jest.fn(async () => result),
});
const dispatch = jest.fn();
const getState = () => Mock.all<ShlinkState>();
afterEach(() => dispatch.mockReset());
it('calls API on success', async () => {
const tag = 'foo';
const apiClientMock = createApiClientMock(Promise.resolve());
const dispatchable = deleteTag(() => apiClientMock)(tag);
deleteTagsCall.mockResolvedValue(undefined);
await dispatchable(dispatch, getState);
await deleteTag(tag)(dispatch, getState, {});
expect(apiClientMock.deleteTags).toHaveBeenCalledTimes(1);
expect(apiClientMock.deleteTags).toHaveBeenNthCalledWith(1, [tag]);
expect(deleteTagsCall).toHaveBeenCalledTimes(1);
expect(deleteTagsCall).toHaveBeenNthCalledWith(1, [tag]);
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_TAG_START });
expect(dispatch).toHaveBeenNthCalledWith(2, { type: DELETE_TAG });
expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteTag.pending.toString() }));
expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: deleteTag.fulfilled.toString() }));
});
it('throws on error', async () => {
const error = 'Error';
const tag = 'foo';
const apiClientMock = createApiClientMock(Promise.reject(error));
const dispatchable = deleteTag(() => apiClientMock)(tag);
deleteTagsCall.mockRejectedValue(error);
try {
await dispatchable(dispatch, getState);
await deleteTag(tag)(dispatch, getState, {});
} catch (e) {
expect(e).toEqual(error);
}
expect(apiClientMock.deleteTags).toHaveBeenCalledTimes(1);
expect(apiClientMock.deleteTags).toHaveBeenNthCalledWith(1, [tag]);
expect(deleteTagsCall).toHaveBeenCalledTimes(1);
expect(deleteTagsCall).toHaveBeenNthCalledWith(1, [tag]);
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_TAG_START });
expect(dispatch).toHaveBeenNthCalledWith(2, { type: DELETE_TAG_ERROR });
expect(dispatch).toHaveBeenNthCalledWith(1, expect.objectContaining({ type: deleteTag.pending.toString() }));
expect(dispatch).toHaveBeenNthCalledWith(2, expect.objectContaining({ type: deleteTag.rejected.toString() }));
});
});
});

View File

@@ -8,11 +8,11 @@ import reducer, {
listTags,
TagsList,
} from '../../../src/tags/reducers/tagsList';
import { TAG_DELETED } from '../../../src/tags/reducers/tagDelete';
import { ShlinkState } from '../../../src/container/types';
import { ShortUrl } from '../../../src/short-urls/data';
import { CREATE_SHORT_URL } from '../../../src/short-urls/reducers/shortUrlCreation';
import { tagEdited } from '../../../src/tags/reducers/tagEdit';
import { tagDeleted } from '../../../src/tags/reducers/tagDelete';
describe('tagsListReducer', () => {
const state = (props: Partial<TagsList>) => Mock.of<TagsList>(props);
@@ -48,7 +48,10 @@ describe('tagsListReducer', () => {
const tag = 'foo';
const expectedTags = ['bar', 'baz'];
expect(reducer(state({ tags, filteredTags: tags }), { type: TAG_DELETED, payload: tag } as any)).toEqual({
expect(reducer(
state({ tags, filteredTags: tags }),
{ type: tagDeleted.toString(), payload: tag } as any,
)).toEqual({
tags: expectedTags,
filteredTags: expectedTags,
});