From ab3cdada3178e6f8518bbfacf05bed3d6141fb89 Mon Sep 17 00:00:00 2001 From: Vinayak Date: Mon, 18 Jul 2022 21:33:34 +0530 Subject: [PATCH 1/9] new feature notifications in UI completed with styling and tests succeded --- ui/src/Components/notification/index.jsx | 82 +++++++++++++++++++ .../notification/notification.module.css | 41 ++++++++++ ui/src/test/Notification.test.js | 51 ++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 ui/src/Components/notification/index.jsx create mode 100644 ui/src/Components/notification/notification.module.css create mode 100644 ui/src/test/Notification.test.js diff --git a/ui/src/Components/notification/index.jsx b/ui/src/Components/notification/index.jsx new file mode 100644 index 0000000..491287c --- /dev/null +++ b/ui/src/Components/notification/index.jsx @@ -0,0 +1,82 @@ +import styles from "./notification.module.css"; +import { useState } from "react"; + +/** + * a pubsub kinda implementation, basically it will save a function in closure with varaible called "fn" + * when i use a function called subcribe and pass it with the function i want to save + * then when i will call publish function with "data" parameter it will call the function present in "fn" + * with the "data" as a arguement + */ +export const NotificationQue = () => { + let fn = () => {}; + const subscribe = (callback) => { + fn = callback; + }; + const publish = (data) => { + return fn(data); + }; + return { subscribe, publish }; +}; + +/** + * now this NotificationHandler can be imported in any component and can be called to create a + * notification + */ +export const { subscribe, publish: NotificationHandler } = NotificationQue(); + +/** + * when we have decided what kind of resources we want to use for icons there also be an icon rendered according to + * type of the notification + * + * + * @param {{message : string, type : string}} data the structure of notification that has to be passed down to the NotificationHandler + */ +export const NotificationElement = ({ data }) => { + return ( +
+

{data.message}

+
+ ); +}; + +const NotificationParent = ({ timeout = 2000 }) => { + const [notifications, setNotifications] = useState([]); + + /* + *whenever someone call the NotificationHandler with data for the alert this function will be called from + * the pubsub closure + * then the data will be pushed to the ending of the notification array with state update + * also at the same time a setTimeout will be runned which will remove the first entry from + * the notification array after "timeout" secs + */ + subscribe((alert) => { + setNotifications((prev) => [...prev, alert]); + + setTimeout(() => { + setNotifications((prev) => { + let [firstAlert, ...data] = prev; + return data; + }); + }, timeout); + }); + + return ( +
+ {notifications.map((alert, index) => ( + + ))} +
+ ); +}; + +export default NotificationParent; diff --git a/ui/src/Components/notification/notification.module.css b/ui/src/Components/notification/notification.module.css new file mode 100644 index 0000000..e44abd6 --- /dev/null +++ b/ui/src/Components/notification/notification.module.css @@ -0,0 +1,41 @@ +.wrapper { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column-reverse; + position: fixed; + top: 1rem; + left: 50%; + right: 50%; + width: max-content; + gap: 6px; + transition: height cubic-bezier(0.165, 0.84, 0.44, 1) 300ms; +} + +.notification { + display: flex; + justify-content: flex-start; + align-items: center; + min-width: 100%; + width: max-content; + background-color: white; + font: 500 1.2rem Helvetica, sans-serif; + text-transform: capitalize; + box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); + border-radius: 4px; + padding: 6px 9px; +} + +.notification-success { + background-color: rgb(95, 214, 95); +} + +.notification-error { + background-color: rgb(253, 81, 81); +} + +.notification-warning { + background-color: rgb(238, 241, 41); +} diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js new file mode 100644 index 0000000..423fdf3 --- /dev/null +++ b/ui/src/test/Notification.test.js @@ -0,0 +1,51 @@ +import { render, screen } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import { act } from "react-dom/test-utils"; + +import NotificationParent, { + NotificationHandler, + NotificationElement, + NotificationQue, +} from "../Components/notification"; + +describe("notification Functionality", () => { + it("notification parent renders on the screen", async () => { + render(); + expect(screen.getByTestId("notification-parent")).toBeInTheDocument(); + }); + + it("check that pubsub que working fine", async () => { + const { publish, subscribe } = NotificationQue(); + subscribe((a) => a * 10); + expect(publish(5)).toEqual(50); + }); + + it("check that notification element gets the correct data", async () => { + let notificationProps = { message: "Hello World", type: "success" }; + render(); + + expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( + notificationProps.message + ); + expect(screen.getByTestId("notification-child")).toHaveClass( + `notification-${notificationProps.type}` + ); + }); + + it("checking the whole function cycle of the notification feature", async () => { + render(); + + let notificationProps = { message: "Hello World", type: "success" }; + + act(() => { + NotificationHandler(notificationProps); + }); + + expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( + notificationProps.message + ); + expect(screen.getByTestId("notification-child")).toHaveClass( + `notification-${notificationProps.type}` + ); + }); +}); From 3bd6e47c552ad2a3c44428536b35591e9f6ac21f Mon Sep 17 00:00:00 2001 From: Vinayak Date: Tue, 19 Jul 2022 13:49:15 +0530 Subject: [PATCH 2/9] styling of the feature now migrated to tailwind CSS from CSS modules --- ui/src/Components/notification/index.jsx | 16 +++++--- .../notification/notification.module.css | 41 ------------------- 2 files changed, 10 insertions(+), 47 deletions(-) delete mode 100644 ui/src/Components/notification/notification.module.css diff --git a/ui/src/Components/notification/index.jsx b/ui/src/Components/notification/index.jsx index 491287c..3333922 100644 --- a/ui/src/Components/notification/index.jsx +++ b/ui/src/Components/notification/index.jsx @@ -1,4 +1,3 @@ -import styles from "./notification.module.css"; import { useState } from "react"; /** @@ -32,12 +31,17 @@ export const { subscribe, publish: NotificationHandler } = NotificationQue(); * @param {{message : string, type : string}} data the structure of notification that has to be passed down to the NotificationHandler */ export const NotificationElement = ({ data }) => { + const typeToColor = { + success: "rgb(95, 214, 95)", + warning: "rgb(238, 241, 41)", + error: "rgb(253, 81, 81)", + }; + return (

{data.message}

@@ -59,7 +63,7 @@ const NotificationParent = ({ timeout = 2000 }) => { setTimeout(() => { setNotifications((prev) => { - let [firstAlert, ...data] = prev; + let [_, ...data] = prev; return data; }); }, timeout); @@ -68,7 +72,7 @@ const NotificationParent = ({ timeout = 2000 }) => { return (
diff --git a/ui/src/Components/notification/notification.module.css b/ui/src/Components/notification/notification.module.css deleted file mode 100644 index e44abd6..0000000 --- a/ui/src/Components/notification/notification.module.css +++ /dev/null @@ -1,41 +0,0 @@ -.wrapper { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column-reverse; - position: fixed; - top: 1rem; - left: 50%; - right: 50%; - width: max-content; - gap: 6px; - transition: height cubic-bezier(0.165, 0.84, 0.44, 1) 300ms; -} - -.notification { - display: flex; - justify-content: flex-start; - align-items: center; - min-width: 100%; - width: max-content; - background-color: white; - font: 500 1.2rem Helvetica, sans-serif; - text-transform: capitalize; - box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); - -webkit-box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1); - border-radius: 4px; - padding: 6px 9px; -} - -.notification-success { - background-color: rgb(95, 214, 95); -} - -.notification-error { - background-color: rgb(253, 81, 81); -} - -.notification-warning { - background-color: rgb(238, 241, 41); -} From 65243a9a11595186de08cba086ee29879f82d261 Mon Sep 17 00:00:00 2001 From: Vinayak Date: Wed, 20 Jul 2022 12:24:40 +0530 Subject: [PATCH 3/9] changes requested by @harshith-venkatesh are done --- ui/src/Components/notification/index.jsx | 13 ++++--------- ui/src/Constant/constant.js | 14 ++++++++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ui/src/Components/notification/index.jsx b/ui/src/Components/notification/index.jsx index 3333922..1094521 100644 --- a/ui/src/Components/notification/index.jsx +++ b/ui/src/Components/notification/index.jsx @@ -1,7 +1,8 @@ import { useState } from "react"; +import { TYPETOCOLOR } from "../../Constant/constant"; /** - * a pubsub kinda implementation, basically it will save a function in closure with varaible called "fn" + * a pubsub kind of implementation, basically it will save a function in closure with varaible called "fn" * when i use a function called subcribe and pass it with the function i want to save * then when i will call publish function with "data" parameter it will call the function present in "fn" * with the "data" as a arguement @@ -31,17 +32,11 @@ export const { subscribe, publish: NotificationHandler } = NotificationQue(); * @param {{message : string, type : string}} data the structure of notification that has to be passed down to the NotificationHandler */ export const NotificationElement = ({ data }) => { - const typeToColor = { - success: "rgb(95, 214, 95)", - warning: "rgb(238, 241, 41)", - error: "rgb(253, 81, 81)", - }; - return (

{data.message}

@@ -55,7 +50,7 @@ const NotificationParent = ({ timeout = 2000 }) => { *whenever someone call the NotificationHandler with data for the alert this function will be called from * the pubsub closure * then the data will be pushed to the ending of the notification array with state update - * also at the same time a setTimeout will be runned which will remove the first entry from + * also at the same time a setTimeout will be run which will remove the first entry from * the notification array after "timeout" secs */ subscribe((alert) => { diff --git a/ui/src/Constant/constant.js b/ui/src/Constant/constant.js index c9355c4..16abc3f 100644 --- a/ui/src/Constant/constant.js +++ b/ui/src/Constant/constant.js @@ -1,5 +1,11 @@ export const FOOTER = { - "COPYRIGHT": "Copyright 2022-2023", - "RDS_WEBSITE": "RDS Website", - "DISCORD_SERVER":"Discord server" -} \ No newline at end of file + COPYRIGHT: "Copyright 2022-2023", + RDS_WEBSITE: "RDS Website", + DISCORD_SERVER: "Discord server", +}; + +export const TYPETOCOLOR = { + success: "rgb(95, 214, 95)", + warning: "rgb(238, 241, 41)", + error: "rgb(253, 81, 81)", +}; From cc5d4d374d6e70faf85725351ad33020de7ba9da Mon Sep 17 00:00:00 2001 From: Vinayak Date: Tue, 26 Jul 2022 16:33:09 +0530 Subject: [PATCH 4/9] new changes, refactoring. --- .../notification/{index.jsx => index.js} | 12 ++++----- ui/src/Constant/constant.js | 4 ++- ui/src/test/Notification.test.js | 26 +++++++------------ 3 files changed, 18 insertions(+), 24 deletions(-) rename ui/src/Components/notification/{index.jsx => index.js} (85%) diff --git a/ui/src/Components/notification/index.jsx b/ui/src/Components/notification/index.js similarity index 85% rename from ui/src/Components/notification/index.jsx rename to ui/src/Components/notification/index.js index 1094521..3065a46 100644 --- a/ui/src/Components/notification/index.jsx +++ b/ui/src/Components/notification/index.js @@ -1,10 +1,10 @@ import { useState } from "react"; -import { TYPETOCOLOR } from "../../Constant/constant"; +import { NOTIFICATION_TIMEOUT, TYPE_TO_COLOR } from "../../Constant/constant"; /** * a pubsub kind of implementation, basically it will save a function in closure with varaible called "fn" - * when i use a function called subcribe and pass it with the function i want to save - * then when i will call publish function with "data" parameter it will call the function present in "fn" + * when we use a function called subcribe and pass it with the function we want to save + * then, when we will call publish function with "data" parameter it will call the function present in "fn" * with the "data" as a arguement */ export const NotificationQue = () => { @@ -36,14 +36,14 @@ export const NotificationElement = ({ data }) => {

{data.message}

); }; -const NotificationParent = ({ timeout = 2000 }) => { +const NotificationParent = () => { const [notifications, setNotifications] = useState([]); /* @@ -61,7 +61,7 @@ const NotificationParent = ({ timeout = 2000 }) => { let [_, ...data] = prev; return data; }); - }, timeout); + }, NOTIFICATION_TIMEOUT); }); return ( diff --git a/ui/src/Constant/constant.js b/ui/src/Constant/constant.js index 16abc3f..429351f 100644 --- a/ui/src/Constant/constant.js +++ b/ui/src/Constant/constant.js @@ -4,8 +4,10 @@ export const FOOTER = { DISCORD_SERVER: "Discord server", }; -export const TYPETOCOLOR = { +export const TYPE_TO_COLOR = { success: "rgb(95, 214, 95)", warning: "rgb(238, 241, 41)", error: "rgb(253, 81, 81)", }; + +export const NOTIFICATION_TIMEOUT = 2000; diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js index 423fdf3..272375e 100644 --- a/ui/src/test/Notification.test.js +++ b/ui/src/test/Notification.test.js @@ -1,12 +1,12 @@ -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import "@testing-library/jest-dom"; import { act } from "react-dom/test-utils"; import NotificationParent, { NotificationHandler, - NotificationElement, NotificationQue, } from "../Components/notification"; +import { TYPE_TO_COLOR } from "../Constant/constant"; describe("notification Functionality", () => { it("notification parent renders on the screen", async () => { @@ -20,18 +20,6 @@ describe("notification Functionality", () => { expect(publish(5)).toEqual(50); }); - it("check that notification element gets the correct data", async () => { - let notificationProps = { message: "Hello World", type: "success" }; - render(); - - expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( - notificationProps.message - ); - expect(screen.getByTestId("notification-child")).toHaveClass( - `notification-${notificationProps.type}` - ); - }); - it("checking the whole function cycle of the notification feature", async () => { render(); @@ -41,11 +29,15 @@ describe("notification Functionality", () => { NotificationHandler(notificationProps); }); + let notificationChild = await waitFor(() => + screen.getByTestId("notification-child") + ); + + expect(notificationChild.style.backgroundColor).toEqual( + TYPE_TO_COLOR[notificationProps.type] + ); expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( notificationProps.message ); - expect(screen.getByTestId("notification-child")).toHaveClass( - `notification-${notificationProps.type}` - ); }); }); From 522a1e2d06e231ff700faaae8a73e879459b2310 Mon Sep 17 00:00:00 2001 From: Vinayak Date: Sun, 31 Jul 2022 22:15:43 +0530 Subject: [PATCH 5/9] notification component migrated to Context API, test cases are remaining --- ui/src/Components/notification/index.js | 79 ++++--------------------- ui/src/Context/NotificationContext.js | 31 ++++++++++ ui/src/index.js | 17 +++--- 3 files changed, 54 insertions(+), 73 deletions(-) create mode 100644 ui/src/Context/NotificationContext.js diff --git a/ui/src/Components/notification/index.js b/ui/src/Components/notification/index.js index 3065a46..664991a 100644 --- a/ui/src/Components/notification/index.js +++ b/ui/src/Components/notification/index.js @@ -1,78 +1,25 @@ -import { useState } from "react"; -import { NOTIFICATION_TIMEOUT, TYPE_TO_COLOR } from "../../Constant/constant"; - -/** - * a pubsub kind of implementation, basically it will save a function in closure with varaible called "fn" - * when we use a function called subcribe and pass it with the function we want to save - * then, when we will call publish function with "data" parameter it will call the function present in "fn" - * with the "data" as a arguement - */ -export const NotificationQue = () => { - let fn = () => {}; - const subscribe = (callback) => { - fn = callback; - }; - const publish = (data) => { - return fn(data); - }; - return { subscribe, publish }; -}; - -/** - * now this NotificationHandler can be imported in any component and can be called to create a - * notification - */ -export const { subscribe, publish: NotificationHandler } = NotificationQue(); - -/** - * when we have decided what kind of resources we want to use for icons there also be an icon rendered according to - * type of the notification - * - * - * @param {{message : string, type : string}} data the structure of notification that has to be passed down to the NotificationHandler - */ -export const NotificationElement = ({ data }) => { - return ( -
-

{data.message}

-
- ); -}; +import { TYPE_TO_COLOR } from "../../Constant/constant"; +import { useNotificationContext } from "../../Context/NotificationContext"; const NotificationParent = () => { - const [notifications, setNotifications] = useState([]); - - /* - *whenever someone call the NotificationHandler with data for the alert this function will be called from - * the pubsub closure - * then the data will be pushed to the ending of the notification array with state update - * also at the same time a setTimeout will be run which will remove the first entry from - * the notification array after "timeout" secs - */ - subscribe((alert) => { - setNotifications((prev) => [...prev, alert]); - - setTimeout(() => { - setNotifications((prev) => { - let [_, ...data] = prev; - return data; - }); - }, NOTIFICATION_TIMEOUT); - }); + const { notificationQue } = useNotificationContext(); return (
- {notifications.map((alert, index) => ( - + {notificationQue.map((alert, index) => ( +
+

{alert.message}

+
))}
); diff --git a/ui/src/Context/NotificationContext.js b/ui/src/Context/NotificationContext.js new file mode 100644 index 0000000..4a58f68 --- /dev/null +++ b/ui/src/Context/NotificationContext.js @@ -0,0 +1,31 @@ +import { createContext, useContext, useState } from "react"; +import { NOTIFICATION_TIMEOUT } from "../Constant/constant"; + +export const NotificationContext = createContext(); + +export const useNotificationContext = () => useContext(NotificationContext); + +const NotificationProvider = ({ children }) => { + const [notificationQue, setNotificationQue] = useState([]); + + const createNotifcation = (notificationData) => { + setNotificationQue((prev) => [...prev, notificationData]); + + setTimeout(() => { + setNotificationQue((prev) => { + let [_, ...data] = prev; + return data; + }); + }, NOTIFICATION_TIMEOUT); + }; + + return ( + + {children} + + ); +}; + +export default NotificationProvider; diff --git a/ui/src/index.js b/ui/src/index.js index d563c0f..73b6ae8 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -1,13 +1,16 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; +import NotificationProvider from "./Context/NotificationContext"; -const root = ReactDOM.createRoot(document.getElementById('root')); +const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + + + ); From cf1fd1aadac41458a1b3b84255063e52fa93ffec Mon Sep 17 00:00:00 2001 From: Vinayak Date: Mon, 1 Aug 2022 20:49:35 +0530 Subject: [PATCH 6/9] default value in context added, test cases updated --- ui/src/Context/NotificationContext.js | 5 ++- ui/src/test/Notification.test.js | 45 ++++++++++++++++----------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/ui/src/Context/NotificationContext.js b/ui/src/Context/NotificationContext.js index 4a58f68..c33e4c8 100644 --- a/ui/src/Context/NotificationContext.js +++ b/ui/src/Context/NotificationContext.js @@ -1,7 +1,10 @@ import { createContext, useContext, useState } from "react"; import { NOTIFICATION_TIMEOUT } from "../Constant/constant"; -export const NotificationContext = createContext(); +export const NotificationContext = createContext({ + createNotifcation() {}, + notificationQue: [], +}); export const useNotificationContext = () => useContext(NotificationContext); diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js index 272375e..5e47f76 100644 --- a/ui/src/test/Notification.test.js +++ b/ui/src/test/Notification.test.js @@ -1,33 +1,42 @@ import { render, screen, waitFor } from "@testing-library/react"; import "@testing-library/jest-dom"; -import { act } from "react-dom/test-utils"; -import NotificationParent, { - NotificationHandler, - NotificationQue, -} from "../Components/notification"; -import { TYPE_TO_COLOR } from "../Constant/constant"; +import NotificationParent from "../Components/notification"; +import { NOTIFICATION_TIMEOUT, TYPE_TO_COLOR } from "../Constant/constant"; +import { NotificationContext } from "../Context/NotificationContext"; +import React from "react"; + +const customeRender = (ui, { value, ...options }) => + render( + + {ui} + , + options + ); describe("notification Functionality", () => { it("notification parent renders on the screen", async () => { - render(); + render(); expect(screen.getByTestId("notification-parent")).toBeInTheDocument(); }); - it("check that pubsub que working fine", async () => { - const { publish, subscribe } = NotificationQue(); - subscribe((a) => a * 10); - expect(publish(5)).toEqual(50); - }); - it("checking the whole function cycle of the notification feature", async () => { - render(); - let notificationProps = { message: "Hello World", type: "success" }; - act(() => { - NotificationHandler(notificationProps); - }); + const contextValue = { + notificationQue: [], + createNotifcation(data) { + this.notificationQue = [data, ...this.notificationQue]; + + setTimeout(() => { + let [_, ...data] = this.notificationQue; + this.notificationQue = data; + }, NOTIFICATION_TIMEOUT); + }, + }; + + contextValue.createNotifcation(notificationProps); + customeRender(, { value: contextValue }); let notificationChild = await waitFor(() => screen.getByTestId("notification-child") From 4213a19eb060e3187ffe81d86dcc1c8a196021c0 Mon Sep 17 00:00:00 2001 From: Vinayak Date: Tue, 2 Aug 2022 13:42:56 +0530 Subject: [PATCH 7/9] changes done as suggested with new test cases added --- ui/src/Components/notification/index.js | 18 ++++--- ui/src/Constant/constant.js | 6 +-- ui/src/Context/NotificationContext.js | 16 +++--- ui/src/test/Notification.test.js | 70 +++++++++++++++++-------- 4 files changed, 72 insertions(+), 38 deletions(-) diff --git a/ui/src/Components/notification/index.js b/ui/src/Components/notification/index.js index 664991a..943799e 100644 --- a/ui/src/Components/notification/index.js +++ b/ui/src/Components/notification/index.js @@ -2,23 +2,27 @@ import { TYPE_TO_COLOR } from "../../Constant/constant"; import { useNotificationContext } from "../../Context/NotificationContext"; const NotificationParent = () => { - const { notificationQue } = useNotificationContext(); + const { notificationQueue } = useNotificationContext(); return (
- {notificationQue.map((alert, index) => ( + {notificationQueue.map((notification, index) => (
-

{alert.message}

+

{notification.message}

))}
diff --git a/ui/src/Constant/constant.js b/ui/src/Constant/constant.js index 429351f..da94604 100644 --- a/ui/src/Constant/constant.js +++ b/ui/src/Constant/constant.js @@ -5,9 +5,9 @@ export const FOOTER = { }; export const TYPE_TO_COLOR = { - success: "rgb(95, 214, 95)", - warning: "rgb(238, 241, 41)", - error: "rgb(253, 81, 81)", + SUCCESS: "rgb(95, 214, 95)", + WARNING: "rgb(238, 241, 41)", + ERROR: "rgb(253, 81, 81)", }; export const NOTIFICATION_TIMEOUT = 2000; diff --git a/ui/src/Context/NotificationContext.js b/ui/src/Context/NotificationContext.js index c33e4c8..8180203 100644 --- a/ui/src/Context/NotificationContext.js +++ b/ui/src/Context/NotificationContext.js @@ -3,19 +3,23 @@ import { NOTIFICATION_TIMEOUT } from "../Constant/constant"; export const NotificationContext = createContext({ createNotifcation() {}, - notificationQue: [], + notificationQueue: [], }); export const useNotificationContext = () => useContext(NotificationContext); const NotificationProvider = ({ children }) => { - const [notificationQue, setNotificationQue] = useState([]); + const [notificationQueue, setNotificationQueue] = useState([]); - const createNotifcation = (notificationData) => { - setNotificationQue((prev) => [...prev, notificationData]); + /** + * + * @param {type : string, message : string} notificationContent + */ + const createNotifcation = (notificationContent) => { + setNotificationQueue((prev) => [...prev, notificationContent]); setTimeout(() => { - setNotificationQue((prev) => { + setNotificationQueue((prev) => { let [_, ...data] = prev; return data; }); @@ -24,7 +28,7 @@ const NotificationProvider = ({ children }) => { return ( {children} diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js index 5e47f76..c3d8b56 100644 --- a/ui/src/test/Notification.test.js +++ b/ui/src/test/Notification.test.js @@ -6,7 +6,7 @@ import { NOTIFICATION_TIMEOUT, TYPE_TO_COLOR } from "../Constant/constant"; import { NotificationContext } from "../Context/NotificationContext"; import React from "react"; -const customeRender = (ui, { value, ...options }) => +const customRender = (ui, { value, ...options }) => render( {ui} @@ -14,39 +14,65 @@ const customeRender = (ui, { value, ...options }) => options ); -describe("notification Functionality", () => { - it("notification parent renders on the screen", async () => { +let notificationContent = { message: "Hello World", type: "success" }; + +let mockNotificationContext = {}; + +beforeEach(() => { + mockNotificationContext = { + notificationQueue: [], + createNotifcation(data) { + this.notificationQueue = [data, ...this.notificationQueue]; + + setTimeout(() => { + let [_, ...data] = this.notificationQueue; + this.notificationQueue = data; + }, NOTIFICATION_TIMEOUT); + }, + }; +}); + +afterEach(() => { + mockNotificationContext = {}; +}); + +describe("Notification Component", () => { + it("should check if the notification wrapper renders", async () => { render(); - expect(screen.getByTestId("notification-parent")).toBeInTheDocument(); + expect(screen.getByTestId("notificationparent")).toBeInTheDocument(); }); - it("checking the whole function cycle of the notification feature", async () => { - let notificationProps = { message: "Hello World", type: "success" }; + it("should check the function cycle of the notification component", async () => { + mockNotificationContext.createNotifcation(notificationContent); + customRender(, { value: mockNotificationContext }); - const contextValue = { - notificationQue: [], - createNotifcation(data) { - this.notificationQue = [data, ...this.notificationQue]; + let notificationChild = await waitFor(() => + screen.getByTestId("notificationchild") + ); - setTimeout(() => { - let [_, ...data] = this.notificationQue; - this.notificationQue = data; - }, NOTIFICATION_TIMEOUT); - }, - }; + expect(notificationChild).toHaveTextContent(notificationContent.message); + }); - contextValue.createNotifcation(notificationProps); - customeRender(, { value: contextValue }); + it("should check if the color rendered is the same one as passed", async () => { + mockNotificationContext.createNotifcation(notificationContent); + customRender(, { value: mockNotificationContext }); let notificationChild = await waitFor(() => - screen.getByTestId("notification-child") + screen.getByTestId("notificationchild") ); - expect(notificationChild.style.backgroundColor).toEqual( - TYPE_TO_COLOR[notificationProps.type] + TYPE_TO_COLOR[notificationContent.type.toUpperCase()] + ); + }); + it("should check if the heading rendered as h3", async () => { + mockNotificationContext.createNotifcation(notificationContent); + customRender(, { value: mockNotificationContext }); + + let notificationChild = await waitFor(() => + screen.getByTestId("notificationchild") ); expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( - notificationProps.message + notificationContent.message ); }); }); From f56dd043a3eb6e47ed7dca76fb9616a738b99ac3 Mon Sep 17 00:00:00 2001 From: Vinayak Date: Thu, 11 Aug 2022 19:55:25 +0530 Subject: [PATCH 8/9] Requested Changes are done --- ui/src/Components/notification/index.js | 6 +++--- ui/src/Constant/constant.js | 2 +- ui/src/Context/NotificationContext.js | 2 +- ui/src/test/Notification.test.js | 7 +++++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ui/src/Components/notification/index.js b/ui/src/Components/notification/index.js index 943799e..ec81b38 100644 --- a/ui/src/Components/notification/index.js +++ b/ui/src/Components/notification/index.js @@ -1,4 +1,4 @@ -import { TYPE_TO_COLOR } from "../../Constant/constant"; +import { NOTIFICATION_TEXT_COLOR } from "../../Constant/constant"; import { useNotificationContext } from "../../Context/NotificationContext"; const NotificationParent = () => { @@ -18,11 +18,11 @@ const NotificationParent = () => { className="flex justify-start items-center min-w-full w-max bg-white font-['Helvetica', 'sans-serif'] font-medium text-base capitalize rounded px-2.5 py-1.5" style={{ backgroundColor: `${ - TYPE_TO_COLOR[notification.type.toUpperCase()] + NOTIFICATION_TEXT_COLOR[notification.type.toUpperCase()] }`, }} > -

{notification.message}

+

{notification.message}

))} diff --git a/ui/src/Constant/constant.js b/ui/src/Constant/constant.js index da94604..f9f47f0 100644 --- a/ui/src/Constant/constant.js +++ b/ui/src/Constant/constant.js @@ -4,7 +4,7 @@ export const FOOTER = { DISCORD_SERVER: "Discord server", }; -export const TYPE_TO_COLOR = { +export const NOTIFICATION_TEXT_COLOR = { SUCCESS: "rgb(95, 214, 95)", WARNING: "rgb(238, 241, 41)", ERROR: "rgb(253, 81, 81)", diff --git a/ui/src/Context/NotificationContext.js b/ui/src/Context/NotificationContext.js index 8180203..d89a32f 100644 --- a/ui/src/Context/NotificationContext.js +++ b/ui/src/Context/NotificationContext.js @@ -20,7 +20,7 @@ const NotificationProvider = ({ children }) => { setTimeout(() => { setNotificationQueue((prev) => { - let [_, ...data] = prev; + let [, ...data] = prev; return data; }); }, NOTIFICATION_TIMEOUT); diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js index c3d8b56..da6e940 100644 --- a/ui/src/test/Notification.test.js +++ b/ui/src/test/Notification.test.js @@ -2,7 +2,10 @@ import { render, screen, waitFor } from "@testing-library/react"; import "@testing-library/jest-dom"; import NotificationParent from "../Components/notification"; -import { NOTIFICATION_TIMEOUT, TYPE_TO_COLOR } from "../Constant/constant"; +import { + NOTIFICATION_TIMEOUT, + NOTIFICATION_TEXT_COLOR, +} from "../Constant/constant"; import { NotificationContext } from "../Context/NotificationContext"; import React from "react"; @@ -61,7 +64,7 @@ describe("Notification Component", () => { screen.getByTestId("notificationchild") ); expect(notificationChild.style.backgroundColor).toEqual( - TYPE_TO_COLOR[notificationContent.type.toUpperCase()] + NOTIFICATION_TEXT_COLOR[notificationContent.type.toUpperCase()] ); }); it("should check if the heading rendered as h3", async () => { From cb18b87ff44486620e455d3fd6579330fb5431e2 Mon Sep 17 00:00:00 2001 From: Vinayak Goyal Date: Mon, 3 Oct 2022 11:19:53 +0530 Subject: [PATCH 9/9] requested changes done --- ui/src/Components/notification/index.js | 6 +++--- ui/src/test/Notification.test.js | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ui/src/Components/notification/index.js b/ui/src/Components/notification/index.js index ec81b38..632731c 100644 --- a/ui/src/Components/notification/index.js +++ b/ui/src/Components/notification/index.js @@ -1,12 +1,12 @@ import { NOTIFICATION_TEXT_COLOR } from "../../Constant/constant"; import { useNotificationContext } from "../../Context/NotificationContext"; -const NotificationParent = () => { +const NotificationContainer = () => { const { notificationQueue } = useNotificationContext(); return (
{ ); }; -export default NotificationParent; +export default NotificationContainer; diff --git a/ui/src/test/Notification.test.js b/ui/src/test/Notification.test.js index da6e940..040ba6a 100644 --- a/ui/src/test/Notification.test.js +++ b/ui/src/test/Notification.test.js @@ -1,7 +1,7 @@ import { render, screen, waitFor } from "@testing-library/react"; import "@testing-library/jest-dom"; -import NotificationParent from "../Components/notification"; +import NotificationContainer from "../Components/notification"; import { NOTIFICATION_TIMEOUT, NOTIFICATION_TEXT_COLOR, @@ -28,7 +28,7 @@ beforeEach(() => { this.notificationQueue = [data, ...this.notificationQueue]; setTimeout(() => { - let [_, ...data] = this.notificationQueue; + let [, ...data] = this.notificationQueue; this.notificationQueue = data; }, NOTIFICATION_TIMEOUT); }, @@ -41,13 +41,13 @@ afterEach(() => { describe("Notification Component", () => { it("should check if the notification wrapper renders", async () => { - render(); - expect(screen.getByTestId("notificationparent")).toBeInTheDocument(); + render(); + expect(screen.getByTestId("notificationcontainer")).toBeInTheDocument(); }); it("should check the function cycle of the notification component", async () => { mockNotificationContext.createNotifcation(notificationContent); - customRender(, { value: mockNotificationContext }); + customRender(, { value: mockNotificationContext }); let notificationChild = await waitFor(() => screen.getByTestId("notificationchild") @@ -58,7 +58,7 @@ describe("Notification Component", () => { it("should check if the color rendered is the same one as passed", async () => { mockNotificationContext.createNotifcation(notificationContent); - customRender(, { value: mockNotificationContext }); + customRender(, { value: mockNotificationContext }); let notificationChild = await waitFor(() => screen.getByTestId("notificationchild") @@ -69,12 +69,13 @@ describe("Notification Component", () => { }); it("should check if the heading rendered as h3", async () => { mockNotificationContext.createNotifcation(notificationContent); - customRender(, { value: mockNotificationContext }); + customRender(, { value: mockNotificationContext }); let notificationChild = await waitFor(() => screen.getByTestId("notificationchild") ); - expect(screen.getByRole("heading", { level: 3 })).toHaveTextContent( + expect(screen.getByRole("alert").nodeName).toEqual('H3') + expect(screen.getByRole("alert")).toHaveTextContent( notificationContent.message ); });