diff --git a/src/domains/DomainRow.tsx b/src/domains/DomainRow.tsx index f3ca7426..e57b0f36 100644 --- a/src/domains/DomainRow.tsx +++ b/src/domains/DomainRow.tsx @@ -8,11 +8,12 @@ import { SelectedServer } from '../servers/data'; import { Domain } from './data'; import { DomainStatusIcon } from './helpers/DomainStatusIcon'; import { DomainDropdown } from './helpers/DomainDropdown'; +import { EditDomainRedirects } from './reducers/domainRedirects'; interface DomainRowProps { domain: Domain; defaultRedirects?: ShlinkDomainRedirects; - editDomainRedirects: (domain: string, redirects: Partial) => Promise; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise; checkDomainHealth: (domain: string) => void; selectedServer: SelectedServer; } diff --git a/src/domains/ManageDomains.tsx b/src/domains/ManageDomains.tsx index a6170595..f7c52992 100644 --- a/src/domains/ManageDomains.tsx +++ b/src/domains/ManageDomains.tsx @@ -4,7 +4,7 @@ import { Result } from '../utils/Result'; import { ShlinkApiError } from '../api/ShlinkApiError'; import { SimpleCard } from '../utils/SimpleCard'; import { SearchField } from '../utils/SearchField'; -import { ShlinkDomainRedirects } from '../api/types'; +import { EditDomainRedirects } from './reducers/domainRedirects'; import { SelectedServer } from '../servers/data'; import { DomainsList } from './reducers/domainsList'; import { DomainRow } from './DomainRow'; @@ -12,7 +12,7 @@ import { DomainRow } from './DomainRow'; interface ManageDomainsProps { listDomains: Function; filterDomains: (searchTerm: string) => void; - editDomainRedirects: (domain: string, redirects: Partial) => Promise; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise; checkDomainHealth: (domain: string) => void; domainsList: DomainsList; selectedServer: SelectedServer; diff --git a/src/domains/helpers/DomainDropdown.tsx b/src/domains/helpers/DomainDropdown.tsx index 423c4db5..a91b40a8 100644 --- a/src/domains/helpers/DomainDropdown.tsx +++ b/src/domains/helpers/DomainDropdown.tsx @@ -7,14 +7,14 @@ import { useToggle } from '../../utils/helpers/hooks'; import { DropdownBtnMenu } from '../../utils/DropdownBtnMenu'; import { EditDomainRedirectsModal } from './EditDomainRedirectsModal'; import { Domain } from '../data'; -import { ShlinkDomainRedirects } from '../../api/types'; +import { EditDomainRedirects } from '../reducers/domainRedirects'; import { supportsDefaultDomainRedirectsEdition, supportsDomainVisits } from '../../utils/helpers/features'; import { getServerId, SelectedServer } from '../../servers/data'; import { DEFAULT_DOMAIN } from '../../visits/reducers/domainVisits'; interface DomainDropdownProps { domain: Domain; - editDomainRedirects: (domain: string, redirects: Partial) => Promise; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise; selectedServer: SelectedServer; } diff --git a/src/domains/helpers/EditDomainRedirectsModal.tsx b/src/domains/helpers/EditDomainRedirectsModal.tsx index 0bc86bf8..26d11be5 100644 --- a/src/domains/helpers/EditDomainRedirectsModal.tsx +++ b/src/domains/helpers/EditDomainRedirectsModal.tsx @@ -1,15 +1,16 @@ import { FC, useState } from 'react'; import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; -import { ShlinkDomain, ShlinkDomainRedirects } from '../../api/types'; +import { ShlinkDomain } from '../../api/types'; import { InputFormGroup, InputFormGroupProps } from '../../utils/forms/InputFormGroup'; import { handleEventPreventingDefault, nonEmptyValueOrNull } from '../../utils/utils'; import { InfoTooltip } from '../../utils/InfoTooltip'; +import { EditDomainRedirects } from '../reducers/domainRedirects'; interface EditDomainRedirectsModalProps { domain: ShlinkDomain; isOpen: boolean; toggle: () => void; - editDomainRedirects: (domain: string, redirects: Partial) => Promise; + editDomainRedirects: (redirects: EditDomainRedirects) => Promise; } const FormGroup: FC = ({ isLast, ...rest }) => ( @@ -30,10 +31,13 @@ export const EditDomainRedirectsModal: FC = ( const [invalidShortUrlRedirect, setInvalidShortUrlRedirect] = useState( domain.redirects?.invalidShortUrlRedirect ?? '', ); - const handleSubmit = handleEventPreventingDefault(async () => editDomainRedirects(domain.domain, { - baseUrlRedirect: nonEmptyValueOrNull(baseUrlRedirect), - regular404Redirect: nonEmptyValueOrNull(regular404Redirect), - invalidShortUrlRedirect: nonEmptyValueOrNull(invalidShortUrlRedirect), + const handleSubmit = handleEventPreventingDefault(async () => editDomainRedirects({ + domain: domain.domain, + redirects: { + baseUrlRedirect: nonEmptyValueOrNull(baseUrlRedirect), + regular404Redirect: nonEmptyValueOrNull(regular404Redirect), + invalidShortUrlRedirect: nonEmptyValueOrNull(invalidShortUrlRedirect), + }, }).then(toggle)); return ( diff --git a/src/domains/reducers/domainRedirects.ts b/src/domains/reducers/domainRedirects.ts index 8cb65d93..4a5472b9 100644 --- a/src/domains/reducers/domainRedirects.ts +++ b/src/domains/reducers/domainRedirects.ts @@ -9,15 +9,17 @@ export const EDIT_DOMAIN_REDIRECTS_START = 'shlink/domainRedirects/EDIT_DOMAIN_R export const EDIT_DOMAIN_REDIRECTS_ERROR = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS_ERROR'; export const EDIT_DOMAIN_REDIRECTS = 'shlink/domainRedirects/EDIT_DOMAIN_REDIRECTS'; -export interface EditDomainRedirectsAction extends Action { +export interface EditDomainRedirects { domain: string; redirects: ShlinkDomainRedirects; } -export const editDomainRedirects = (buildShlinkApiClient: ShlinkApiClientBuilder) => ( - domain: string, - domainRedirects: Partial, -) => async (dispatch: Dispatch, getState: GetState) => { +export interface EditDomainRedirectsAction extends Action, EditDomainRedirects {} + +export const editDomainRedirects = (buildShlinkApiClient: ShlinkApiClientBuilder) => ({ + domain, + redirects: domainRedirects, +}: EditDomainRedirects) => async (dispatch: Dispatch, getState: GetState) => { dispatch({ type: EDIT_DOMAIN_REDIRECTS_START }); const { editDomainRedirects: shlinkEditDomainRedirects } = buildShlinkApiClient(getState); diff --git a/test/domains/helpers/DomainDropdown.test.tsx b/test/domains/helpers/DomainDropdown.test.tsx index 90b5658b..1efd1a5e 100644 --- a/test/domains/helpers/DomainDropdown.test.tsx +++ b/test/domains/helpers/DomainDropdown.test.tsx @@ -71,7 +71,7 @@ describe('', () => { expect(editDomainRedirects).not.toHaveBeenCalled(); await user.click(screen.getByText('Save')); - expect(editDomainRedirects).toHaveBeenCalledWith(domain, expect.anything()); + expect(editDomainRedirects).toHaveBeenCalledWith(expect.objectContaining({ domain })); await waitForElementToBeRemoved(() => screen.queryByRole('dialog')); }); diff --git a/test/domains/helpers/EditDomainRedirectsModal.test.tsx b/test/domains/helpers/EditDomainRedirectsModal.test.tsx index 6f402350..a83ddcbb 100644 --- a/test/domains/helpers/EditDomainRedirectsModal.test.tsx +++ b/test/domains/helpers/EditDomainRedirectsModal.test.tsx @@ -40,37 +40,49 @@ describe('', () => { expect(editDomainRedirects).not.toHaveBeenCalled(); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'baz', - regular404Redirect: null, - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'baz', + regular404Redirect: null, + invalidShortUrlRedirect: null, + }, })); await user.clear(screen.getByDisplayValue('baz')); await user.type(screen.getAllByPlaceholderText('No redirect')[0], 'new_base_url'); await user.type(screen.getAllByPlaceholderText('No redirect')[2], 'new_invalid_short_url'); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'new_base_url', - regular404Redirect: null, - invalidShortUrlRedirect: 'new_invalid_short_url', + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'new_base_url', + regular404Redirect: null, + invalidShortUrlRedirect: 'new_invalid_short_url', + }, })); await user.type(screen.getAllByPlaceholderText('No redirect')[1], 'new_regular_404'); await user.clear(screen.getByDisplayValue('new_invalid_short_url')); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: 'new_base_url', - regular404Redirect: 'new_regular_404', - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: 'new_base_url', + regular404Redirect: 'new_regular_404', + invalidShortUrlRedirect: null, + }, })); await Promise.all(screen.getAllByPlaceholderText('No redirect').map((element) => user.clear(element))); submitForm(); - await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith('foo.com', { - baseUrlRedirect: null, - regular404Redirect: null, - invalidShortUrlRedirect: null, + await waitFor(() => expect(editDomainRedirects).toHaveBeenCalledWith({ + domain: 'foo.com', + redirects: { + baseUrlRedirect: null, + regular404Redirect: null, + invalidShortUrlRedirect: null, + }, })); }); }); diff --git a/test/domains/reducers/domainRedirects.test.ts b/test/domains/reducers/domainRedirects.test.ts index f77f8377..c7ed433d 100644 --- a/test/domains/reducers/domainRedirects.test.ts +++ b/test/domains/reducers/domainRedirects.test.ts @@ -3,7 +3,7 @@ import { ShlinkApiClient } from '../../../src/api/services/ShlinkApiClient'; import { EDIT_DOMAIN_REDIRECTS, EDIT_DOMAIN_REDIRECTS_ERROR, - EDIT_DOMAIN_REDIRECTS_START, + EDIT_DOMAIN_REDIRECTS_START, EditDomainRedirects, editDomainRedirects as editDomainRedirectsAction, } from '../../../src/domains/reducers/domainRedirects'; import { ShlinkDomainRedirects } from '../../../src/api/types'; @@ -22,7 +22,10 @@ describe('domainRedirectsReducer', () => { it('dispatches error when loading domains fails', async () => { editDomainRedirects.mockRejectedValue(new Error('error')); - await editDomainRedirectsAction(buildShlinkApiClient)(domain, {})(dispatch, getState); + await editDomainRedirectsAction(buildShlinkApiClient)(Mock.of({ domain }))( + dispatch, + getState, + ); expect(dispatch).toHaveBeenCalledTimes(2); expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_DOMAIN_REDIRECTS_START }); @@ -33,7 +36,10 @@ describe('domainRedirectsReducer', () => { it('dispatches domain and redirects once loaded', async () => { editDomainRedirects.mockResolvedValue(redirects); - await editDomainRedirectsAction(buildShlinkApiClient)(domain, {})(dispatch, getState); + await editDomainRedirectsAction(buildShlinkApiClient)(Mock.of({ domain }))( + dispatch, + getState, + ); expect(dispatch).toHaveBeenCalledTimes(2); expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_DOMAIN_REDIRECTS_START });