✨(frontend) add support email field on domain creation form
Add new field to give email of support to manage actions required on domain.
This commit is contained in:
@@ -99,6 +99,7 @@ describe('MailDomainAccessesPage', () => {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
|
||||
@@ -25,6 +25,7 @@ describe('AccessAction', () => {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
|
||||
@@ -31,6 +31,7 @@ describe('AccessesContent', () => {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
|
||||
@@ -26,6 +26,7 @@ const mockMailDomain: MailDomain = {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
manage_accesses: true,
|
||||
get: true,
|
||||
|
||||
@@ -36,6 +36,7 @@ describe('ModalDelete', () => {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
|
||||
@@ -19,6 +19,7 @@ describe('ModalAddMailDomain', () => {
|
||||
modalElement: screen.getByText('Add a mail domain'),
|
||||
formTag: screen.getByTitle('Mail domain addition form'),
|
||||
inputName: screen.getByLabelText(/Domain name/i),
|
||||
inputSupportEmail: screen.getByLabelText(/Support email address/i),
|
||||
buttonCancel: screen.getByRole('button', { name: /Cancel/i, hidden: true }),
|
||||
buttonSubmit: screen.getByRole('button', {
|
||||
name: /Add the domain/i,
|
||||
@@ -37,12 +38,19 @@ describe('ModalAddMailDomain', () => {
|
||||
it('renders all the elements', () => {
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { modalElement, formTag, inputName, buttonCancel, buttonSubmit } =
|
||||
getElements();
|
||||
const {
|
||||
modalElement,
|
||||
formTag,
|
||||
inputName,
|
||||
inputSupportEmail,
|
||||
buttonCancel,
|
||||
buttonSubmit,
|
||||
} = getElements();
|
||||
|
||||
expect(modalElement).toBeVisible();
|
||||
expect(formTag).toBeVisible();
|
||||
expect(inputName).toBeVisible();
|
||||
expect(inputSupportEmail).toBeVisible();
|
||||
expect(screen.getByText('Example: saint-laurent.fr')).toBeVisible();
|
||||
expect(buttonCancel).toBeVisible();
|
||||
expect(buttonSubmit).toBeVisible();
|
||||
@@ -104,9 +112,10 @@ describe('ModalAddMailDomain', () => {
|
||||
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { inputName, buttonSubmit } = getElements();
|
||||
const { inputName, inputSupportEmail, buttonSubmit } = getElements();
|
||||
|
||||
await user.type(inputName, 'domain.fr');
|
||||
await user.type(inputSupportEmail, 'support@domain.fr');
|
||||
|
||||
await user.click(buttonSubmit);
|
||||
|
||||
@@ -114,6 +123,7 @@ describe('ModalAddMailDomain', () => {
|
||||
expect(fetchMock.lastOptions()).toEqual({
|
||||
body: JSON.stringify({
|
||||
name: 'domain.fr',
|
||||
support_email: 'support@domain.fr',
|
||||
}),
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -123,29 +133,6 @@ describe('ModalAddMailDomain', () => {
|
||||
expect(mockPush).toHaveBeenCalledWith(`/mail-domains/domainfr`);
|
||||
});
|
||||
|
||||
it('submits the form on key enter press', async () => {
|
||||
fetchMock.mock(`end:mail-domains/`, 201);
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { inputName } = getElements();
|
||||
|
||||
await user.type(inputName, 'domain.fr');
|
||||
await user.type(inputName, '{enter}');
|
||||
|
||||
expect(fetchMock.lastUrl()).toContain('/mail-domains/');
|
||||
expect(fetchMock.lastOptions()).toEqual({
|
||||
body: JSON.stringify({
|
||||
name: 'domain.fr',
|
||||
}),
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
method: 'POST',
|
||||
});
|
||||
});
|
||||
|
||||
it('displays right error message error when maildomain name is already used', async () => {
|
||||
fetchMock.mock(`end:mail-domains/`, {
|
||||
status: 400,
|
||||
@@ -158,10 +145,10 @@ describe('ModalAddMailDomain', () => {
|
||||
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { inputName, buttonSubmit } = getElements();
|
||||
const { inputName, inputSupportEmail, buttonSubmit } = getElements();
|
||||
|
||||
await user.type(inputName, 'domain.fr');
|
||||
|
||||
await user.type(inputSupportEmail, 'support@domain.fr');
|
||||
await user.click(buttonSubmit);
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -175,6 +162,7 @@ describe('ModalAddMailDomain', () => {
|
||||
expect(inputName).toHaveFocus();
|
||||
|
||||
await user.type(inputName, 'domain2.fr');
|
||||
|
||||
expect(buttonSubmit).toBeEnabled();
|
||||
});
|
||||
|
||||
@@ -190,9 +178,10 @@ describe('ModalAddMailDomain', () => {
|
||||
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { inputName, buttonSubmit } = getElements();
|
||||
const { inputName, inputSupportEmail, buttonSubmit } = getElements();
|
||||
|
||||
await user.type(inputName, 'domainfr');
|
||||
await user.type(inputSupportEmail, 'support@domain.fr');
|
||||
|
||||
await user.click(buttonSubmit);
|
||||
|
||||
@@ -220,9 +209,10 @@ describe('ModalAddMailDomain', () => {
|
||||
|
||||
render(<ModalAddMailDomain />, { wrapper: AppWrapper });
|
||||
|
||||
const { inputName, buttonSubmit } = getElements();
|
||||
const { inputName, inputSupportEmail, buttonSubmit } = getElements();
|
||||
|
||||
await user.type(inputName, 'domain.fr');
|
||||
await user.type(inputSupportEmail, 'support@domain.fr');
|
||||
|
||||
await user.click(buttonSubmit);
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@ import { KEY_LIST_MAIL_DOMAIN } from './useMailDomains';
|
||||
|
||||
export interface AddMailDomainParams {
|
||||
name: string;
|
||||
supportEmail: string;
|
||||
}
|
||||
|
||||
export const addMailDomain = async (
|
||||
name: AddMailDomainParams['name'],
|
||||
): Promise<MailDomain> => {
|
||||
export const addMailDomain = async ({
|
||||
name,
|
||||
supportEmail,
|
||||
}: AddMailDomainParams): Promise<MailDomain> => {
|
||||
const response = await fetchAPI(`mail-domains/`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
}),
|
||||
body: JSON.stringify({ name, support_email: supportEmail }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -38,7 +38,7 @@ export const useAddMailDomain = ({
|
||||
onError: (error: APIError) => void;
|
||||
}) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<MailDomain, APIError, string>({
|
||||
return useMutation<MailDomain, APIError, AddMailDomainParams>({
|
||||
mutationFn: addMailDomain,
|
||||
onSuccess: (data) => {
|
||||
void queryClient.invalidateQueries({
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Controller, FormProvider, useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { APIError } from '@/api';
|
||||
import { parseAPIError } from '@/api/parseAPIError';
|
||||
import { Box, Text, TextErrors } from '@/components';
|
||||
import { Modal } from '@/components/Modal';
|
||||
@@ -23,12 +24,14 @@ export const ModalAddMailDomain = () => {
|
||||
|
||||
const addMailDomainValidationSchema = z.object({
|
||||
name: z.string().min(1, t('Example: saint-laurent.fr')),
|
||||
supportEmail: z.string().email(t('Please enter a valid email address')),
|
||||
});
|
||||
|
||||
const methods = useForm<{ name: string }>({
|
||||
const methods = useForm<{ name: string; supportEmail: string }>({
|
||||
delayError: 0,
|
||||
defaultValues: {
|
||||
name: '',
|
||||
supportEmail: '',
|
||||
},
|
||||
mode: 'onChange',
|
||||
reValidateMode: 'onChange',
|
||||
@@ -39,7 +42,7 @@ export const ModalAddMailDomain = () => {
|
||||
onSuccess: (mailDomain) => {
|
||||
router.push(`/mail-domains/${mailDomain.slug}`);
|
||||
},
|
||||
onError: (error) => {
|
||||
onError: (error: APIError) => {
|
||||
const unhandledCauses = parseAPIError({
|
||||
error,
|
||||
errorParams: [
|
||||
@@ -87,8 +90,8 @@ export const ModalAddMailDomain = () => {
|
||||
const onSubmitCallback = (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
void methods.handleSubmit(({ name }) => {
|
||||
void addMailDomain(name);
|
||||
void methods.handleSubmit(({ name, supportEmail }) => {
|
||||
void addMailDomain({ name, supportEmail });
|
||||
})();
|
||||
};
|
||||
|
||||
@@ -167,6 +170,27 @@ export const ModalAddMailDomain = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Box $margin={{ vertical: '10px' }}>
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="supportEmail"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
aria-required
|
||||
required
|
||||
label={t('Support email address')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState?.error?.message
|
||||
? fieldState.error.message
|
||||
: t('E.g. : support@saint-laurent.fr')
|
||||
}
|
||||
{...methods.register('supportEmail')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</form>
|
||||
|
||||
{isPending && (
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface MailDomain {
|
||||
updated_at: string;
|
||||
slug: string;
|
||||
status: 'pending' | 'enabled' | 'failed' | 'disabled';
|
||||
support_email: string;
|
||||
abilities: {
|
||||
get: boolean;
|
||||
patch: boolean;
|
||||
|
||||
@@ -14,6 +14,7 @@ const mockMailDomain: MailDomain = {
|
||||
name: 'example.com',
|
||||
slug: 'example-com',
|
||||
status: 'enabled',
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
@@ -31,6 +32,7 @@ const mockMailDomainAsViewer: MailDomain = {
|
||||
name: 'example.com',
|
||||
slug: 'example-com',
|
||||
status: 'enabled',
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: false,
|
||||
|
||||
@@ -14,6 +14,7 @@ const mockMailDomain: MailDomain = {
|
||||
status: 'enabled',
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
get: true,
|
||||
patch: true,
|
||||
|
||||
@@ -9,6 +9,7 @@ const getElements = (page: Page) => {
|
||||
});
|
||||
const form = page.locator('form');
|
||||
const inputName = form.getByLabel('Domain name');
|
||||
const inputSupportEmail = form.getByLabel('Support email address');
|
||||
const buttonSubmit = page.getByRole('button', {
|
||||
name: 'Add the domain',
|
||||
});
|
||||
@@ -22,6 +23,7 @@ const getElements = (page: Page) => {
|
||||
linkIndexPageAddDomain,
|
||||
form,
|
||||
inputName,
|
||||
inputSupportEmail,
|
||||
buttonCancel,
|
||||
buttonSubmit,
|
||||
};
|
||||
@@ -50,6 +52,7 @@ test.describe('Add Mail Domains', () => {
|
||||
}),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(inputName).toBeVisible();
|
||||
await expect(inputName).toBeVisible();
|
||||
|
||||
await expect(page.getByText('Example: saint-laurent.fr')).toBeVisible();
|
||||
@@ -82,12 +85,17 @@ test.describe('Add Mail Domains', () => {
|
||||
test('checks form invalid status', async ({ page }) => {
|
||||
await page.goto('/mail-domains/');
|
||||
|
||||
const { linkIndexPageAddDomain, inputName, buttonSubmit } =
|
||||
getElements(page);
|
||||
const {
|
||||
linkIndexPageAddDomain,
|
||||
inputName,
|
||||
inputSupportEmail,
|
||||
buttonSubmit,
|
||||
} = getElements(page);
|
||||
|
||||
await linkIndexPageAddDomain.click();
|
||||
|
||||
await expect(inputName).toBeVisible();
|
||||
await expect(inputSupportEmail).toBeVisible();
|
||||
await expect(page.getByText('Example: saint-laurent.fr')).toBeVisible();
|
||||
|
||||
await expect(
|
||||
@@ -111,16 +119,23 @@ test.describe('Add Mail Domains', () => {
|
||||
browserName,
|
||||
}) => {
|
||||
const mailDomainName = randomName('versailles.fr', browserName, 1)[0];
|
||||
const mailDomainSupportMail = 'support@'.concat(mailDomainName);
|
||||
const mailDomainSlug = mailDomainName.replace('.', '');
|
||||
|
||||
await page.goto('/mail-domains/');
|
||||
|
||||
const { linkIndexPageAddDomain, inputName, buttonSubmit } =
|
||||
getElements(page);
|
||||
const {
|
||||
linkIndexPageAddDomain,
|
||||
inputName,
|
||||
inputSupportEmail,
|
||||
buttonSubmit,
|
||||
} = getElements(page);
|
||||
|
||||
await linkIndexPageAddDomain.click();
|
||||
|
||||
await inputName.fill(mailDomainName);
|
||||
await inputSupportEmail.fill(mailDomainSupportMail);
|
||||
|
||||
await buttonSubmit.click();
|
||||
|
||||
await expect(page).toHaveURL(`/mail-domains/${mailDomainSlug}/`);
|
||||
|
||||
Reference in New Issue
Block a user