✨(frontend) display domain expected config for DNS
If any action is required on the domain, display the expected domain configuration in the modal window to inform the user of actions required to operate the domain.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import { MailDomain } from '@/features/mail-domains/domains';
|
||||
import { AppWrapper } from '@/tests/utils';
|
||||
|
||||
import { MailDomainView } from '../components/MailDomainView';
|
||||
|
||||
const toast = jest.fn();
|
||||
jest.mock('@openfun/cunningham-react', () => ({
|
||||
...jest.requireActual('@openfun/cunningham-react'),
|
||||
useToastProvider: () => ({
|
||||
toast,
|
||||
}),
|
||||
}));
|
||||
|
||||
const mockMailDomain: MailDomain = {
|
||||
id: '123e4567-e89b-12d3-a456-426614174000',
|
||||
name: 'example.com',
|
||||
status: 'action_required',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
slug: 'example-com',
|
||||
support_email: 'support@example.com',
|
||||
abilities: {
|
||||
delete: false,
|
||||
manage_accesses: true,
|
||||
get: true,
|
||||
patch: true,
|
||||
put: true,
|
||||
post: true,
|
||||
},
|
||||
action_required_details: {
|
||||
mx: 'Je veux que le MX du domaine soit mx.ox.numerique.gouv.fr....',
|
||||
},
|
||||
expected_config: [
|
||||
{ target: '', type: 'mx', value: 'mx.ox.numerique.gouv.fr.' },
|
||||
{
|
||||
target: 'dimail._domainkey',
|
||||
type: 'txt',
|
||||
value:
|
||||
'v=DKIM1; h=sha256; k=rsa; p=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||
},
|
||||
{ target: 'imap', type: 'cname', value: 'imap.ox.numerique.gouv.fr.' },
|
||||
{ target: 'smtp', type: 'cname', value: 'smtp.ox.numerique.gouv.fr.' },
|
||||
{
|
||||
target: '',
|
||||
type: 'txt',
|
||||
value: 'v=spf1 include:_spf.ox.numerique.gouv.fr -all',
|
||||
},
|
||||
{
|
||||
target: 'webmail',
|
||||
type: 'cname',
|
||||
value: 'webmail.ox.numerique.gouv.fr.',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('<MailDomainView />', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.restore();
|
||||
});
|
||||
it('display action required button and open modal with information when domain status is action_required', () => {
|
||||
render(<MailDomainView mailDomain={mockMailDomain} />, {
|
||||
wrapper: AppWrapper,
|
||||
});
|
||||
// Check if action required button is displayed
|
||||
const actionButton = screen.getByText('Actions required');
|
||||
expect(actionButton).toBeInTheDocument();
|
||||
|
||||
// Click the button and verify modal content
|
||||
fireEvent.click(actionButton);
|
||||
|
||||
// Verify modal title and content
|
||||
expect(screen.getByText('Required actions on domain')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
/Je veux que le MX du domaine soit mx.ox.numerique.gouv.fr/,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
|
||||
// Verify DNS configuration section
|
||||
expect(
|
||||
screen.getByText(/DNS Configuration Required:/i),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText(/imap.ox.numerique.gouv.fr./i)).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(/webmail.ox.numerique.gouv.fr./i),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Modal, ModalSize } from '@openfun/cunningham-react';
|
||||
import {
|
||||
Modal,
|
||||
ModalSize,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import * as React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -15,6 +20,7 @@ type Props = {
|
||||
};
|
||||
export const MailDomainView = ({ mailDomain }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToastProvider();
|
||||
const [showModal, setShowModal] = React.useState(false);
|
||||
const currentRole = mailDomain.abilities.delete
|
||||
? Role.OWNER
|
||||
@@ -46,6 +52,10 @@ export const MailDomainView = ({ mailDomain }: Props) => {
|
||||
const handleShowModal = () => {
|
||||
setShowModal(true);
|
||||
};
|
||||
const copyToClipboard = async (text: string) => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
toast(t('copy done'), VariantType.SUCCESS);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -62,18 +72,69 @@ export const MailDomainView = ({ mailDomain }: Props) => {
|
||||
)}
|
||||
</p>
|
||||
<h3>{t('Actions required detail')}</h3>
|
||||
|
||||
<pre>
|
||||
{mailDomain.action_required_details &&
|
||||
Object.entries(mailDomain.action_required_details).map(
|
||||
([check, value]) => (
|
||||
<ul key={check}>
|
||||
<li>
|
||||
([check, value], index) => (
|
||||
<ul key={`action-required-list-${index}`}>
|
||||
<li key={`action-required-${index}`}>
|
||||
<b>{check}</b>: {value}
|
||||
</li>
|
||||
</ul>
|
||||
),
|
||||
)}
|
||||
</pre>
|
||||
{mailDomain.expected_config && (
|
||||
<Box $margin={{ bottom: 'medium' }}>
|
||||
<h3>{t('DNS Configuration Required:')}</h3>
|
||||
<pre>
|
||||
<div
|
||||
style={{
|
||||
whiteSpace: 'pre-wrap',
|
||||
overflowWrap: 'break-word',
|
||||
}}
|
||||
>
|
||||
{t('Add the following DNS values:')}
|
||||
<ul>
|
||||
{mailDomain.expected_config.map((item, index) => (
|
||||
<li
|
||||
key={`dns-record-${index}`}
|
||||
style={{ marginBottom: '10px' }}
|
||||
>
|
||||
{item.target && (
|
||||
<>
|
||||
<b>{item.target.toUpperCase()}</b> -{' '}
|
||||
</>
|
||||
)}
|
||||
<b>{item.type.toUpperCase()}</b> {t('with value:')}{' '}
|
||||
<span style={{ backgroundColor: '#d4e5f5' }}>
|
||||
{item.value}
|
||||
</span>
|
||||
<button
|
||||
style={{
|
||||
padding: '2px 5px',
|
||||
marginLeft: '10px',
|
||||
backgroundColor: '#cccccc',
|
||||
border: 'none',
|
||||
color: 'white',
|
||||
cursor: 'pointer',
|
||||
fontWeight: '500',
|
||||
borderRadius: '5px',
|
||||
}}
|
||||
onClick={() => {
|
||||
void copyToClipboard(item.value);
|
||||
}}
|
||||
>
|
||||
{t('Copy')}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</pre>
|
||||
</Box>
|
||||
)}
|
||||
</Modal>
|
||||
)}
|
||||
<Box $padding="big">
|
||||
|
||||
@@ -17,6 +17,11 @@ export interface MailDomain {
|
||||
delete: boolean;
|
||||
manage_accesses: boolean;
|
||||
};
|
||||
expected_config?: Array<{
|
||||
target: string;
|
||||
type: string;
|
||||
value: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export enum Role {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"Add a team": "Ajouter un groupe",
|
||||
"Add members to the team": "Ajouter des membres à l'équipe",
|
||||
"Add the domain": "Ajouter le domaine",
|
||||
"Add the following DNS values:": "Ajouter les valeurs DNS suivantes :",
|
||||
"Add to group": "Ajouter au groupe",
|
||||
"Address: National Agency for Territorial Cohesion - 20, avenue de Ségur TSA 10717 75 334 Paris Cedex 07 Paris": "Adresse : Agence Nationale de la Cohésion des Territoires - 20, avenue de Ségur TSA 10717 75 334 Paris Cedex 07",
|
||||
"Administration": "Administration",
|
||||
@@ -55,6 +56,7 @@
|
||||
"Content modal to delete the team": "Contenu modal pour supprimer le groupe",
|
||||
"Content modal to update the team": "Contenu modal pour mettre à jour le groupe",
|
||||
"Cookies placed": "Cookies déposés",
|
||||
"Copy": "Copier",
|
||||
"Copyright": "Copyright",
|
||||
"Create a mailbox": "Créer une boîte mail",
|
||||
"Create a mailbox in {{name}} domain": "Créer une boîte mail dans le domaine {{name}}",
|
||||
@@ -65,6 +67,7 @@
|
||||
"Create the team": "Créer le groupe",
|
||||
"Create your first team by clicking on the \"Create a new team\" button.": "Créez votre premier groupe en cliquant sur le bouton \"Créer un nouveau groupe\".",
|
||||
"Created at": "Créé le",
|
||||
"DNS Configuration Required:": "Configuration DNS requise :",
|
||||
"Declaration established on June 25, 2024.": "Établie le 25 juin 2024.",
|
||||
"Defender of Rights - Free response - 71120 75342 Paris CEDEX 07": "Défenseur des droits\nLibre réponse 71120 75342 Paris CEDEX 07",
|
||||
"Delete the team": "Supprimer le groupe",
|
||||
@@ -222,7 +225,9 @@
|
||||
"[pending]": "[en attente]",
|
||||
"accessibility-contact-defenseurdesdroits": "Contacter le délégué du<1>Défenseur des droits dans votre région</1>",
|
||||
"accessibility-form-defenseurdesdroits": "Écrire un message au<1>Défenseur des droits</1>",
|
||||
"copy done": "copié",
|
||||
"mail domains list loading": "chargement de la liste des domaines de messagerie",
|
||||
"with value:": "avec la valeur:",
|
||||
"{{count}} member_many": "{{count}} membres",
|
||||
"{{count}} member_one": "{{count}} membre",
|
||||
"{{count}} member_other": "{{count}} membres",
|
||||
|
||||
Reference in New Issue
Block a user