From 5c870008a8c22c367526f80684ca7fb6b31e3a5c Mon Sep 17 00:00:00 2001 From: Yasiu1376 Date: Tue, 10 Oct 2023 16:15:10 +0330 Subject: [PATCH] CFE-20 implement middlewarecomponent and middleware test --- mocks/handler.js | 5 ++- package.json | 2 +- public/locales/fa/app.json | 2 +- .../Middleware/RolePermissionComponent.jsx | 33 ++++++++++++++++ .../Middleware/WithAuthComponent.jsx | 36 +++++++++++++++++ .../Middleware/WithoutAuthComponent.jsx | 25 ++++++++++++ .../__test__/RolePermissionComponent.test.js | 23 +++++++++++ .../__test__/WithAuthComponent.test.js | 39 +++++++++++++++++++ .../__test__/WithoutAuthComponent.test.js | 37 ++++++++++++++++++ src/middlewares/RolePermission.jsx | 33 +--------------- src/middlewares/WithAuth.jsx | 37 ++---------------- src/middlewares/WithoutAuth.jsx | 36 ++++------------- .../__test__/RolePermission.test.js | 34 ++++++++++++++++ 13 files changed, 245 insertions(+), 97 deletions(-) create mode 100644 src/core/components/Middleware/RolePermissionComponent.jsx create mode 100644 src/core/components/Middleware/WithAuthComponent.jsx create mode 100644 src/core/components/Middleware/WithoutAuthComponent.jsx create mode 100644 src/core/components/Middleware/__test__/RolePermissionComponent.test.js create mode 100644 src/core/components/Middleware/__test__/WithAuthComponent.test.js create mode 100644 src/core/components/Middleware/__test__/WithoutAuthComponent.test.js create mode 100644 src/middlewares/__test__/RolePermission.test.js diff --git a/mocks/handler.js b/mocks/handler.js index 65f5398..7e1d193 100644 --- a/mocks/handler.js +++ b/mocks/handler.js @@ -5,7 +5,10 @@ export const handler = [ rest.get(GET_USER_ROUTE, (req, res, ctx) => { return res(ctx.json({ data:{ - id: 10 + id: 10, + permissions:[ + "manage_users" + ], } })) }), diff --git a/package.json b/package.json index 5d6417a..f82c9f2 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "msw": "^1.3.1", - "next-router-mock": "^0.9.9", + "next-router-mock": "^0.9.10", "run-script-os": "^1.1.6" } } diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 3613a1c..4c242dd 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -40,7 +40,7 @@ "typography_your_login_is_valid_and_you_do_not_need_to_login_again": "شما دسترسی لازم به این صفحه را دارید نیاز به ورود مجدد نیست.", "typography_your_access_to_this_page_has_expired_Please_login_again": "دسترسی شما منقضی شده است لطفا دوباره ورود نمایید.", "typography_redirect_to": "درحال رفتن به صفحه", - "typography_routing_previuos_page": "صفحه قبل...", + "typography_routing_previuos_page": " قبل...", "typography_routing_dashbaord_page": "داشبورد..." }, "Permission": { diff --git a/src/core/components/Middleware/RolePermissionComponent.jsx b/src/core/components/Middleware/RolePermissionComponent.jsx new file mode 100644 index 0000000..869f78a --- /dev/null +++ b/src/core/components/Middleware/RolePermissionComponent.jsx @@ -0,0 +1,33 @@ +import { Button, Typography } from "@mui/material"; +import { useTranslations } from "next-intl"; +import { NextLinkComposed } from "@/core/components/LinkRouting"; +import Message from "@/core/components/Messages"; + +const RolePermissionComponent = () => { + const t = useTranslations(); + + return ( + + {t("Permission.typography_you_dont_have_access")} + + } + actions={ + <> + + + } + /> + ); +}; + +export default RolePermissionComponent; diff --git a/src/core/components/Middleware/WithAuthComponent.jsx b/src/core/components/Middleware/WithAuthComponent.jsx new file mode 100644 index 0000000..9a6ff5d --- /dev/null +++ b/src/core/components/Middleware/WithAuthComponent.jsx @@ -0,0 +1,36 @@ +import { Button, Typography } from "@mui/material"; +import { useRouter } from "next/router"; +import Message from "@/core/components/Messages"; +import { NextLinkComposed } from "@/core/components/LinkRouting"; +import {useTranslations} from "next-intl"; + +const WithAuthComponent = () => { + const router = useRouter(); + const t = useTranslations(); + + return ( + + {t("Authorization.typography_your_access_to_this_page_has_expired_Please_login_again")} + + } + actions={ + <> + + + } + /> + ); +}; + +export default WithAuthComponent; diff --git a/src/core/components/Middleware/WithoutAuthComponent.jsx b/src/core/components/Middleware/WithoutAuthComponent.jsx new file mode 100644 index 0000000..7dbb38d --- /dev/null +++ b/src/core/components/Middleware/WithoutAuthComponent.jsx @@ -0,0 +1,25 @@ +import {Button, Stack, Typography} from "@mui/material"; +import Message from "@/core/components/Messages"; +import {useTranslations} from "next-intl"; +const WithoutAuthComponent = ({ backUrlDecodedPath }) => { + const t = useTranslations(); + + return ( + + + {t("Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again")} + + + {t("Authorization.typography_redirect_to")}{" "} + {backUrlDecodedPath + ? t("Authorization.typography_routing_previuos_page") + : t("Authorization.typography_routing_dashbaord_page")} + + + } + /> + ); +}; +export default WithoutAuthComponent; diff --git a/src/core/components/Middleware/__test__/RolePermissionComponent.test.js b/src/core/components/Middleware/__test__/RolePermissionComponent.test.js new file mode 100644 index 0000000..44a583d --- /dev/null +++ b/src/core/components/Middleware/__test__/RolePermissionComponent.test.js @@ -0,0 +1,23 @@ +import { render, screen } from '@testing-library/react'; +import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; +import RolePermissionComponent from "@/core/components/Middleware/RolePermissionComponent"; + +describe('RolePermissionComponent From RolePermissionComponent page', () => { + describe('Rendering', () => { + it('should render the error message when user dont have permission', () => { + render(); + + expect(screen.queryByText('شما دسترسی لازم برای مشاهده این صفحه را ندارید!')).toBeInTheDocument(); + + }); + + it('should render the back dashboard button when user dont have permission', () => { + render(); + + const backButton = screen.queryByText('بازگشت به صفحه اصلی'); + + expect(backButton).toBeInTheDocument(); + + }); + }); +}); diff --git a/src/core/components/Middleware/__test__/WithAuthComponent.test.js b/src/core/components/Middleware/__test__/WithAuthComponent.test.js new file mode 100644 index 0000000..a43e20f --- /dev/null +++ b/src/core/components/Middleware/__test__/WithAuthComponent.test.js @@ -0,0 +1,39 @@ +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; +import WithAuthComponent from "@/core/components/Middleware/WithAuthComponent"; +import mockRouter from 'next-router-mock'; + +describe('WithAuthComponent From WithAuthMiddleware', () => { + describe('Rendering', () => { + it('should see expired text in render component', () => { + render(); + + const authText = screen.queryByText('دسترسی شما منقضی شده است لطفا دوباره ورود نمایید.'); + + expect(authText).toBeInTheDocument(); + }); + + it('should see login button in render component', () => { + render(); + + const loginButton = screen.queryByText('ورود'); + + expect(loginButton).toBeInTheDocument(); + }); + }); + describe('behavior', () => { + it('should see if router updated in login button', () => { + + mockRouter.query.back_url = 'back_url' + render(); + + const loginButton = screen.queryByText('ورود'); + + fireEvent.click(loginButton); + + expect(mockRouter).toMatchObject({ + query: { back_url: "back_url" }, + }); + }); + }); +}); diff --git a/src/core/components/Middleware/__test__/WithoutAuthComponent.test.js b/src/core/components/Middleware/__test__/WithoutAuthComponent.test.js new file mode 100644 index 0000000..520d7bd --- /dev/null +++ b/src/core/components/Middleware/__test__/WithoutAuthComponent.test.js @@ -0,0 +1,37 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import WithoutAuthComponent from "@/core/components/Middleware/WithoutAuthComponent"; +import MockAppWithProviders from "../../../../../mocks/AppWithProvider"; +import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; + +describe('WithoutAuthComponent From WithoutAuthMiddleware', () => { + describe('Rendering', () => { + it('should render the message with correct text when backUrlDecodedPath is not provided', async () => { + + localStorage.setItem("_token", 'token'); + + render(); + + await waitFor(()=>{ + expect(screen.queryByText('شما دسترسی لازم به این صفحه را دارید نیاز به ورود مجدد نیست.')).toBeInTheDocument(); + + expect(screen.queryByText('درحال رفتن به صفحه داشبورد...')).toBeInTheDocument(); + }) + + }); + + it('should render the message with a different text when backUrlDecodedPath is provided', async() => { + render(); + + localStorage.setItem("_token", 'token'); + + render(); + + await waitFor(()=>{ + + expect(screen.queryByText('درحال رفتن به صفحه قبل...')).toBeInTheDocument(); + }) + + + }); + }); +}); diff --git a/src/middlewares/RolePermission.jsx b/src/middlewares/RolePermission.jsx index 67fc3f1..4b1cc8a 100644 --- a/src/middlewares/RolePermission.jsx +++ b/src/middlewares/RolePermission.jsx @@ -1,43 +1,14 @@ -import {NextLinkComposed} from "@/core/components/LinkRouting"; -import Message from "@/core/components/Messages"; import useUser from "@/lib/app/hooks/useUser"; -import {Button, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; +import RolePermissionComponent from "@/core/components/Middleware/RolePermissionComponent"; const RolePermissionMiddleware = ({children, requiredPermissions}) => { const {user} = useUser(); - const t = useTranslations(); const hasPermission = requiredPermissions.some((permission) => user?.permissions?.includes(permission) ); - if (!hasPermission) { - return ( - - {t("Permission.typography_you_dont_have_access")} - - } - actions={ - <> - - - } - /> - ); - } - - return <>{children}; + return !hasPermission ? : <>{children}; }; export default RolePermissionMiddleware; diff --git a/src/middlewares/WithAuth.jsx b/src/middlewares/WithAuth.jsx index b20d8b3..d3b0493 100644 --- a/src/middlewares/WithAuth.jsx +++ b/src/middlewares/WithAuth.jsx @@ -1,42 +1,11 @@ -import {NextLinkComposed} from "@/core/components/LinkRouting"; -import Message from "@/core/components/Messages"; import useUser from "@/lib/app/hooks/useUser"; -import {Button, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; -import {useRouter} from "next/router"; +import WithAuthComponent from "@/core/components/Middleware/WithAuthComponent"; + const WithAuthMiddleware = ({children}) => { const {isAuth} = useUser(); - const t = useTranslations(); - const router = useRouter(); - if (!isAuth) - return ( - - {t( - "Authorization.typography_your_access_to_this_page_has_expired_Please_login_again" - )} - - } - actions={ - <> - - - } - /> - ); - return <>{children}; + return isAuth ? <>{children} : ; }; export default WithAuthMiddleware; diff --git a/src/middlewares/WithoutAuth.jsx b/src/middlewares/WithoutAuth.jsx index 594ffc5..7fbcba6 100644 --- a/src/middlewares/WithoutAuth.jsx +++ b/src/middlewares/WithoutAuth.jsx @@ -1,19 +1,13 @@ -import Message from "@/core/components/Messages"; import useUser from "@/lib/app/hooks/useUser"; -import {Stack, Typography} from "@mui/material"; -import {useTranslations} from "next-intl"; -import {useSearchParams} from "next/navigation"; import {useRouter} from "next/router"; import {useEffect} from "react"; +import WithoutAuthComponent from "@/core/components/Middleware/WithoutAuthComponent"; const WithoutAuthMiddleware = ({children}) => { const {isAuth} = useUser(); - const t = useTranslations(); const router = useRouter(); - // gettin url query - const searchParams = useSearchParams(); - const backUrlDecodedPath = searchParams.get("back_url"); + const backUrlDecodedPath = router.query?.back_url; useEffect(() => { if (!isAuth) return; @@ -30,27 +24,11 @@ const WithoutAuthMiddleware = ({children}) => { }; }, [isAuth]); - if (isAuth) - return ( - - - {t( - "Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again" - )} - - - {t("Authorization.typography_redirect_to")}{" "} - {backUrlDecodedPath - ? t("Authorization.typography_routing_previuos_page") - : t("Authorization.typography_routing_dashbaord_page")} - - - } - /> - ); - return <>{children}; + return isAuth ? ( + + ) : ( + <>{children} + ); }; export default WithoutAuthMiddleware; diff --git a/src/middlewares/__test__/RolePermission.test.js b/src/middlewares/__test__/RolePermission.test.js new file mode 100644 index 0000000..f37796f --- /dev/null +++ b/src/middlewares/__test__/RolePermission.test.js @@ -0,0 +1,34 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import MockAppWithProviders from "../../../mocks/AppWithProvider"; +import RolePermissionMiddleware from "@/middlewares/RolePermission"; + + +describe('RolePermissionMiddleware From RolePermissionMiddleware', () => { + describe('Behavior', () => { + it('show related child if permission exist', async () => { + + const requiredPermissions = ["manage_users"]; + render({'children'}); + + await waitFor(()=>{ + expect(screen.queryByText('children')).toBeInTheDocument(); + + }) + + }); + it('show related error if permission not exist', async () => { + + const requiredPermissions = ["other-permission"]; + + render(); + + await waitFor(()=>{ + + expect(screen.queryByText('شما دسترسی لازم برای مشاهده این صفحه را ندارید!')).toBeInTheDocument(); + + }) + + + }); + }); +});