Skip to content

Commit

Permalink
Merge pull request #668 from IntersectMBO/637-create-atoms-components…
Browse files Browse the repository at this point in the history
…-ui-tests

[#637] Create atoms components ui tests
  • Loading branch information
JanJaroszczak authored Apr 11, 2024
2 parents 2fc7e74 + efa2df0 commit 01bbc02
Show file tree
Hide file tree
Showing 7 changed files with 469 additions and 0 deletions.
1 change: 1 addition & 0 deletions govtool/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"test": "vitest",
"test:ui": "vitest --ui",
"test-storybook": "test-storybook",
"test:watch": "vitest watch",
"tsc": "npx tsc --noEmit --skipLibCheck"
Expand Down
90 changes: 90 additions & 0 deletions govtool/frontend/src/components/atoms/ActionRadio.test.tsx
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();
});
});
69 changes: 69 additions & 0 deletions govtool/frontend/src/components/atoms/CopyButton.test.tsx
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();
});
});
90 changes: 90 additions & 0 deletions govtool/frontend/src/components/atoms/DrawerLink.test.tsx
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 govtool/frontend/src/components/atoms/LoadingButton.test.tsx
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",
});
});
});
55 changes: 55 additions & 0 deletions govtool/frontend/src/components/atoms/VotePill.test.tsx
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",
});
});
});
Loading

0 comments on commit 01bbc02

Please sign in to comment.