From 46d4adcfee72b0089a966e8d4dc462e859a4535b Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 17:52:33 +0000 Subject: [PATCH 1/8] added bp --- .../partials/OptionEntireCatalogue/func.tsx | 20 +++++++++++++++++++ .../partials/OptionEntireCatalogue/index.ts | 3 +++ .../partials/OptionEntireCatalogue/stories.ts | 15 ++++++++++++++ .../partials/OptionEntireCatalogue/styles.ts | 7 +++++++ 4 files changed, 45 insertions(+) create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/index.ts create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx new file mode 100644 index 0000000..2c16a96 --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx @@ -0,0 +1,20 @@ +import type { JSX } from "react"; + +import { OptionLayoutTemplate } from "@app-ui/navigation/templates"; + +type TProps = { + onRequestCatalogue: () => void; +}; + +export default function OptionEntireCatalogue({ + onRequestCatalogue, +}: TProps): JSX.Element { + return ( + + ); +} diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/index.ts b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/index.ts new file mode 100644 index 0000000..06cbde1 --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/index.ts @@ -0,0 +1,3 @@ +import OptionEntireCatalogue from "./func"; + +export default OptionEntireCatalogue; diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts new file mode 100644 index 0000000..5320ed4 --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import OptionEntireCatalogue from "./func"; + +const meta: Meta = { + title: "app/ui/navigation/partials/OptionEntireCatalogue", + component: OptionEntireCatalogue, + args: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Index: Story = {}; diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts new file mode 100644 index 0000000..e79d8cd --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts @@ -0,0 +1,7 @@ +import { makeStyles } from "@lib-theme"; + +const useOptionEntireCatalogueClasses = makeStyles({ + root: {}, +}); + +export default useOptionEntireCatalogueClasses; From c488776c8ada7901d20653aa5e0dae4d0a1aa921 Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 18:01:56 +0000 Subject: [PATCH 2/8] done --- .../partials/OptionEntireCatalogue/func.tsx | 12 ++++++---- .../partials/OptionEntireCatalogue/styles.ts | 7 ------ .../templates/OptionLayout/func.tsx | 22 ++++++++++--------- libs/components/src/index.ts | 1 + 4 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx index 2c16a96..7687993 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/func.tsx @@ -4,17 +4,21 @@ import { OptionLayoutTemplate } from "@app-ui/navigation/templates"; type TProps = { onRequestCatalogue: () => void; + isRequestingCatalogue: boolean; + disableButton: boolean; }; export default function OptionEntireCatalogue({ onRequestCatalogue, + isRequestingCatalogue, + disableButton, }: TProps): JSX.Element { return ( ); } diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts deleted file mode 100644 index e79d8cd..0000000 --- a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/styles.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { makeStyles } from "@lib-theme"; - -const useOptionEntireCatalogueClasses = makeStyles({ - root: {}, -}); - -export default useOptionEntireCatalogueClasses; diff --git a/apps/frontend/ui/src/navigation/templates/OptionLayout/func.tsx b/apps/frontend/ui/src/navigation/templates/OptionLayout/func.tsx index 2ed218b..4fc0b1d 100644 --- a/apps/frontend/ui/src/navigation/templates/OptionLayout/func.tsx +++ b/apps/frontend/ui/src/navigation/templates/OptionLayout/func.tsx @@ -1,35 +1,37 @@ import type { JSX, ReactNode } from "react"; -import { Flex, Button } from "@lib-components"; +import { Flex, Button, Spinner } from "@lib-components"; import { Subtitle2, Caption2 } from "@lib-theme"; import useOptionLayoutClasses from "@app-ui/navigation/templates/OptionLayout/styles"; type TProps = { header: string; - subtitle: string; + onClick: () => void; + disableClick?: boolean; + isLoading?: boolean; + subtitle?: string; children?: ReactNode; - onSearch: () => void; - disabledSearch: boolean; }; export default function OptionLayout({ header, - subtitle, + onClick, + subtitle = undefined, children = undefined, - onSearch, - disabledSearch, + disableClick = false, + isLoading = false, }: TProps): JSX.Element { const classes = useOptionLayoutClasses(); return ( {header} - {subtitle} + {subtitle && {subtitle}} {children} - ); diff --git a/libs/components/src/index.ts b/libs/components/src/index.ts index 295896e..449766b 100644 --- a/libs/components/src/index.ts +++ b/libs/components/src/index.ts @@ -4,6 +4,7 @@ export { TabList } from "@fluentui/react-components"; export { Button } from "@fluentui/react-components"; export { MenuList } from "@fluentui/react-components"; export { MenuItemRadio } from "@fluentui/react-components"; +export { Spinner } from "@fluentui/react-components"; export { Collapse } from "@fluentui/react-motion-components-preview"; From 2d7c9cf0ef0b26a38c7689f9992af9d389b9942c Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 18:19:38 +0000 Subject: [PATCH 3/8] missing u for storybook --- .../partials/OptionConcepts/func.tsx | 22 ++++++++++++------- .../partials/OptionConcepts/hooks.ts | 14 +++++++----- .../{stories.ts => stories.tsx} | 0 3 files changed, 23 insertions(+), 13 deletions(-) rename apps/frontend/ui/src/navigation/partials/OptionConcepts/{stories.ts => stories.tsx} (100%) diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx index 499db14..ab65266 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx @@ -1,4 +1,4 @@ -import type { JSX } from "react"; +import type { JSX, useState } from "react"; import { MenuList } from "@lib-components"; @@ -9,23 +9,29 @@ import { useSelectionState } from "@app-ui/navigation/partials/OptionConcepts/ho type TProps = { concepts: string[]; - onSearch: (value: string) => void; + /* must be initialized with { concept: [] } */ + useCheckedValuesState: typeof useState>; + onSearch: () => void; + isReqestingConcepts: boolean; + disableButton: boolean; }; export default function OptionConcepts({ concepts, onSearch, + isReqestingConcepts, + useCheckedValuesState, + disableButton, }: TProps): JSX.Element { const classes = useOptionConceptsClasses(); - const { checkedValues, onChange } = useSelectionState(); + const { checkedValues, onChange } = useSelectionState(useCheckedValuesState); return ( { - onSearch(checkedValues.concept[0]); - }} - disabledSearch={checkedValues.concept.length === 0} + subtitle="Choose one from the given list below" + onClick={onSearch} + disableClick={disableButton} + isLoading={isReqestingConcepts} > >({ - concept: [], - }); +/** + * @param useCheckedValuesState needs to be initialized with { concept: [] } + */ +function useSelectionState( + useCheckedValuesState: typeof useState>, +) { + const [checkedValues, setCheckedValues] = useCheckedValuesState(); + const onChange: TMenuProps["onCheckedValueChange"] = ( _, { name, checkedItems }, diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.ts b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx similarity index 100% rename from apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.ts rename to apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx From 4f08a15d5d71e88ab4bfc3a0c425a3a05f5990d5 Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 18:36:38 +0000 Subject: [PATCH 4/8] u for stories --- .../partials/OptionConcepts/func.tsx | 15 +++-- .../partials/OptionConcepts/hooks.ts | 10 +-- .../partials/OptionConcepts/stories.tsx | 67 ++++++++++++++++++- 3 files changed, 79 insertions(+), 13 deletions(-) diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx index ab65266..2b69db1 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/func.tsx @@ -1,4 +1,4 @@ -import type { JSX, useState } from "react"; +import type { JSX, Dispatch, SetStateAction } from "react"; import { MenuList } from "@lib-components"; @@ -9,8 +9,9 @@ import { useSelectionState } from "@app-ui/navigation/partials/OptionConcepts/ho type TProps = { concepts: string[]; - /* must be initialized with { concept: [] } */ - useCheckedValuesState: typeof useState>; + /** must be initialized with { concept: [] }, only then inner functions apply state correctly */ + checkedValuesState: Record; + setCheckedValuesState: Dispatch>>; onSearch: () => void; isReqestingConcepts: boolean; disableButton: boolean; @@ -20,11 +21,15 @@ export default function OptionConcepts({ concepts, onSearch, isReqestingConcepts, - useCheckedValuesState, + checkedValuesState, + setCheckedValuesState, disableButton, }: TProps): JSX.Element { const classes = useOptionConceptsClasses(); - const { checkedValues, onChange } = useSelectionState(useCheckedValuesState); + const { checkedValues, onChange } = useSelectionState( + checkedValuesState, + setCheckedValuesState, + ); return ( >, + checkedValues: Record, + setCheckedValues: Dispatch>>, ) { - const [checkedValues, setCheckedValues] = useCheckedValuesState(); - const onChange: TMenuProps["onCheckedValueChange"] = ( _, { name, checkedItems }, diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx index 28cd5bd..8586392 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import type { Meta, StoryObj } from "@storybook/react"; import OptionConcepts from "@app-ui/navigation/partials/OptionConcepts"; @@ -15,7 +16,37 @@ export default meta; type Story = StoryObj; -export const Index: Story = {}; +export const Index: Story = { + render: () => { + const [checkedValues, setCheckedValues] = useState< + Record + >({ + concept: [], + }); + const [isFetching, setIsFetching] = useState(false); + + return ( + { + setIsFetching(true); + setTimeout(() => { + setIsFetching(false); + }, 2000); + }} + isReqestingConcepts={isFetching} + disableButton={checkedValues.concept.length === 0 || isFetching} + checkedValuesState={checkedValues} + setCheckedValuesState={setCheckedValues} + /> + ); + }, +}; export const WithOverflow: Story = { args: { @@ -31,4 +62,38 @@ export const WithOverflow: Story = { "Sustainability", ], }, + render: () => { + const [checkedValues, setCheckedValues] = useState< + Record + >({ + concept: [], + }); + const [isFetching, setIsFetching] = useState(false); + + return ( + { + setIsFetching(true); + setTimeout(() => { + setIsFetching(false); + }, 2000); + }} + isReqestingConcepts={isFetching} + disableButton={checkedValues.concept.length === 0 || isFetching} + checkedValuesState={checkedValues} + setCheckedValuesState={setCheckedValues} + /> + ); + }, }; From 19b9ff04a2344afacaf8f9ae4c083db2cfe2f7a8 Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 19:00:09 +0000 Subject: [PATCH 5/8] updated tests --- .../partials/OptionConcepts/stories.tsx | 14 ++-- .../partials/OptionConcepts/tests.tsx | 75 ++++++++++++------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx index 8586392..01f7ef2 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx @@ -6,10 +6,6 @@ import OptionConcepts from "@app-ui/navigation/partials/OptionConcepts"; const meta: Meta = { title: "App/UI/Navigation/Partials/OptionConcepts", component: OptionConcepts, - args: { - concepts: ["Partiality", "Signaling", "Connectivity", "Transformativity"], - onSearch: () => {}, - }, }; export default meta; @@ -17,7 +13,7 @@ export default meta; type Story = StoryObj; export const Index: Story = { - render: () => { + render: (props) => { const [checkedValues, setCheckedValues] = useState< Record >({ @@ -39,8 +35,12 @@ export const Index: Story = { setIsFetching(false); }, 2000); }} - isReqestingConcepts={isFetching} - disableButton={checkedValues.concept.length === 0 || isFetching} + isReqestingConcepts={isFetching || props.isReqestingConcepts} + disableButton={ + checkedValues.concept.length === 0 || + isFetching || + props.disableButton + } checkedValuesState={checkedValues} setCheckedValuesState={setCheckedValues} /> diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/tests.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/tests.tsx index 6257313..8286614 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/tests.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/tests.tsx @@ -1,18 +1,36 @@ +import { useState } from "react"; + import { render, screen, fireEvent } from "@tests-unit-browser"; import "@testing-library/jest-dom"; import OptionConcepts from "@app-ui/navigation/partials/OptionConcepts"; +function Wrapper() { + const [checkedValues, setCheckedValues] = useState>({ + concept: [], + }); + const [isFetching, setIsFetching] = useState(false); + + return ( + { + setIsFetching(true); + setTimeout(() => { + setIsFetching(false); + }, 3000); + }} + isReqestingConcepts={isFetching} + disableButton={checkedValues.concept.length === 0 || isFetching} + checkedValuesState={checkedValues} + setCheckedValuesState={setCheckedValues} + /> + ); +} + describe("OptionConcepts", () => { it("should render with given concepts", () => { - const onSearch = jest.fn((value: string) => value); - - render( - , - ); + render(); const menuList = screen.getByRole("menu"); expect(menuList).toBeInTheDocument(); @@ -26,40 +44,45 @@ describe("OptionConcepts", () => { }); it("should be able to select different concepts", () => { - const onSearch = jest.fn((value: string) => value); - - render( - , - ); + render(); const concept1 = screen.getByText("concept1"); - expect(concept1).toBeInTheDocument(); const concept2 = screen.getByText("concept2"); - expect(concept2).toBeInTheDocument(); const concept3 = screen.getByText("concept3"); - expect(concept3).toBeInTheDocument(); const searchButton = screen.getByRole("button", { name: "Search" }); expect(searchButton).toBeInTheDocument(); expect(searchButton).toBeDisabled(); fireEvent.click(concept1); + // has aria-checked attribute, when checked + expect(concept1.parentElement).toHaveAttribute("aria-checked", "true"); expect(searchButton).toBeEnabled(); - fireEvent.click(searchButton); - expect(onSearch).toHaveBeenCalledWith("concept1"); - fireEvent.click(concept2); - fireEvent.click(searchButton); - expect(onSearch).toHaveBeenCalledWith("concept2"); + expect(concept2.parentElement).toHaveAttribute("aria-checked", "true"); + // concept1 should be unchecked -> exclusitivity + expect(concept1.parentElement).toHaveAttribute("aria-checked", "false"); fireEvent.click(concept3); + expect(concept3.parentElement).toHaveAttribute("aria-checked", "true"); + expect(concept2.parentElement).toHaveAttribute("aria-checked", "false"); + }); + + it("should show loading state and disable search button", () => { + render(); + + const concept1 = screen.getByText("concept1"); + const searchButton = screen.getByRole("button", { name: "Search" }); + + fireEvent.click(concept1); + expect(searchButton).toBeEnabled(); + fireEvent.click(searchButton); - expect(onSearch).toHaveBeenCalledWith("concept3"); + expect(searchButton).toBeDisabled(); - expect(onSearch).toHaveBeenCalledTimes(3); + // role progressbar is used for loading state + const loading = screen.getByRole("progressbar"); + expect(loading).toBeInTheDocument(); }); }); From 6efbcb2ca74bf9ada47b1ad058d865e011d955b4 Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 19:04:37 +0000 Subject: [PATCH 6/8] updated stories --- .../partials/OptionConcepts/stories.tsx | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx index 01f7ef2..d82cced 100644 --- a/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx +++ b/apps/frontend/ui/src/navigation/partials/OptionConcepts/stories.tsx @@ -13,12 +13,44 @@ export default meta; type Story = StoryObj; export const Index: Story = { + argTypes: { + concepts: { control: false }, + onSearch: { control: false }, + checkedValuesState: { control: false }, + setCheckedValuesState: { control: false }, + }, render: (props) => { const [checkedValues, setCheckedValues] = useState< Record >({ concept: [], }); + + return ( + {}} + isReqestingConcepts={props.isReqestingConcepts} + disableButton={props.disableButton} + checkedValuesState={checkedValues} + setCheckedValuesState={setCheckedValues} + /> + ); + }, +}; + +export const FlowWithoutOverflow: Story = { + render: () => { + const [checkedValues, setCheckedValues] = useState< + Record + >({ + concept: [], + }); const [isFetching, setIsFetching] = useState(false); return ( @@ -35,12 +67,8 @@ export const Index: Story = { setIsFetching(false); }, 2000); }} - isReqestingConcepts={isFetching || props.isReqestingConcepts} - disableButton={ - checkedValues.concept.length === 0 || - isFetching || - props.disableButton - } + isReqestingConcepts={isFetching} + disableButton={checkedValues.concept.length === 0 || isFetching} checkedValuesState={checkedValues} setCheckedValuesState={setCheckedValues} /> @@ -48,20 +76,7 @@ export const Index: Story = { }, }; -export const WithOverflow: Story = { - args: { - concepts: [ - "Partiality", - "Signaling", - "Connectivity", - "Transformativity", - "Adaptability", - "Inclusivity", - "Interactivity", - "Reactivity", - "Sustainability", - ], - }, +export const FlowWithOverflow: Story = { render: () => { const [checkedValues, setCheckedValues] = useState< Record From 6d1000084a5fa7c5fb337a2511b0a418c12c5331 Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 19:15:26 +0000 Subject: [PATCH 7/8] u stories for main --- .../partials/OptionEntireCatalogue/stories.ts | 15 ------- .../OptionEntireCatalogue/stories.tsx | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) delete mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.tsx diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts deleted file mode 100644 index 5320ed4..0000000 --- a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import OptionEntireCatalogue from "./func"; - -const meta: Meta = { - title: "app/ui/navigation/partials/OptionEntireCatalogue", - component: OptionEntireCatalogue, - args: {}, -}; - -export default meta; - -type Story = StoryObj; - -export const Index: Story = {}; diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.tsx b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.tsx new file mode 100644 index 0000000..27a1943 --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/stories.tsx @@ -0,0 +1,40 @@ +import { useState } from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import OptionEntireCatalogue from "./func"; + +const meta: Meta = { + title: "app/ui/navigation/partials/OptionEntireCatalogue", + component: OptionEntireCatalogue, + args: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Index: Story = { + args: { + isRequestingCatalogue: false, + disableButton: false, + }, +}; + +export const Flow: Story = { + render: () => { + const [isRequestingCatalogue, setIsRequestingCatalogue] = useState(false); + + return ( + { + setIsRequestingCatalogue(true); + setTimeout(() => { + setIsRequestingCatalogue(false); + }, 3000); + }} + isRequestingCatalogue={isRequestingCatalogue} + disableButton={isRequestingCatalogue} + /> + ); + }, +}; From 8ea1f9eee939e716b3d13ad5a5a9813bd7ed40ff Mon Sep 17 00:00:00 2001 From: Samuil Berenzon Date: Mon, 10 Mar 2025 19:21:46 +0000 Subject: [PATCH 8/8] added test --- .../partials/OptionEntireCatalogue/tests.tsx | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/tests.tsx diff --git a/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/tests.tsx b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/tests.tsx new file mode 100644 index 0000000..2f0dc5e --- /dev/null +++ b/apps/frontend/ui/src/navigation/partials/OptionEntireCatalogue/tests.tsx @@ -0,0 +1,36 @@ +import { useState } from "react"; + +import { render, screen, fireEvent } from "@tests-unit-browser"; +import "@testing-library/jest-dom"; + +import OptionEntireCatalogue from "./func"; + +describe("OptionEntireCatalogue", () => { + it("should apply loading and disabling logic when clicked", () => { + function Wrapper() { + const [isRequestingCatalogue, setIsRequestingCatalogue] = useState(false); + + return ( + { + setIsRequestingCatalogue(true); + setTimeout(() => { + setIsRequestingCatalogue(false); + }, 3000); + }} + isRequestingCatalogue={isRequestingCatalogue} + disableButton={isRequestingCatalogue} + /> + ); + } + + render(); + const button = screen.getByRole("button"); + expect(button).toBeInTheDocument(); + expect(button).not.toBeDisabled(); + + fireEvent.click(button); + expect(button).toBeDisabled(); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); + }); +});