✨(frontend) add tabs for mail domain page (#466)
Currently, it is complicated to understand the navigation between mailbox management and role management for an email domain. This is why we add tabs with explicit naming
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
const path = require('path');
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: 'export',
|
||||
@@ -5,6 +7,9 @@ const nextConfig = {
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
sassOptions: {
|
||||
includePaths: [path.join(__dirname, 'src')],
|
||||
},
|
||||
compiler: {
|
||||
// Enables the styled-components SWC transform
|
||||
styledComponents: true,
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"react-hook-form": "7.53.0",
|
||||
"react-i18next": "15.0.2",
|
||||
"react-select": "5.8.1",
|
||||
"sass": "1.80.3",
|
||||
"styled-components": "6.1.13",
|
||||
"zod": "3.23.8",
|
||||
"zustand": "4.5.5"
|
||||
|
||||
54
src/frontend/apps/desk/src/components/tabs/CustomTabs.tsx
Normal file
54
src/frontend/apps/desk/src/components/tabs/CustomTabs.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import * as React from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
|
||||
|
||||
import { Box } from '@/components';
|
||||
|
||||
import style from './custom-tabs.module.scss';
|
||||
|
||||
type TabsOption = {
|
||||
ariaLabel?: string;
|
||||
label: string;
|
||||
iconName?: string;
|
||||
id?: string;
|
||||
content: ReactNode;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
tabs: TabsOption[];
|
||||
};
|
||||
|
||||
export const CustomTabs = ({ tabs }: Props) => {
|
||||
return (
|
||||
<div className={style.customTabsContainer}>
|
||||
<Tabs>
|
||||
<TabList>
|
||||
{tabs.map((tab) => {
|
||||
const id = tab.id ?? tab.label;
|
||||
return (
|
||||
<Tab key={id} aria-label={tab.ariaLabel} id={id}>
|
||||
<Box $direction="row" $align="center" $gap="5px">
|
||||
{tab.iconName && (
|
||||
<span className="material-icons" aria-hidden="true">
|
||||
{tab.iconName}
|
||||
</span>
|
||||
)}
|
||||
{tab.label}
|
||||
</Box>
|
||||
</Tab>
|
||||
);
|
||||
})}
|
||||
</TabList>
|
||||
|
||||
{tabs.map((tab) => {
|
||||
const id = tab.id ?? tab.label;
|
||||
return (
|
||||
<TabPanel key={id} id={id}>
|
||||
{tab.content}
|
||||
</TabPanel>
|
||||
);
|
||||
})}
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
.customTabsContainer {
|
||||
:global {
|
||||
.react-aria-TabList {
|
||||
display: flex;
|
||||
|
||||
&[data-orientation='horizontal'] {
|
||||
.react-aria-Tab {
|
||||
border-bottom: 2px solid var(--c--theme--colors--greyscale-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-aria-Tab {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
position: relative;
|
||||
color: var(--c--theme--colors--greyscale-700);
|
||||
transition: color 200ms;
|
||||
|
||||
--border-color: transparent;
|
||||
|
||||
forced-color-adjust: none;
|
||||
|
||||
&[data-hovered],
|
||||
&[data-focused] {
|
||||
color: var(--c--theme--colors--greyscale-900);
|
||||
}
|
||||
|
||||
&[data-selected] {
|
||||
border-bottom: 2px solid var(--c--theme--colors--primary-600) !important;
|
||||
color: var(--c--theme--colors--primary-600);
|
||||
}
|
||||
|
||||
&[data-disabled] {
|
||||
color: var(--c--theme--colors--greyscale-500);
|
||||
|
||||
&[data-selected] {
|
||||
--border-color: var(--c--theme--colors--greyscale-200);
|
||||
}
|
||||
}
|
||||
|
||||
&[data-focus-visible]::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 4px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--c--theme--colors--primary-600);
|
||||
}
|
||||
}
|
||||
|
||||
.react-aria-TabPanel {
|
||||
margin-top: 4px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
|
||||
&[data-focus-visible] {
|
||||
outline: 2px solid var(--c--theme--colors--primary-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
import { Button } from '@openfun/cunningham-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { AccessesGrid } from '@/features/mail-domains/access-management/components/AccessesGrid';
|
||||
import MailDomainsLogo from '@/features/mail-domains/assets/mail-domains-logo.svg';
|
||||
|
||||
import { MailDomain, Role } from '../../domains';
|
||||
|
||||
@@ -17,50 +12,6 @@ export const AccessesContent = ({
|
||||
currentRole: Role;
|
||||
}) => (
|
||||
<>
|
||||
<TopBanner mailDomain={mailDomain} />
|
||||
<AccessesGrid mailDomain={mailDomain} currentRole={currentRole} />
|
||||
</>
|
||||
);
|
||||
|
||||
const TopBanner = ({ mailDomain }: { mailDomain: MailDomain }) => {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box
|
||||
$direction="column"
|
||||
$margin={{ all: 'big', bottom: 'tiny' }}
|
||||
$gap="1rem"
|
||||
>
|
||||
<Box
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$gap="2.25rem"
|
||||
$justify="space-between"
|
||||
>
|
||||
<Box $direction="row" $margin="none" $gap="0.5rem">
|
||||
<MailDomainsLogo aria-hidden="true" />
|
||||
<Text $margin="none" as="h3" $size="h3">
|
||||
{mailDomain?.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box $direction="row" $justify="flex-end">
|
||||
<Box $display="flex" $direction="row" $gap="8rem">
|
||||
{mailDomain?.abilities?.manage_accesses && (
|
||||
<Button
|
||||
color="tertiary"
|
||||
aria-label={t('Manage {{name}} domain mailboxes', {
|
||||
name: mailDomain?.name,
|
||||
})}
|
||||
onClick={() => router.push(`/mail-domains/${mailDomain.slug}/`)}
|
||||
>
|
||||
{t('Manage mailboxes')}
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -106,8 +106,6 @@ export const AccessesGrid = ({
|
||||
|
||||
return (
|
||||
<Card
|
||||
$padding={{ bottom: 'small' }}
|
||||
$margin={{ all: 'big', top: 'none' }}
|
||||
$overflow="auto"
|
||||
$css={`
|
||||
& .c__pagination__goto {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { AccessesGrid } from '@/features/mail-domains/access-management';
|
||||
import { AppWrapper } from '@/tests/utils';
|
||||
|
||||
import { MailDomain, Role } from '../../../domains';
|
||||
@@ -61,58 +59,9 @@ describe('AccessesContent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the top banner and accesses grid correctly', () => {
|
||||
it('renders the accesses grid correctly', () => {
|
||||
renderAccessesContent();
|
||||
|
||||
expect(screen.getByText(mockMailDomain.name)).toBeInTheDocument();
|
||||
expect(screen.getByTestId('mail-domains-logo')).toBeInTheDocument();
|
||||
expect(screen.getByText('Mock AccessesGrid')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the "Manage mailboxes" button when the user has access', () => {
|
||||
renderAccessesContent();
|
||||
|
||||
const manageMailboxesButton = screen.getByRole('button', {
|
||||
name: /Manage example.com domain mailboxes/,
|
||||
});
|
||||
|
||||
expect(manageMailboxesButton).toBeInTheDocument();
|
||||
|
||||
expect(AccessesGrid).toHaveBeenCalledWith(
|
||||
{ currentRole: Role.ADMIN, mailDomain: mockMailDomain },
|
||||
{}, // adding this empty object is necessary to load jest context and that AccessesGrid is a mock
|
||||
);
|
||||
});
|
||||
|
||||
it('does not render the "Manage mailboxes" button if the user lacks manage_accesses ability', () => {
|
||||
const mailDomainWithoutAccess = {
|
||||
...mockMailDomain,
|
||||
abilities: {
|
||||
...mockMailDomain.abilities,
|
||||
manage_accesses: false,
|
||||
},
|
||||
};
|
||||
|
||||
renderAccessesContent(Role.ADMIN, mailDomainWithoutAccess);
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', {
|
||||
name: /Manage mailboxes/i,
|
||||
}),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('navigates to the mailboxes management page when "Manage mailboxes" is clicked', async () => {
|
||||
renderAccessesContent();
|
||||
|
||||
const manageMailboxesButton = screen.getByRole('button', {
|
||||
name: /Manage example.com domain mailboxes/,
|
||||
});
|
||||
|
||||
await userEvent.click(manageMailboxesButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockRouterPush).toHaveBeenCalledWith(`/mail-domains/example-com/`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import * as React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { CustomTabs } from '@/components/tabs/CustomTabs';
|
||||
import { AccessesContent } from '@/features/mail-domains/access-management';
|
||||
import MailDomainsLogo from '@/features/mail-domains/assets/mail-domains-logo.svg';
|
||||
import { MailDomain, Role } from '@/features/mail-domains/domains';
|
||||
import { MailDomainsContent } from '@/features/mail-domains/mailboxes';
|
||||
|
||||
type Props = {
|
||||
mailDomain: MailDomain;
|
||||
};
|
||||
export const MailDomainView = ({ mailDomain }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const currentRole = mailDomain.abilities.delete
|
||||
? Role.OWNER
|
||||
: mailDomain.abilities.manage_accesses
|
||||
? Role.ADMIN
|
||||
: Role.VIEWER;
|
||||
|
||||
const tabs = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
ariaLabel: t('Go to mailbox management'),
|
||||
id: 'mails',
|
||||
iconName: 'mail',
|
||||
label: t('Mailbox management'),
|
||||
content: <MailDomainsContent mailDomain={mailDomain} />,
|
||||
},
|
||||
{
|
||||
ariaLabel: t('Go to accesses management'),
|
||||
id: 'accesses',
|
||||
iconName: 'people',
|
||||
label: t('Access management'),
|
||||
content: (
|
||||
<AccessesContent mailDomain={mailDomain} currentRole={currentRole} />
|
||||
),
|
||||
},
|
||||
];
|
||||
}, [t, currentRole, mailDomain]);
|
||||
|
||||
return (
|
||||
<Box $padding="big">
|
||||
<Box
|
||||
$width="100%"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$gap="2.25rem"
|
||||
$justify="center"
|
||||
>
|
||||
<Box
|
||||
$direction="row"
|
||||
$justify="center"
|
||||
$margin={{ bottom: 'big' }}
|
||||
$gap="0.5rem"
|
||||
>
|
||||
<MailDomainsLogo aria-hidden="true" />
|
||||
<Text $margin="none" as="h3" $size="h3">
|
||||
{mailDomain?.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<CustomTabs tabs={tabs} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -9,14 +9,12 @@ import {
|
||||
VariantType,
|
||||
usePagination,
|
||||
} from '@openfun/cunningham-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Card, Text, TextErrors, TextStyled } from '@/components';
|
||||
import { ModalCreateMailbox } from '@/features/mail-domains/mailboxes';
|
||||
|
||||
import { default as MailDomainsLogo } from '../../assets/mail-domains-logo.svg';
|
||||
import { PAGE_SIZE } from '../../conf';
|
||||
import { MailDomain } from '../../domains/types';
|
||||
import { useMailboxes } from '../api/useMailboxes';
|
||||
@@ -99,12 +97,7 @@ export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
showMailBoxCreationForm={setIsCreateMailboxFormVisible}
|
||||
/>
|
||||
|
||||
<Card
|
||||
$padding={{ bottom: 'small' }}
|
||||
$margin={{ all: 'big', top: 'none' }}
|
||||
$overflow="auto"
|
||||
aria-label={t('Mailboxes list card')}
|
||||
>
|
||||
<Card $overflow="auto" aria-label={t('Mailboxes list card')}>
|
||||
{error && <TextErrors causes={error.cause} />}
|
||||
|
||||
<DataGrid
|
||||
@@ -153,47 +146,19 @@ const TopBanner = ({
|
||||
mailDomain: MailDomain;
|
||||
showMailBoxCreationForm: (value: boolean) => void;
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box
|
||||
$direction="column"
|
||||
$margin={{ all: 'big', bottom: 'tiny' }}
|
||||
$gap="1rem"
|
||||
>
|
||||
<Box $direction="column" $gap="1rem">
|
||||
<AlertStatus status={mailDomain.status} />
|
||||
|
||||
<Box
|
||||
$direction="row"
|
||||
$justify="flex-end"
|
||||
$margin={{ bottom: 'small' }}
|
||||
$align="center"
|
||||
$gap="2.25rem"
|
||||
$justify="space-between"
|
||||
>
|
||||
<Box $direction="row" $margin="none" $gap="0.5rem">
|
||||
<MailDomainsLogo aria-hidden="true" />
|
||||
<Text $margin="none" as="h3" $size="h3">
|
||||
{mailDomain?.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box $direction="row" $justify="space-between">
|
||||
<AlertStatus status={mailDomain.status} />
|
||||
</Box>
|
||||
<Box $direction="row" $justify="flex-end">
|
||||
<Box $display="flex" $direction="row" $gap="0.5rem">
|
||||
{mailDomain?.abilities?.manage_accesses && (
|
||||
<Button
|
||||
color="tertiary"
|
||||
aria-label={t('Manage {{name}} domain members', {
|
||||
name: mailDomain?.name,
|
||||
})}
|
||||
onClick={() =>
|
||||
router.push(`/mail-domains/${mailDomain.slug}/accesses/`)
|
||||
}
|
||||
>
|
||||
{t('Manage accesses')}
|
||||
</Button>
|
||||
)}
|
||||
<Box $display="flex" $direction="row">
|
||||
{mailDomain?.abilities.post && (
|
||||
<Button
|
||||
aria-label={t('Create a mailbox in {{name}} domain', {
|
||||
|
||||
@@ -187,25 +187,6 @@ describe('MailDomainsContent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('redirects to accesses management page when button is clicked by granted user', async () => {
|
||||
fetchMock.get('end:/mail-domains/example-com/mailboxes/?page=1', {
|
||||
count: 0,
|
||||
results: [],
|
||||
});
|
||||
|
||||
render(<MailDomainsContent mailDomain={mockMailDomain} />, {
|
||||
wrapper: AppWrapper,
|
||||
});
|
||||
|
||||
await waitFor(async () => {
|
||||
await userEvent.click(screen.getByText('Manage accesses'));
|
||||
});
|
||||
|
||||
expect(mockPush).toHaveBeenCalledWith(
|
||||
'/mail-domains/example-com/accesses/',
|
||||
);
|
||||
});
|
||||
|
||||
it('displays the correct alert based on mail domain status', async () => {
|
||||
fetchMock.get('end:/mail-domains/example-com/mailboxes/?page=1', {
|
||||
count: 0,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"de": { "translation": {} },
|
||||
"en": {
|
||||
"translation": {
|
||||
"{{count}} member_many": "{{count}} members",
|
||||
@@ -11,6 +10,7 @@
|
||||
"translation": {
|
||||
"0 group to display.": "0 groupe à afficher.",
|
||||
"Access icon": "Icône d'accès",
|
||||
"Access management": "Gestion des rôles",
|
||||
"Accesses list card": "Carte de la liste des accès",
|
||||
"Accessibility statement": "Déclaration d'accessibilité",
|
||||
"Accessibility: non-compliant": "Accessibilité : non conforme",
|
||||
@@ -68,6 +68,8 @@
|
||||
"First name": "Prénom",
|
||||
"Freedom Equality Fraternity Logo": "Logo Liberté Égalité Fraternité",
|
||||
"French Interministerial Directorate for Digital Affairs (DINUM), 20 avenue de Ségur 75007 Paris.": "Direction interministérielle des affaires numériques (DINUM), 20 avenue de Segur 75007 Paris.",
|
||||
"Go to accesses management": "Aller à la gestion des rôles",
|
||||
"Go to mailbox management": "Aller à la gestion des mails",
|
||||
"Group details": "Détails du groupe",
|
||||
"Group members": "Membres du groupe",
|
||||
"Groups": "Groupes",
|
||||
@@ -94,12 +96,9 @@
|
||||
"Mail domains panel": "Panel des domaines de messagerie",
|
||||
"Mailbox created!": "Boîte mail créée !",
|
||||
"Mailbox creation form": "Formulaire de création de boite mail",
|
||||
"Mailbox management": "Gestion des boîtes mails",
|
||||
"Mailboxes list": "Liste des boîtes mail",
|
||||
"Mailboxes list card": "Carte liste des boîtes mails",
|
||||
"Manage accesses": "Gérer les accès",
|
||||
"Manage mailboxes": "Gérer les boîtes mails",
|
||||
"Manage {{name}} domain mailboxes": "Gérer les boîtes mails du domaine {{name}}",
|
||||
"Manage {{name}} domain members": "Gérer les membres du domaine {{name}}",
|
||||
"Marianne Logo": "Logo Marianne",
|
||||
"Member": "Membre",
|
||||
"Member icon": "Icône de membre",
|
||||
@@ -155,6 +154,7 @@
|
||||
"The National Agency for Territorial Cohesion undertakes to make its\n service accessible, in accordance with article 47 of law no. 2005-102\n of February 11, 2005.": "L'Agence Nationale de la Cohésion des Territoires s’engage à rendre son service accessible, conformément à l’article 47 de la loi n° 2005-102 du 11 février 2005.",
|
||||
"The access has been removed from the domain": "L'accès a été supprimé du domaine",
|
||||
"The domain name encounters an error. Please contact our support team to solve the problem:": "Le nom de domaine rencontre une erreur. Veuillez contacter notre support pour résoudre le problème :",
|
||||
"The mail domain secret is misconfigured. Please, contact our support team to solve the issue: suiteterritoriale@anct.gouv.fr": "Le secret du domaine de messagerie est mal configuré. Veuillez contacter notre support pour résoudre le problème : suiteterritoriale@anct.gouv.fr",
|
||||
"The member has been removed from the team": "Le membre a été supprimé de votre groupe",
|
||||
"The role has been updated": "Le rôle a bien été mis à jour",
|
||||
"The team has been removed.": "Le groupe a été supprimé.",
|
||||
@@ -177,11 +177,11 @@
|
||||
"Update the team": "Mettre à jour le groupe",
|
||||
"Validate": "Valider",
|
||||
"Validate the modification": "Valider la modification",
|
||||
"Version: {{release}}": "Version : {{release}}",
|
||||
"Viewer": "Lecteur",
|
||||
"We simply comply with the law, which states that certain audience measurement tools, properly configured to respect privacy, are exempt from prior authorization.": "Nous nous conformons simplement à la loi, qui stipule que certains outils de mesure d’audience, correctement configurés pour respecter la vie privée, sont exemptés de toute autorisation préalable.",
|
||||
"You are the last owner, you cannot be removed from your domain.": "Vous êtes le dernier propriétaire, vous ne pouvez pas être retiré de votre domaine.",
|
||||
"You are the last owner, you cannot be removed from your team.": "Vous êtes le dernier propriétaire, vous ne pouvez pas être retiré de votre groupe.",
|
||||
"You are the sole owner of this domain. Make another member the domain owner, before you can change your own role.": "Vous êtes le seul propriétaire de ce domaine. Faites d'un autre membre le propriétaire du domaine avant de modifier votre rôle.",
|
||||
"You are the sole owner of this group. Make another member the group owner, before you can change your own role.": "Vous êtes l’unique propriétaire de ce groupe. Désignez un autre membre comme propriétaire du groupe, avant de pouvoir modifier votre propre rôle.",
|
||||
"You can oppose the tracking of your browsing on this website.": "Vous pouvez vous opposer au suivi de votre navigation sur ce site.",
|
||||
"You can:": "Vous pouvez :",
|
||||
@@ -190,7 +190,6 @@
|
||||
"You must have minimum 1 character": "Vous devez entrer au moins 1 caractère",
|
||||
"Your domain name is being validated. You will not be able to create mailboxes until your domain name has been validated by our team.": "Votre nom de domaine est en cours de validation. Vous ne pourrez créer de boîtes mail que lorsque votre nom de domaine sera validé par notre équipe.",
|
||||
"Your request cannot be processed because the server is experiencing an error. If the problem persists, please contact our support to resolve the issue: suiteterritoriale@anct.gouv.fr": "Votre demande ne peut pas être traitée car le serveur rencontre une erreur. Si le problème persiste, veuillez contacter notre support pour résoudre le problème : suiteterritoriale@anct.gouv.fr",
|
||||
"Your request to create a mailbox cannot be completed due to incorrect settings on our server. Please contact our support team to resolve the problem: suiteterritoriale@anct.gouv.fr": "Votre demande de création de boîte mail ne peut pas être complétée en raison de paramètres incorrects sur notre serveur. Veuillez contacter notre équipe support pour résoudre le problème : suiteterritoriale@anct.gouv.fr",
|
||||
"[disabled]": "[désactivé]",
|
||||
"[enabled]": "[actif]",
|
||||
"[failed]": "[erroné]",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Loader } from '@openfun/cunningham-react';
|
||||
import { useRouter as useNavigate } from 'next/navigation';
|
||||
import { useRouter } from 'next/router';
|
||||
import { ReactElement } from 'react';
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
import { Box } from '@/components';
|
||||
import { TextErrors } from '@/components/TextErrors';
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
MailDomainsLayout,
|
||||
useMailDomain,
|
||||
} from '@/features/mail-domains/domains';
|
||||
import { MailDomainsContent } from '@/features/mail-domains/mailboxes';
|
||||
import { MailDomainView } from '@/features/mail-domains/domains/components/MailDomainView';
|
||||
import { NextPageWithLayout } from '@/types/next';
|
||||
|
||||
const MailboxesPage: NextPageWithLayout = () => {
|
||||
@@ -45,9 +45,13 @@ const MailboxesPage: NextPageWithLayout = () => {
|
||||
<Loader />
|
||||
</Box>
|
||||
);
|
||||
} else {
|
||||
return mailDomain ? <MailDomainsContent mailDomain={mailDomain} /> : null;
|
||||
}
|
||||
|
||||
if (!mailDomain) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <MailDomainView mailDomain={mailDomain} />;
|
||||
};
|
||||
|
||||
MailboxesPage.getLayout = function getLayout(page: ReactElement) {
|
||||
|
||||
@@ -211,6 +211,19 @@ test.describe('Mail domain', () => {
|
||||
},
|
||||
];
|
||||
|
||||
test('checks if all tabs are visible', async ({ page }) => {
|
||||
await interceptCommonApiCalls(page, mailDomainsFixtures);
|
||||
|
||||
await clickOnMailDomainsNavButton(page);
|
||||
|
||||
await assertMailDomainUpperElementsAreVisible(page);
|
||||
|
||||
await expect(
|
||||
page.getByLabel('Go to accesses management'),
|
||||
).toBeVisible();
|
||||
await expect(page.getByLabel('Go to mailbox management')).toBeVisible();
|
||||
});
|
||||
|
||||
test('checks all the elements are visible when domain exist but contains no mailboxes', async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
Reference in New Issue
Block a user