Skip to content

Commit

Permalink
feat: add AppRouter tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TomatoVan committed Mar 24, 2024
1 parent b720f38 commit 3d2de35
Show file tree
Hide file tree
Showing 25 changed files with 140 additions and 67 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@storybook/testing-library": "^0.0.9",
"@svgr/webpack": "^6.2.1",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.3.0",
"@types/jest": "^27.4.1",
"@types/node": "^17.0.21",
Expand Down
36 changes: 18 additions & 18 deletions src/app/providers/router/config/routeConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,63 +10,63 @@ import { ForbiddenPage } from '@/pages/ForbiddenPage';
import { NotFoundPage } from '@/pages/NotFoundPage';
import {
AppRoutes,
getRouterAbout,
getRouterAdminPanel,
getRouterArticleCreate,
getRouterArticleDetails,
getRouterArticleEdit,
getRouterArticles, getRouterForbidden,
getRouterMain, getRouterNotFound,
getRouterProfile,
getRouteAbout,
getRouteAdminPanel,
getRouteArticleCreate,
getRouteArticleDetails,
getRouteArticleEdit,
getRouteArticles, getRouteForbidden,
getRouteMain, getRouteNotFound,
getRouteProfile,
} from '@/shared/const/router';
import { AppRoutesProps } from '@/shared/types/router';

export const routeConfig: Record<AppRoutes, AppRoutesProps> = {
[AppRoutes.MAIN]: {
path: getRouterMain(),
path: getRouteMain(),
element: <MainPage />,
},
[AppRoutes.ABOUT]: {
path: getRouterAbout(),
path: getRouteAbout(),
element: <AboutPage />,
},
[AppRoutes.PROFILE]: {
path: getRouterProfile(':id'),
path: getRouteProfile(':id'),
element: <ProfilePage />,
authOnly: true,
},
[AppRoutes.ARTICLES]: {
path: getRouterArticles(),
path: getRouteArticles(),
element: <ArticlesPage />,
authOnly: true,
},
[AppRoutes.ARTICLE_DETAILS]: {
path: getRouterArticleDetails(':id'),
path: getRouteArticleDetails(':id'),
element: <ArticlesDetailsPage />,
authOnly: true,
},
[AppRoutes.ARTICLE_CREATE]: {
path: getRouterArticleCreate(),
path: getRouteArticleCreate(),
element: <ArticleEditPage />,
authOnly: true,
},
[AppRoutes.ARTICLE_EDIT]: {
path: getRouterArticleEdit(':id'),
path: getRouteArticleEdit(':id'),
element: <ArticleEditPage />,
authOnly: true,
},
[AppRoutes.ADMIN_PANEL]: {
path: getRouterAdminPanel(),
path: getRouteAdminPanel(),
element: <AdminPanelPage />,
authOnly: true,
roles: [UserRole.ADMIN, UserRole.MANAGER],
},
[AppRoutes.FORBIDDEN]: {
path: getRouterForbidden(),
path: getRouteForbidden(),
element: <ForbiddenPage />,
},
[AppRoutes.NOT_FOUND]: {
path: getRouterNotFound(),
path: getRouteNotFound(),
element: <NotFoundPage />,
},
};
66 changes: 66 additions & 0 deletions src/app/providers/router/ui/AppRouter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { screen } from '@testing-library/react';
import AppRouter from './AppRouter';
import { componentRender } from '@/shared/lib/tests/componentRender/componentRender';
import { getRouteAbout, getRouteAdminPanel, getRouteProfile } from '@/shared/const/router';
import { UserRole } from '@/entities/User';

describe('AppRouter', () => {
test('Test render', async () => {
componentRender(<AppRouter />, {
route: getRouteAbout(),
});
const page = await screen.findByTestId('AboutPage');
expect(page).toBeInTheDocument();
});
test('no page foundN', async () => {
componentRender(<AppRouter />, {
route: '/dadsdsad',
});
const page = await screen.findByTestId('NotFoundPage');
expect(page).toBeInTheDocument();
});
test('redirect no auth to main page', async () => {
componentRender(<AppRouter />, {
route: getRouteProfile('1'),
});

const page = await screen.findByTestId('MainPage');
expect(page).toBeInTheDocument();
});

test('access to profile', async () => {
componentRender(<AppRouter />, {
route: getRouteProfile('1'),
initialState: {
user: { _inited: true, authData: {} },
},
});

const page = await screen.findByTestId('ProfilePage');
expect(page).toBeInTheDocument();
});

test('access denied (no roles)', async () => {
componentRender(<AppRouter />, {
route: getRouteAdminPanel(),
initialState: {
user: { _inited: true, authData: {} },
},
});

const page = await screen.findByTestId('ForbiddenPage');
expect(page).toBeInTheDocument();
});

test('access granted (have roles)', async () => {
componentRender(<AppRouter />, {
route: getRouteAdminPanel(),
initialState: {
user: { _inited: true, authData: { roles: [UserRole.ADMIN] } },
},
});

const page = await screen.findByTestId('AdminPanelPage');
expect(page).toBeInTheDocument();
});
});
6 changes: 3 additions & 3 deletions src/app/providers/router/ui/RequireAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getUserRoles,
UserRole,
} from '../../../../entities/User';
import { getRouterForbidden, getRouterMain } from '@/shared/const/router';
import { getRouteForbidden, getRouteMain } from '@/shared/const/router';

interface RequireAuthProps {
children: JSX.Element;
Expand All @@ -27,11 +27,11 @@ export function RequireAuth({ children, roles }: RequireAuthProps) {
}, [roles, userRoles]);

if (!auth) {
return <Navigate to={getRouterMain()} state={{ from: location }} replace />;
return <Navigate to={getRouteMain()} state={{ from: location }} replace />;
}

if (!hasRequiredRoles) {
return <Navigate to={getRouterForbidden()} state={{ from: location }} replace />;
return <Navigate to={getRouteForbidden()} state={{ from: location }} replace />;
}

return children;
Expand Down
6 changes: 3 additions & 3 deletions src/entities/Article/ui/ArticleListItem/ArticleListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ArticleBlockType, ArticleView } from '../../model/consts/consts';
import { ArticleTextBlockComponent } from '../ArticleTextBlockComponent/ArticleTextBlockComponent';
import { Article, ArticleTextBlock } from '../../model/types/article';
import cls from './ArticleListItem.module.scss';
import { getRouterArticleDetails } from '@/shared/const/router';
import { getRouteArticleDetails } from '@/shared/const/router';
import { AppImage } from '@/shared/ui/AppImage';
import { Skeleton } from '@/shared/ui/Skeleton';

Expand Down Expand Up @@ -66,7 +66,7 @@ export const ArticleListItem = memo((props: ArticleListItemProps) => {
<div className={cls.footer}>
<AppLink
target={target}
to={getRouterArticleDetails(article.id)}
to={getRouteArticleDetails(article.id)}
>
<Button theme={ButtonTheme.OUTLINE}>
{t('Read more...')}
Expand All @@ -82,7 +82,7 @@ export const ArticleListItem = memo((props: ArticleListItemProps) => {
return (
<AppLink
target={target}
to={getRouterArticleDetails(article.id)}
to={getRouteArticleDetails(article.id)}
className={classNames(cls.ArticleListItem, {}, [className, cls[view]])}
>
<Card>
Expand Down
4 changes: 2 additions & 2 deletions src/entities/Comment/ui/CommentCard/CommentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Comment } from '../../model/types/comment';
import { Avatar } from '../../../../shared/ui/Avatar/Avatar';
import { Text } from '../../../../shared/ui/Text/Text';
import { Skeleton } from '../../../../shared/ui/Skeleton/Skeleton';
import { getRouterProfile } from '@/shared/const/router';
import { getRouteProfile } from '@/shared/const/router';

interface CommentCardProps {
className?: string;
Expand Down Expand Up @@ -38,7 +38,7 @@ export const CommentCard = memo(({ className, comment, isLoading }: CommentCardP

return (
<VStack max gap="8" className={classNames(cls.CommentCard, {}, [className])}>
<AppLink to={getRouterProfile(comment.user.id)} className={cls.header}>
<AppLink to={getRouteProfile(comment.user.id)} className={cls.header}>
{comment.user.avatar && <Avatar src={comment.user.avatar} alt={comment.user.username} size={30} />}
<Text className={cls.username} title={comment.user.username} />
</AppLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
import { memo, useMemo } from 'react';
import { classNames } from '@/shared/lib/classNames/classNames';
import { Select, SelectOption } from '@/shared/ui/Select';
import { SortOrder } from '@/shared/types';
import { SortOrder } from '@/shared/types/sort';
import cls from './ArticleSortSelector.module.scss';
import { ArticleSortField } from '@/entities/Article';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
isUserManager,
userActions,
} from '../../../../entities/User';
import { getRouterAdminPanel, getRouterProfile } from '@/shared/const/router';
import { getRouteAdminPanel, getRouteProfile } from '@/shared/const/router';

export const AvatarDropDown = memo(() => {
const { t } = useTranslation();
Expand Down Expand Up @@ -39,13 +39,13 @@ export const AvatarDropDown = memo(() => {
? [
{
content: t('Admin panel'),
href: getRouterAdminPanel(),
href: getRouteAdminPanel(),
},
]
: []),
{
content: t('Profile'),
href: getRouterProfile(authData.id),
href: getRouteProfile(authData.id),
},
{
content: t('Exit'),
Expand Down
5 changes: 3 additions & 2 deletions src/pages/AboutPage/ui/AboutPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Page } from '@/widgets/Page';

const AboutPage = memo((props: any) => {
const { t } = useTranslation('about');

return (
<div>
<Page data-testid="AboutPage">
{t('About website')}
</div>
</Page>
);
});

Expand Down
2 changes: 1 addition & 1 deletion src/pages/AdminPanelPage/ui/AdminPanelPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const AdminPanelPage = memo((props: any) => {
const { t } = useTranslation('');

return (
<Page>
<Page data-testid="AdminPanelPage">
{t('Admin panel')}
</Page>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { classNames } from '@/shared/lib/classNames/classNames';
import { HStack } from '@/shared/ui/Stack';
import { getCanEditArticle } from '../../model/selectors/article';
import { getArticlesDetailsData } from '../../../../entities/Article';
import { getRouterArticleEdit, getRouterArticles } from '@/shared/const/router';
import { getRouteArticleEdit, getRouteArticles } from '@/shared/const/router';

interface ArticlesDetailsPageHeaderProps {
className?: string;
Expand All @@ -21,11 +21,11 @@ export const ArticlesDetailsPageHeader = memo((props: ArticlesDetailsPageHeaderP
const article = useSelector(getArticlesDetailsData);

const onBackToList = useCallback(() => {
navigate(getRouterArticles());
navigate(getRouteArticles());
}, [navigate]);

const onEditArticle = useCallback(() => {
navigate(getRouterArticleEdit(article?.id || ''));
navigate(getRouteArticleEdit(article?.id || ''));
}, [article?.id, navigate]);

const canEdit = useSelector(getCanEditArticle);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { ThunkConfig } from '@/app/providers/StoreProvider';
import { SortOrder } from '@/shared/types';
import { SortOrder } from '@/shared/types/sort';
import { getArticlesPageInited } from '../../../model/selectors/articlesPageSelectors';
import { articlesPageActions } from '../../../model/slices/articlesPageSlice';
import { fetchArticlesList } from '../../../model/services/fetchArticlesList/fetchArticlesList';
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ArticlesPage/model/slices/articlesPageSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from '@reduxjs/toolkit';
import { StateSchema } from '@/app/providers/StoreProvider';
import { ARTICLE_VIEW_LOCALSTORAGE_KEY } from '@/shared/const/localstorage';
import { SortOrder } from '@/shared/types';
import { SortOrder } from '@/shared/types/sort';
import { ArticlesPageSchema } from '../types/articlesPageSchema';
import {
Article, ArticleSortField, ArticleType, ArticleView,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ArticlesPage/model/types/articlesPageSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EntityState } from '@reduxjs/toolkit';
import {
Article, ArticleView, ArticleSortField, ArticleType,
} from '@/entities/Article';
import { SortOrder } from '@/shared/types';
import { SortOrder } from '@/shared/types/sort';

export interface ArticlesPageSchema extends EntityState<Article> {
isLoading?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ArticleViewSelector } from '@/features/ArticleViewSelector';
import { useAppDispatch } from '@/shared/lib/hook/useAppDispatch/useAppDispatch';
import { Input } from '@/shared/ui/Input';
import { Card } from '@/shared/ui/Card';
import { SortOrder } from '@/shared/types';
import { SortOrder } from '@/shared/types/sort';
import { useDebounce } from '@/shared/lib/hook/useDebounce/useDebounce';
import { ArticleTypeTabs } from '@/features/ArticleTypeTabs';
import { fetchArticlesList } from '../../model/services/fetchArticlesList/fetchArticlesList';
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ForbiddenPage/ui/ForbiddenPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const ForbiddenPage = memo((props: any) => {
const { t } = useTranslation('');

return (
<Page>
<Page data-testid="ForbiddenPage">
{t('You don`t have access to this page!')}
</Page>
);
Expand Down
5 changes: 3 additions & 2 deletions src/pages/MainPage/ui/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Page } from '@/widgets/Page';

const MainPage = memo((props: any) => {
const { t } = useTranslation();

return (
<div>
<Page data-testid="MainPage">
{t('Главная страница')}
</div>
</Page>
);
});

Expand Down
2 changes: 1 addition & 1 deletion src/pages/NotFoundPage/ui/NotFoundPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface NotFoundPageProps {
export const NotFoundPage = memo(({ className }: NotFoundPageProps) => {
const { t } = useTranslation();
return (
<div className={classNames(cls.NotFoundPage, {}, [className])}>
<div data-testid="NotFoundPage" className={classNames(cls.NotFoundPage, {}, [className])}>

Page not found
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ProfilePage/ui/ProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ProfilePage = memo(({ className }: ProfilePageProps) => {
const { id } = useParams<{ id: string }>();

return (
<Page className={classNames('', {}, [className])}>
<Page data-testid="ProfilePage" className={classNames('', {}, [className])}>
<VStack gap="16" max>
<EditableProfileCard id={id} />
</VStack>
Expand Down
Loading

0 comments on commit 3d2de35

Please sign in to comment.