feat: add pages tests
This commit is contained in:
parent
8db726a505
commit
9ed5af6857
20
__spec__/custon-renders.tsx
Normal file
20
__spec__/custon-renders.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { render } from './utils';
|
||||||
|
|
||||||
|
export const renderWithProvider = (Component: ReactNode) => {
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
element: Component,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const router = createMemoryRouter(routes, {
|
||||||
|
initialEntries: ['/'],
|
||||||
|
initialIndex: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
return render(<RouterProvider router={router} />);
|
||||||
|
};
|
||||||
@ -9,11 +9,12 @@ const config: Config = {
|
|||||||
'<rootDir>src',
|
'<rootDir>src',
|
||||||
'<rootDir>',
|
'<rootDir>',
|
||||||
],
|
],
|
||||||
|
rootDir: './',
|
||||||
verbose: true,
|
verbose: true,
|
||||||
preset: 'ts-jest/presets/js-with-ts',
|
preset: 'ts-jest/presets/js-with-ts',
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||||
'./configs/jest/__mocks__/fileMock.ts',
|
'<rootDir>/configs/jest/__mocks__/fileMock.ts',
|
||||||
'\\.(css|less|scss)$': 'identity-obj-proxy',
|
'\\.(css|less|scss)$': 'identity-obj-proxy',
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: [
|
transformIgnorePatterns: [
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import { screen, render } from '@testing-library/react';
|
|
||||||
|
|
||||||
import MoneyControllApp from './MoneyControllApp.ui';
|
|
||||||
|
|
||||||
describe('Test MoneyControllApp', () => {
|
|
||||||
test('Render MoneyControllApp', () => {
|
|
||||||
render(<MoneyControllApp />);
|
|
||||||
|
|
||||||
const appElem = screen.getByTestId('money-contoll-app');
|
|
||||||
expect(appElem).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
32
src/pages/AnalyzePage/ui/AnalyzePage.spec.tsx
Normal file
32
src/pages/AnalyzePage/ui/AnalyzePage.spec.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import AnalyzePage from './AnalyzePage.ui';
|
||||||
|
import AnalyzePageToolbar from './AnalyzePageToolbar.ui';
|
||||||
|
|
||||||
|
describe('Test AnalyzePage', () => {
|
||||||
|
const setup = () => render(
|
||||||
|
<AnalyzePage data-testid="analyze-page" />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const pageElem = screen.getByTestId('analyze-page');
|
||||||
|
expect(pageElem).toBeVisible();
|
||||||
|
expect(pageElem).toHaveTextContent('Analyze page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test AnalyzePageToolbar', () => {
|
||||||
|
const setup = () => render(
|
||||||
|
<AnalyzePageToolbar data-testid="analyze-page-toolbar" />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByTestId('analyze-page-toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
expect(toolbarElem).toHaveTextContent('Analyze Page Toolbar');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import type { FC } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
const AnalyzePage: FC = () => (
|
type AnalyzePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
<div>
|
const AnalyzePage: FC<AnalyzePageProps> = (props) => (
|
||||||
|
<div {...props}>
|
||||||
Analyze page
|
Analyze page
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
const AnalyzePageToolbar = () => (
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
<Toolbar>
|
import type { FC } from 'react';
|
||||||
|
|
||||||
|
type AnalyzePageToolbarProps = ToolbarProps;
|
||||||
|
const AnalyzePageToolbar: FC<AnalyzePageToolbarProps> = (props) => (
|
||||||
|
<Toolbar {...props}>
|
||||||
<Typography noWrap component="div" variant="h6">
|
<Typography noWrap component="div" variant="h6">
|
||||||
Analyze Page Toolbar
|
Analyze Page Toolbar
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
52
src/pages/ErrorPage/ui/ErrorPage.spec.tsx
Normal file
52
src/pages/ErrorPage/ui/ErrorPage.spec.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { ErrorPageToolbar } from 'pages/ErrorPage';
|
||||||
|
import type { ErrorPageToolbarProps } from 'pages/ErrorPage/ui/ErrorPageToolbar.ui';
|
||||||
|
|
||||||
|
import ErrorPage from './ErrorPage.ui';
|
||||||
|
|
||||||
|
import type { ErrorPageProps } from './ErrorPage.ui';
|
||||||
|
|
||||||
|
describe('Test ErrorPage', () => {
|
||||||
|
const setup = (props?: Partial<ErrorPageProps>) => render(
|
||||||
|
<ErrorPage data-testid="error-page" {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render ErrorBoundary', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const pageElem = screen.getByTestId('error-page');
|
||||||
|
expect(pageElem).toBeVisible();
|
||||||
|
expect(pageElem).toHaveTextContent('Что-то пошло не так');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render 404', () => {
|
||||||
|
setup({ type: '404' });
|
||||||
|
|
||||||
|
const pageElem = screen.getByTestId('error-page');
|
||||||
|
expect(pageElem).toBeVisible();
|
||||||
|
expect(pageElem).not.toHaveTextContent('Что-то пошло не так');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test ErrorPageToolbar', () => {
|
||||||
|
const setup = (props?: Partial<ErrorPageToolbarProps>) => render(
|
||||||
|
<ErrorPageToolbar data-testid="error-page-toolbar" {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render ErrorBoundary', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByTestId('error-page-toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
expect(toolbarElem).toHaveTextContent('Непредвиденная ошибка');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render 404', () => {
|
||||||
|
setup({ type: '404' });
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByTestId('error-page-toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
expect(toolbarElem).toHaveTextContent('Страницы не существует');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -4,14 +4,16 @@ import Typography from '@mui/material/Typography';
|
|||||||
import _404Image from 'public/assets/images/404.png';
|
import _404Image from 'public/assets/images/404.png';
|
||||||
import OopsImage from 'public/assets/images/oops.png';
|
import OopsImage from 'public/assets/images/oops.png';
|
||||||
|
|
||||||
|
import type { GridProps } from '@mui/material/Grid/Grid';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
type ErrorPageProps = {
|
export type ErrorPageProps = GridProps & {
|
||||||
type?: '404' | 'ErrorBoundary';
|
type?: '404' | 'ErrorBoundary';
|
||||||
};
|
};
|
||||||
const ErrorPage: FC<ErrorPageProps> = (props) => {
|
const ErrorPage: FC<ErrorPageProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
type = 'ErrorBoundary',
|
type = 'ErrorBoundary',
|
||||||
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (type === 'ErrorBoundary') {
|
if (type === 'ErrorBoundary') {
|
||||||
@ -22,6 +24,7 @@ const ErrorPage: FC<ErrorPageProps> = (props) => {
|
|||||||
direction="column"
|
direction="column"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
rowGap={5}
|
rowGap={5}
|
||||||
|
{...restProps}
|
||||||
>
|
>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
@ -37,7 +40,7 @@ const ErrorPage: FC<ErrorPageProps> = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container justifyContent="center">
|
<Grid container justifyContent="center" {...restProps}>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<img alt="asd" src={_404Image} />
|
<img alt="asd" src={_404Image} />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
type ErrorPageToolbarProps = {
|
export type ErrorPageToolbarProps = ToolbarProps & {
|
||||||
type?: '404' | 'ErrorBoundary';
|
type?: '404' | 'ErrorBoundary';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,10 +16,11 @@ const TITLE: Record<NonNullable<ErrorPageToolbarProps['type']>, string> = {
|
|||||||
const ErrorPageToolbar: FC<ErrorPageToolbarProps> = (props) => {
|
const ErrorPageToolbar: FC<ErrorPageToolbarProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
type = 'ErrorBoundary',
|
type = 'ErrorBoundary',
|
||||||
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Toolbar>
|
<Toolbar {...restProps}>
|
||||||
<Typography noWrap component="div" variant="h6">
|
<Typography noWrap component="div" variant="h6">
|
||||||
{TITLE[type]}
|
{TITLE[type]}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
35
src/pages/PaymentsPage/ui/PaymentsPage.spec.tsx
Normal file
35
src/pages/PaymentsPage/ui/PaymentsPage.spec.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import PaymentsPage from './PaymentsPage.ui';
|
||||||
|
import PaymentsPageToolbar from './PaymentsPageToolbar.ui';
|
||||||
|
|
||||||
|
import type { PaymentsPageProps } from './PaymentsPage.ui';
|
||||||
|
import type { PaymentsPageToolbarProps } from './PaymentsPageToolbar.ui';
|
||||||
|
|
||||||
|
describe('Test PaymentsPage', () => {
|
||||||
|
const setup = (props?: Partial<PaymentsPageProps>) => render(
|
||||||
|
<PaymentsPage data-testid="payments-page" {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const pageElem = screen.getByTestId('payments-page');
|
||||||
|
expect(pageElem).toBeVisible();
|
||||||
|
expect(pageElem).toHaveTextContent('Payments Page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test PaymentsPageToolbar', () => {
|
||||||
|
const setup = (props?: Partial<PaymentsPageToolbarProps>) => render(
|
||||||
|
<PaymentsPageToolbar data-testid="payments-page-toolbar" {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByTestId('payments-page-toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
expect(toolbarElem).toHaveTextContent('Payments Page Toolbar');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import type { FC } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
const PaymentsPage: FC = () => (
|
export type PaymentsPageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
<div>
|
const PaymentsPage: FC<PaymentsPageProps> = (props) => (
|
||||||
|
<div {...props}>
|
||||||
Payments Page
|
Payments Page
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
const PaymentsPageToolbar: FC = () => (
|
export type PaymentsPageToolbarProps = ToolbarProps;
|
||||||
<Toolbar>
|
const PaymentsPageToolbar: FC<PaymentsPageToolbarProps> = (props) => (
|
||||||
|
<Toolbar {...props}>
|
||||||
<Typography noWrap component="div" variant="h6">
|
<Typography noWrap component="div" variant="h6">
|
||||||
Payments Page Toolbar
|
Payments Page Toolbar
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
31
src/pages/SchedulePage/ui/SchedulePage.spec.tsx
Normal file
31
src/pages/SchedulePage/ui/SchedulePage.spec.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { SchedulePage, SchedulePageToolbar } from 'pages/SchedulePage';
|
||||||
|
|
||||||
|
describe('Test SchedulePage', () => {
|
||||||
|
const setup = () => render(
|
||||||
|
<SchedulePage data-testid="schedule-page" />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const pageElem = screen.getByTestId('schedule-page');
|
||||||
|
expect(pageElem).toBeVisible();
|
||||||
|
expect(pageElem).toHaveTextContent('Schedule Page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test SchedulePageToolabr', () => {
|
||||||
|
const setup = () => render(
|
||||||
|
<SchedulePageToolbar data-testid="schedule-page-toolbar" />,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByTestId('schedule-page-toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
expect(toolbarElem).toHaveTextContent('Schedule Page Toolbar');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import type { FC } from 'react';
|
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
const SchedulePage: FC = () => (
|
export type SchedulePageProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
<div>
|
const SchedulePage: FC<SchedulePageProps> = (props) => (
|
||||||
|
<div {...props}>
|
||||||
Schedule Page
|
Schedule Page
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
|
import type { ToolbarProps } from '@mui/material/Toolbar/Toolbar';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
const SchedulePageToolbar: FC = () => (
|
type SchedulePageToolbarProps = ToolbarProps;
|
||||||
<Toolbar>
|
const SchedulePageToolbar: FC<SchedulePageToolbarProps> = (props) => (
|
||||||
|
<Toolbar {...props}>
|
||||||
<Typography noWrap component="div" variant="h6">
|
<Typography noWrap component="div" variant="h6">
|
||||||
Schedule Page Toolbar
|
Schedule Page Toolbar
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
116
src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx
Normal file
116
src/widgets/AsideMenuLayout/ui/AsideMenuLayout.spec.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { renderWithProvider } from '__spec__/custon-renders';
|
||||||
|
|
||||||
|
import PieChartIcon from '@mui/icons-material/PieChart';
|
||||||
|
import { fireEvent, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import AsideMenuLayout from './AsideMenuLayout.ui';
|
||||||
|
|
||||||
|
const toggleSwitcher = (testId = 'drawer-switcher') => {
|
||||||
|
const switcherElem = screen.getByTestId(testId);
|
||||||
|
fireEvent.click(switcherElem);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Test AsideMenuLayout', () => {
|
||||||
|
const setup = () => {
|
||||||
|
const Content = () => (
|
||||||
|
<div>
|
||||||
|
Test Content
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Toolbar = () => (
|
||||||
|
<div>
|
||||||
|
Test Toolbar
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
icon: <PieChartIcon />,
|
||||||
|
title: 'Test Route',
|
||||||
|
path: '/test-route',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <PieChartIcon />,
|
||||||
|
title: 'Another Test Route',
|
||||||
|
path: '/another-test-route',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return renderWithProvider(
|
||||||
|
<AsideMenuLayout
|
||||||
|
Content={<Content />}
|
||||||
|
data-testid="aside-menu-layout"
|
||||||
|
DrawerSwitcherProps={{
|
||||||
|
// @ts-ignore
|
||||||
|
'data-testid': 'drawer-switcher',
|
||||||
|
}}
|
||||||
|
pages={pages}
|
||||||
|
Toolbar={<Toolbar />}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
test('should render correctly', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const layoutElem = screen.getByTestId('aside-menu-layout');
|
||||||
|
expect(layoutElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render toolbar', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByText('Test Toolbar');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render content', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const toolbarElem = screen.getByText('Test Content');
|
||||||
|
expect(toolbarElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render navigation routes', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const linkElem = screen.getByText('Test Route');
|
||||||
|
expect(linkElem).toBeVisible();
|
||||||
|
|
||||||
|
const anotherLinkElem = screen.getByText('Another Test Route');
|
||||||
|
expect(anotherLinkElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test switch open/close drawer', () => {
|
||||||
|
test('should have correct close icon', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const closeIconElem = screen.getByTestId('ChevronLeftIcon');
|
||||||
|
expect(closeIconElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should have correct open icon', () => {
|
||||||
|
setup();
|
||||||
|
toggleSwitcher();
|
||||||
|
|
||||||
|
const openIconElem = screen.getByTestId('MenuIcon');
|
||||||
|
expect(openIconElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show link text', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const linkTextElem = screen.getByText('Test Route');
|
||||||
|
expect(linkTextElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should hide link text', () => {
|
||||||
|
setup();
|
||||||
|
toggleSwitcher();
|
||||||
|
|
||||||
|
const linkTextElem = screen.queryByText('Test Route');
|
||||||
|
expect(linkTextElem).not.toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -10,23 +10,32 @@ import AppBar from './components/AppBar';
|
|||||||
import Drawer from './components/Drawer';
|
import Drawer from './components/Drawer';
|
||||||
import DrawerHeader from './components/DrawerMenu';
|
import DrawerHeader from './components/DrawerMenu';
|
||||||
import DrawerSwitcher from './components/DrawerSwitcher';
|
import DrawerSwitcher from './components/DrawerSwitcher';
|
||||||
import MenuItem from './components/MenuItem';
|
import MenuItem from './components/MenuItem/MenuItem.ui';
|
||||||
|
|
||||||
import type { MenuItemProps } from './components/MenuItem';
|
import type { MenuItemProps } from './components/MenuItem/MenuItem.ui';
|
||||||
import type { FC, ReactNode } from 'react';
|
import type { BoxProps } from '@mui/material/Box/Box';
|
||||||
|
import type {
|
||||||
|
FC,
|
||||||
|
ReactNode,
|
||||||
|
DetailedHTMLProps,
|
||||||
|
HTMLAttributes,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
const drawerWidth = 250;
|
const drawerWidth = 250;
|
||||||
|
|
||||||
type AsideMenuLayoutProps = {
|
type AsideMenuLayoutProps = BoxProps & {
|
||||||
pages: MenuItemProps['page'][];
|
pages: MenuItemProps['page'][];
|
||||||
Content: ReactNode;
|
Content: ReactNode;
|
||||||
Toolbar?: ReactNode;
|
Toolbar?: ReactNode;
|
||||||
|
DrawerSwitcherProps?: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||||
};
|
};
|
||||||
const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
pages,
|
pages,
|
||||||
Content,
|
Content,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
|
DrawerSwitcherProps,
|
||||||
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
@ -39,7 +48,7 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }} {...restProps}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
|
||||||
<Drawer
|
<Drawer
|
||||||
@ -51,6 +60,7 @@ const AsideMenuLayout: FC<AsideMenuLayoutProps> = (props) => {
|
|||||||
<DrawerSwitcher
|
<DrawerSwitcher
|
||||||
open={isOpen}
|
open={isOpen}
|
||||||
onClick={isOpen ? handleDrawerClose : handleDrawerOpen}
|
onClick={isOpen ? handleDrawerClose : handleDrawerOpen}
|
||||||
|
{...DrawerSwitcherProps}
|
||||||
>
|
>
|
||||||
{ isOpen ? <ChevronLeftIcon /> : <MenuIcon /> }
|
{ isOpen ? <ChevronLeftIcon /> : <MenuIcon /> }
|
||||||
</DrawerSwitcher>
|
</DrawerSwitcher>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ type AppBarProps = MuiAppBarProps & {
|
|||||||
drawerWidth: number;
|
drawerWidth: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppBar = styled(MuiAppBar, { shouldForwardProp: (prop) => prop !== 'open' })<AppBarProps>(
|
const AppBar = styled(MuiAppBar, { shouldForwardProp: (prop) => !['open', 'drawerWidth'].includes(prop as string) })<AppBarProps>(
|
||||||
({ theme, open, drawerWidth }) => ({
|
({ theme, open, drawerWidth }) => ({
|
||||||
transition: theme.transitions.create(['width', 'margin'], {
|
transition: theme.transitions.create(['width', 'margin'], {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const closedMixin = (theme: Theme): CSSObject => ({
|
|||||||
width: `calc(${theme.spacing(8)} + 1px)`,
|
width: `calc(${theme.spacing(8)} + 1px)`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })<DrawerProps>(
|
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => !['open', 'drawerWidth'].includes(prop as string) })<DrawerProps>(
|
||||||
({ theme, open, drawerWidth }) => ({
|
({ theme, open, drawerWidth }) => ({
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
|||||||
@ -0,0 +1,70 @@
|
|||||||
|
import { renderWithProvider } from '__spec__/custon-renders';
|
||||||
|
|
||||||
|
import PieChartIcon from '@mui/icons-material/PieChart';
|
||||||
|
import { screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import MenuItem from './MenuItem.ui';
|
||||||
|
|
||||||
|
import type { MenuItemProps } from './MenuItem.ui';
|
||||||
|
|
||||||
|
describe('MenuItem', () => {
|
||||||
|
const setup = (props?: Partial<MenuItemProps>) => renderWithProvider(
|
||||||
|
<MenuItem
|
||||||
|
data-testid="menu-item"
|
||||||
|
NavLinkProps={{
|
||||||
|
// @ts-ignore
|
||||||
|
'data-testid': 'menu-item-link',
|
||||||
|
}}
|
||||||
|
page={{
|
||||||
|
icon: <PieChartIcon />,
|
||||||
|
title: 'Test Route',
|
||||||
|
path: '/test-route',
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('should render', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const itemElem = screen.getByTestId('menu-item');
|
||||||
|
expect(itemElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render correct text', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const textElem = screen.getByText('Test Route');
|
||||||
|
expect(textElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render correct icon', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const iconElem = screen.getByTestId('PieChartIcon');
|
||||||
|
expect(iconElem).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should have correct href', () => {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
const itemElem = screen.getByTestId('menu-item-link');
|
||||||
|
expect(itemElem).toHaveAttribute('href', '/test-route');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test closed MenuItem', () => {
|
||||||
|
test('should not render text if closed', () => {
|
||||||
|
setup({ isOpen: false });
|
||||||
|
|
||||||
|
const textElem = screen.getByText('Test Route');
|
||||||
|
expect(textElem).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render correct icon if closed', () => {
|
||||||
|
setup({ isOpen: false });
|
||||||
|
|
||||||
|
const iconElem = screen.getByTestId('PieChartIcon');
|
||||||
|
expect(iconElem).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -6,7 +6,9 @@ import { styled, useTheme } from '@mui/material/styles';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { NavLink as RRDNavLink } from 'react-router-dom';
|
import { NavLink as RRDNavLink } from 'react-router-dom';
|
||||||
|
|
||||||
|
import type { ListItemProps } from '@mui/material/ListItem/ListItem';
|
||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
|
import type { NavLinkProps } from 'react-router-dom';
|
||||||
|
|
||||||
const NavLink = styled(RRDNavLink)(({ theme }) => ({
|
const NavLink = styled(RRDNavLink)(({ theme }) => ({
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
@ -14,25 +16,28 @@ const NavLink = styled(RRDNavLink)(({ theme }) => ({
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export type MenuItemProps = {
|
export type MenuItemProps = ListItemProps & {
|
||||||
page: {
|
page: {
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
title: string;
|
title: string;
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
isOpen: boolean;
|
isOpen?: boolean;
|
||||||
|
NavLinkProps?: NavLinkProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MenuItem: FC<MenuItemProps> = (props) => {
|
const MenuItem: FC<MenuItemProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
page,
|
page,
|
||||||
isOpen,
|
isOpen = true,
|
||||||
|
NavLinkProps,
|
||||||
|
...restProps
|
||||||
} = props;
|
} = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding {...restProps}>
|
||||||
<NavLink to={page.path}>
|
<NavLink to={page.path} {...NavLinkProps}>
|
||||||
{({ isActive }) => (
|
{({ isActive }) => (
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
sx={{
|
sx={{
|
||||||
Loading…
x
Reference in New Issue
Block a user