import { Mock } from 'ts-mockery'; import reducer, { LIST_DOMAINS, LIST_DOMAINS_ERROR, LIST_DOMAINS_START, FILTER_DOMAINS, DomainsCombinedAction, DomainsList, listDomains as listDomainsAction, filterDomains as filterDomainsAction, replaceRedirectsOnDomain, } from '../../../src/domains/reducers/domainsList'; import { EDIT_DOMAIN_REDIRECTS } from '../../../src/domains/reducers/domainRedirects'; import { ShlinkDomain, ShlinkDomainRedirects } from '../../../src/api/types'; import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient'; describe('domainsList', () => { const filteredDomains = [ Mock.of({ domain: 'foo' }), Mock.of({ domain: 'boo' }) ]; const domains = [ ...filteredDomains, Mock.of({ domain: 'bar' }) ]; describe('reducer', () => { const action = (type: string, args: Partial = {}) => Mock.of( { type, ...args }, ); it('returns loading on LIST_DOMAINS_START', () => { expect(reducer(undefined, action(LIST_DOMAINS_START))).toEqual( { domains: [], filteredDomains: [], loading: true, error: false }, ); }); it('returns error on LIST_DOMAINS_ERROR', () => { expect(reducer(undefined, action(LIST_DOMAINS_ERROR))).toEqual( { domains: [], filteredDomains: [], loading: false, error: true }, ); }); it('returns domains on LIST_DOMAINS', () => { expect(reducer(undefined, action(LIST_DOMAINS, { domains }))).toEqual( { domains, filteredDomains: domains, loading: false, error: false }, ); }); it('filters domains on FILTER_DOMAINS', () => { expect(reducer(Mock.of({ domains }), action(FILTER_DOMAINS, { searchTerm: 'oo' }))).toEqual( { domains, filteredDomains }, ); }); it.each([ [ 'foo' ], [ 'bar' ], [ 'does_not_exist' ], ])('replaces redirects on proper domain on EDIT_DOMAIN_REDIRECTS', (domain) => { const redirects: ShlinkDomainRedirects = { baseUrlRedirect: 'bar', regular404Redirect: 'foo', invalidShortUrlRedirect: null, }; expect(reducer( Mock.of({ domains, filteredDomains }), action(EDIT_DOMAIN_REDIRECTS, { domain, redirects }), )).toEqual({ domains: domains.map(replaceRedirectsOnDomain(domain, redirects)), filteredDomains: filteredDomains.map(replaceRedirectsOnDomain(domain, redirects)), }); }); }); describe('listDomains', () => { const dispatch = jest.fn(); const getState = jest.fn(); const listDomains = jest.fn(); const buildShlinkApiClient = () => Mock.of({ listDomains }); beforeEach(jest.clearAllMocks); it('dispatches error when loading domains fails', async () => { listDomains.mockRejectedValue(new Error('error')); await listDomainsAction(buildShlinkApiClient)()(dispatch, getState); expect(dispatch).toHaveBeenCalledTimes(2); expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_DOMAINS_START }); expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_DOMAINS_ERROR }); expect(listDomains).toHaveBeenCalledTimes(1); }); it('dispatches domains once loaded', async () => { listDomains.mockResolvedValue(domains); await listDomainsAction(buildShlinkApiClient)()(dispatch, getState); expect(dispatch).toHaveBeenCalledTimes(2); expect(dispatch).toHaveBeenNthCalledWith(1, { type: LIST_DOMAINS_START }); expect(dispatch).toHaveBeenNthCalledWith(2, { type: LIST_DOMAINS, domains }); expect(listDomains).toHaveBeenCalledTimes(1); }); }); describe('filterDomains', () => { it.each([ [ 'foo' ], [ 'bar' ], [ 'something' ], ])('creates action as expected', (searchTerm) => { expect(filterDomainsAction(searchTerm)).toEqual({ type: FILTER_DOMAINS, searchTerm }); }); }); });