-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #668 from IntersectMBO/637-create-atoms-components…
…-ui-tests [#637] Create atoms components ui tests
- Loading branch information
Showing
7 changed files
with
469 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
govtool/frontend/src/components/atoms/ActionRadio.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { describe, expect, it, vi } from "vitest"; | ||
import { fireEvent, render, screen } from "@testing-library/react"; | ||
import { ActionRadio } from "@atoms"; | ||
|
||
describe("ActionRadio", () => { | ||
it("should execute onChange with the correct value on click", () => { | ||
const handleChange = vi.fn(); | ||
render( | ||
<ActionRadio | ||
title="Test Radio" | ||
value="test-value" | ||
onChange={handleChange} | ||
dataTestId="action-radio" | ||
/>, | ||
); | ||
|
||
const radio = screen.getByTestId("action-radio"); | ||
fireEvent.click(radio); | ||
|
||
expect(handleChange).toHaveBeenCalledTimes(1); | ||
expect(handleChange).toHaveBeenCalledWith("test-value"); | ||
}); | ||
|
||
it("should change styles based on isChecked change", () => { | ||
const { rerender } = render( | ||
<ActionRadio | ||
title="Test Radio" | ||
value="unchecked-value" | ||
isChecked={false} | ||
onChange={() => {}} | ||
dataTestId="action-radio" | ||
/>, | ||
); | ||
let radio = screen.getByTestId("action-radio"); | ||
|
||
expect(radio).toHaveStyle("borderColor: white"); | ||
expect(radio).toHaveStyle("backgroundColor: rgb(255, 255, 255)"); | ||
|
||
rerender( | ||
<ActionRadio | ||
title="Test Radio" | ||
value="checked-value" | ||
isChecked | ||
onChange={() => {}} | ||
dataTestId="action-radio" | ||
/>, | ||
); | ||
radio = screen.getByTestId("action-radio"); | ||
|
||
expect(radio).toHaveStyle("borderColor: specialCyanBorder"); | ||
expect(radio).toHaveStyle("backgroundColor: specialCyan"); | ||
}); | ||
|
||
it("should display correct title and optional subtitle", () => { | ||
render( | ||
<ActionRadio | ||
title="Main Title" | ||
subtitle="Sub Title" | ||
value="any-value" | ||
onChange={() => {}} | ||
dataTestId="action-radio" | ||
/>, | ||
); | ||
|
||
const title = screen.getByText("Main Title"); | ||
const subtitle = screen.getByText("Sub Title"); | ||
|
||
expect(title).toBeInTheDocument(); | ||
expect(subtitle).toBeInTheDocument(); | ||
}); | ||
|
||
it("should display tooltip text when InfoOutlinedIcon is hovered over", async () => { | ||
render( | ||
<ActionRadio | ||
title="With Tooltip" | ||
tooltipText="Info Here" | ||
tooltipTitle="Tooltip" | ||
value="tooltip-present-value" | ||
onChange={() => {}} | ||
dataTestId="action-radio" | ||
/>, | ||
); | ||
|
||
const icon = screen.getByTestId("InfoOutlinedIcon"); | ||
fireEvent.mouseOver(icon); | ||
|
||
const tooltip = await screen.findByText("Info Here", {}, { timeout: 500 }); | ||
expect(tooltip).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { describe, it, expect, vi } from "vitest"; | ||
import { render, screen } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { SnackbarProvider } from "@context"; | ||
import { CopyButton } from "@atoms"; | ||
|
||
Object.defineProperty(global.navigator, "clipboard", { | ||
value: { | ||
writeText: vi.fn(), | ||
}, | ||
writable: true, | ||
}); | ||
|
||
vi.mock("@hooks", () => ({ | ||
useTranslation: () => ({ | ||
t: (key: string) => key, | ||
}), | ||
useScreenDimension: () => ({ | ||
isMobile: false, | ||
}), | ||
})); | ||
|
||
const writeTextMock = navigator.clipboard.writeText as unknown as { | ||
mockClear: () => void; | ||
}; | ||
|
||
describe("CopyButton", () => { | ||
beforeEach(() => { | ||
writeTextMock.mockClear(); | ||
}); | ||
|
||
it("renders correctly with the default icon", () => { | ||
render(<CopyButton text="Example Text" />); | ||
const image = screen.getByRole("img"); | ||
expect(image).toHaveAttribute("src", "/icons/Copy.svg"); | ||
}); | ||
|
||
it("renders the blue icon when variant is 'blue'", () => { | ||
render(<CopyButton text="Example Text" variant="blue" />); | ||
const image = screen.getByRole("img"); | ||
expect(image).toHaveAttribute("src", "/icons/CopyBlue.svg"); | ||
}); | ||
|
||
it("renders the blue thin icon when variant is 'blueThin'", () => { | ||
render(<CopyButton text="Example Text" variant="blueThin" />); | ||
const image = screen.getByRole("img"); | ||
expect(image).toHaveAttribute("src", "/icons/CopyBlueThin.svg"); | ||
}); | ||
|
||
it("renders the white icon when isChecked prop is true", () => { | ||
render(<CopyButton text="Example Text" isChecked />); | ||
const image = screen.getByRole("img"); | ||
expect(image).toHaveAttribute("src", "/icons/CopyWhite.svg"); | ||
}); | ||
|
||
it("copies text to clipboard and shows success alert on click", async () => { | ||
render( | ||
<SnackbarProvider> | ||
<CopyButton text="Example Text" />, | ||
</SnackbarProvider>, | ||
); | ||
|
||
const copyButton = screen.getByTestId("copy-button"); | ||
await userEvent.click(copyButton); | ||
expect(navigator.clipboard.writeText).toHaveBeenCalledWith("Example Text"); | ||
|
||
expect(screen.getByText("alerts.copiedToClipboard")).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { describe, it, expect, vi } from "vitest"; | ||
import { render, screen, fireEvent } from "@testing-library/react"; | ||
import { MemoryRouter, Route, Routes } from "react-router-dom"; | ||
import { DrawerLink } from "@atoms"; | ||
import { theme } from "@/theme"; | ||
|
||
describe("DrawerLink", () => { | ||
const mockOnClick = vi.fn(); | ||
|
||
it("renders correctly with mandatory props", () => { | ||
render( | ||
<MemoryRouter initialEntries={["/somepath"]}> | ||
<DrawerLink label="Home" navTo="/home" /> | ||
</MemoryRouter>, | ||
); | ||
|
||
const linkElement = screen.getByRole("link"); | ||
expect(linkElement).toHaveAttribute("href", "/home"); | ||
expect(screen.getByText("Home")).toBeInTheDocument(); | ||
}); | ||
|
||
it("applies active styles correctly when active", () => { | ||
render( | ||
<MemoryRouter initialEntries={["/home"]}> | ||
<Routes> | ||
<Route | ||
path="/home" | ||
element={<DrawerLink label="Home" navTo="/home" />} | ||
/> | ||
</Routes> | ||
</MemoryRouter>, | ||
); | ||
|
||
const linkElement = screen.getByRole("link"); | ||
expect(linkElement).toHaveStyle( | ||
`backgroundColor: ${theme.palette.highlightBlue}`, | ||
); | ||
}); | ||
|
||
it("does not apply active styles when not active", () => { | ||
render( | ||
<MemoryRouter initialEntries={["/other"]}> | ||
<DrawerLink label="Home" navTo="/home" /> | ||
</MemoryRouter>, | ||
); | ||
|
||
const linkElement = screen.getByRole("link"); | ||
expect(linkElement).not.toHaveStyle( | ||
`backgroundColor: ${theme.palette.highlightBlue}`, | ||
); | ||
}); | ||
|
||
it("renders with an icon and activeIcon", () => { | ||
const icon = "icon-path.png"; | ||
const activeIcon = "active-icon-path.png"; | ||
|
||
render( | ||
<MemoryRouter initialEntries={["/home"]}> | ||
<Routes> | ||
<Route | ||
path="/home" | ||
element={ | ||
<DrawerLink | ||
label="Home" | ||
navTo="/home" | ||
icon={icon} | ||
activeIcon={activeIcon} | ||
/> | ||
} | ||
/> | ||
</Routes> | ||
</MemoryRouter>, | ||
); | ||
|
||
const img = screen.getByAltText("icon") as HTMLImageElement; | ||
expect(img.src).toContain("active-icon-path.png"); | ||
}); | ||
|
||
it("executes onClick callback when clicked", () => { | ||
render( | ||
<MemoryRouter initialEntries={["/home"]}> | ||
<DrawerLink label="Clickable" navTo="/click" onClick={mockOnClick} /> | ||
</MemoryRouter>, | ||
); | ||
|
||
const linkElement = screen.getByRole("link"); | ||
fireEvent.click(linkElement); | ||
expect(mockOnClick).toHaveBeenCalled(); | ||
}); | ||
}); |
53 changes: 53 additions & 0 deletions
53
govtool/frontend/src/components/atoms/LoadingButton.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { describe, it, expect } from "vitest"; | ||
import { render, screen } from "@testing-library/react"; | ||
import { LoadingButton } from "@atoms"; | ||
|
||
describe("LoadingButton", () => { | ||
it("renders its children", () => { | ||
render(<LoadingButton isLoading={false}>Click me</LoadingButton>); | ||
expect(screen.getByText("Click me")).toBeInTheDocument(); | ||
}); | ||
|
||
it("is disabled when isLoading is true", () => { | ||
render(<LoadingButton isLoading>Loading...</LoadingButton>); | ||
expect(screen.getByRole("button", { name: "Loading..." })).toBeDisabled(); | ||
}); | ||
|
||
it("is disabled when disabled prop is true", () => { | ||
render(<LoadingButton disabled>Disabled</LoadingButton>); | ||
expect(screen.getByRole("button", { name: "Disabled" })).toBeDisabled(); | ||
}); | ||
|
||
it("shows a CircularProgress when isLoading", () => { | ||
render(<LoadingButton isLoading>Loading...</LoadingButton>); | ||
expect(screen.getByRole("progressbar")).toBeInTheDocument(); | ||
}); | ||
|
||
it("applies different heights based on size prop", () => { | ||
const { rerender } = render( | ||
<LoadingButton size="small">Small Button</LoadingButton>, | ||
); | ||
|
||
expect(screen.getByText("Small Button")).toHaveStyle({ height: "32px" }); | ||
|
||
rerender(<LoadingButton size="medium">Medium Button</LoadingButton>); | ||
expect(screen.getByText("Medium Button")).toHaveStyle({ height: "36px" }); | ||
|
||
rerender(<LoadingButton size="large">Large Button</LoadingButton>); | ||
expect(screen.getByText("Large Button")).toHaveStyle({ height: "40px" }); | ||
|
||
rerender( | ||
<LoadingButton size="extraLarge">Extra Large Button</LoadingButton>, | ||
); | ||
expect(screen.getByText("Extra Large Button")).toHaveStyle("height: 48px"); | ||
}); | ||
|
||
it("applies custom styles via sx prop", () => { | ||
const customStyles = { backgroundColor: "specialCyan" }; | ||
render(<LoadingButton sx={customStyles}>Styled Button</LoadingButton>); | ||
|
||
expect(screen.getByText("Styled Button")).toHaveStyle({ | ||
backgroundColor: "specialCyan", | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { describe, it, expect } from "vitest"; | ||
import { render } from "@testing-library/react"; | ||
import { VotePill } from "@atoms"; | ||
|
||
describe("VotePill", () => { | ||
it('renders the VotePill component with "yes" vote correctly', () => { | ||
const { getByText } = render(<VotePill vote="yes" />); | ||
const voteText = getByText("yes"); | ||
expect(voteText).toBeInTheDocument(); | ||
expect(voteText.parentNode).toHaveStyle({ | ||
borderColor: "#C0E4BA", | ||
backgroundColor: "#F0F9EE", | ||
}); | ||
}); | ||
|
||
it('renders the VotePill component with "no" vote correctly', () => { | ||
const { getByText } = render(<VotePill vote="no" />); | ||
const voteText = getByText("no"); | ||
expect(voteText).toBeInTheDocument(); | ||
expect(voteText.parentNode).toHaveStyle({ | ||
borderColor: "#EDACAC", | ||
backgroundColor: "#FBEBEB", | ||
}); | ||
}); | ||
|
||
it('renders the VotePill component with "abstain" vote correctly', () => { | ||
const { getByText } = render(<VotePill vote="abstain" />); | ||
const voteText = getByText("abstain"); | ||
expect(voteText).toBeInTheDocument(); | ||
expect(voteText.parentNode).toHaveStyle({ | ||
borderColor: "#99ADDE", | ||
backgroundColor: "#E6EBF7", | ||
}); | ||
}); | ||
|
||
it("handles custom width and maxWidth props correctly", () => { | ||
const { container } = render( | ||
<VotePill vote="yes" width={100} maxWidth={120} />, | ||
); | ||
const pillBox = container.firstChild; | ||
expect(pillBox).toHaveStyle({ | ||
width: "100px", | ||
maxWidth: "120px", | ||
}); | ||
}); | ||
|
||
it("defaults width and maxWidth when not provided", () => { | ||
const { container } = render(<VotePill vote="abstain" />); | ||
const pillBox = container.firstChild; | ||
expect(pillBox).toHaveStyle({ | ||
width: "auto", | ||
maxWidth: "auto", | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.