Skip to content

Commit

Permalink
Merge pull request #490 from huwshimi/add-sidepanel-tests
Browse files Browse the repository at this point in the history
WD-17055 - chore(tests): add SidePanel tests
  • Loading branch information
huwshimi authored Dec 3, 2024
2 parents 583d733 + 84968ea commit a2b87df
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 17 deletions.
5 changes: 4 additions & 1 deletion ui/src/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { FC } from "react";
import { Spinner } from "@canonical/react-components";

import { LoaderTestId } from "./index";
import { testId } from "test/utils";

interface Props {
text?: string;
}

const Loader: FC<Props> = ({ text = "Loading..." }) => {
return (
<div className="u-loader">
<div className="u-loader" {...testId(LoaderTestId.COMPONENT)}>
<Spinner text={text} />
</div>
);
Expand Down
1 change: 1 addition & 0 deletions ui/src/components/Loader/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from "./Loader";
export { TestId as LoaderTestId } from "./test-types";
3 changes: 3 additions & 0 deletions ui/src/components/Loader/test-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum TestId {
COMPONENT = "Loader",
}
135 changes: 135 additions & 0 deletions ui/src/components/SidePanel/SidePanel.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { screen, within } from "@testing-library/dom";
import { render } from "@testing-library/react";

import SidePanel from "./SidePanel";
import { Label } from "./types";
import { LoaderTestId } from "components/Loader";

describe("SidePanel", () => {
test("displays content", () => {
const content = "Content";
render(<SidePanel>{content}</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveTextContent(content);
});

test("can display as normal width", () => {
render(<SidePanel>Content</SidePanel>);
const sidePanel = screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
});
expect(sidePanel).not.toHaveClass("is-wide");
expect(sidePanel).not.toHaveClass("is-narrow");
});

test("can display as wide", () => {
render(<SidePanel width="wide">Content</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveClass("is-wide");
});

test("can display as narrow", () => {
render(<SidePanel width="narrow">Content</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveClass("is-narrow");
});

test("can display as split", () => {
render(<SidePanel isSplit>Content</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveClass("is-split");
});

test("can display as an overlay", () => {
render(<SidePanel isOverlay>Content</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveClass("is-overlay");
});

test("can display as pinned", () => {
render(<SidePanel pinned>Content</SidePanel>);
expect(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).toHaveClass("is-pinned");
});

test("can display loading state", () => {
render(<SidePanel loading>Content</SidePanel>);
expect(
within(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).getByTestId(LoaderTestId.COMPONENT),
).toBeInTheDocument();
});

test("can display loading error", () => {
render(<SidePanel hasError>Content</SidePanel>);
expect(
within(
screen.getByRole("complementary", {
name: Label.SIDE_PANEL,
}),
).getByText(Label.ERROR_LOADING),
).toBeInTheDocument();
});
});

test("HeaderControls", () => {
const content = "Content";
render(<SidePanel.HeaderControls>{content}</SidePanel.HeaderControls>);
expect(screen.getByText(content)).toHaveClass("p-panel__controls");
});

test("HeaderTitle", () => {
const content = "Content";
render(<SidePanel.HeaderTitle>{content}</SidePanel.HeaderTitle>);
expect(screen.getByText(content)).toHaveClass("p-panel__title");
});
test("Sticky", () => {
const content = "Content";
render(<SidePanel.Sticky>{content}</SidePanel.Sticky>);
expect(screen.getByText(content)).toHaveClass("sticky-wrapper");
});

test("Header", () => {
const content = "Content";
render(<SidePanel.Header>{content}</SidePanel.Header>);
expect(screen.getByText(content)).toHaveClass("p-panel__header");
});

test("Container", () => {
const content = "Content";
render(<SidePanel.Container>{content}</SidePanel.Container>);
expect(screen.getByText(content).parentElement).toHaveClass("p-panel");
});

test("Content", () => {
const content = "Content";
render(<SidePanel.Content>{content}</SidePanel.Content>);
expect(screen.getByText(content)).toHaveClass("p-panel__content");
});

test("Footer", () => {
const content = "Content";
render(<SidePanel.Footer>{content}</SidePanel.Footer>);
expect(screen.getByText(content)).toHaveClass("panel-footer");
});
31 changes: 15 additions & 16 deletions ui/src/components/SidePanel/SidePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { FC, PropsWithChildren, ReactNode } from "react";
import Loader from "components/Loader";
import classnames from "classnames";
import { AppAside, Panel, Spinner } from "@canonical/react-components";
import { AppAside, Panel } from "@canonical/react-components";
import { Label } from "./types";

interface CommonProps {
className?: string;
Expand Down Expand Up @@ -78,8 +79,8 @@ interface SidePanelProps {
isOverlay?: boolean;
isSplit?: boolean;
children: ReactNode;
loading: boolean;
hasError: boolean;
loading?: boolean;
hasError?: boolean;
className?: string;
width?: "narrow" | "wide";
pinned?: boolean;
Expand All @@ -90,12 +91,20 @@ const SidePanelComponent: FC<SidePanelProps> = ({
isOverlay,
isSplit = false,
loading = false,
hasError,
hasError = false,
className,
width,
pinned,
...props
}) => {
let content: ReactNode = null;
if (loading) {
content = <Loader />;
} else if (hasError) {
content = Label.ERROR_LOADING;
} else {
content = children;
}
return (
<AppAside
className={classnames(className, {
Expand All @@ -104,21 +113,11 @@ const SidePanelComponent: FC<SidePanelProps> = ({
"is-split": isSplit,
"is-overlay": isOverlay,
})}
aria-label="Side panel"
aria-label={Label.SIDE_PANEL}
pinned={pinned}
{...props}
>
{loading ? (
<div className="loading">
<Spinner />
</div>
) : (
<>
{loading && <Loader />}
{!loading && hasError && <>Loading failed</>}
{!hasError && children}
</>
)}
{content}
</AppAside>
);
};
Expand Down
4 changes: 4 additions & 0 deletions ui/src/components/SidePanel/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Label {
ERROR_LOADING = "Loading failed",
SIDE_PANEL = "Side panel",
}

0 comments on commit a2b87df

Please sign in to comment.