Skip to content

Commit

Permalink
feat: add HealthCheckStatus component that accepts HealthCheck
Browse files Browse the repository at this point in the history
  • Loading branch information
mainawycliffe committed Oct 17, 2023
1 parent 5559521 commit d049ee9
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/components/HealthChecks/CheckLink.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Link } from "react-router-dom";
import { ComponentHealthCheckView } from "../../api/services/topology";
import { HealthCheck } from "../../types/healthChecks";
import { Icon } from "../Icon";
import { Status } from "../Status";
import { HealthCheckStatus } from "../Status/HealthCheckStatus";

type ComponentCheckLinkProps = {
componentCheck: ComponentHealthCheckView;
Expand All @@ -18,7 +19,7 @@ export function CheckLink({ componentCheck: check }: ComponentCheckLinkProps) {
>
<div className="flex flex-row gap-2 w-full items-center">
<div className="flex flex-row space-x-1 items-center flex-1text-sm ">
<Status good={check.status === "healthy"} />
<HealthCheckStatus check={check as Pick<HealthCheck, "status">} />
<Icon name={check.type} className="w-4 h-auto" />
<div className="overflow-hidden text-ellipsis flex-1">
{check.name}
Expand Down
48 changes: 48 additions & 0 deletions src/components/HealthChecks/__tests__/CheckLink.unit.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { CheckLink } from "./../CheckLink";
import { ComponentHealthCheckView } from "../../../api/services/topology";

describe("CheckLink", () => {
const check: ComponentHealthCheckView = {
id: "1",
name: "Example Check",
type: "example",
status: "healthy",
component_id: "1",
severity: "critical"
};

it("renders with healthy status", () => {
render(
<MemoryRouter>
<CheckLink componentCheck={check} />
</MemoryRouter>
);

const linkElement = screen.getByRole("link");
expect(linkElement).toHaveAttribute(
"href",
"/health?checkId=1&timeRange=1h"
);

const statusElement = screen.getByTestId("health-check-status");
expect(statusElement).toHaveClass("bg-green-400");

const nameElement = screen.getByText("Example Check");
expect(nameElement).toBeInTheDocument();
});

it("renders with unhealthy status", () => {
const unhealthyCheck = { ...check, status: "unhealthy" };

render(
<MemoryRouter>
<CheckLink componentCheck={unhealthyCheck} />
</MemoryRouter>
);

const statusElement = screen.getByTestId("health-check-status");
expect(statusElement).toHaveClass("bg-red-400");
});
});
41 changes: 41 additions & 0 deletions src/components/Status/HealthCheckStatus.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Meta, Story } from "@storybook/react";
import { HealthCheckStatus } from "./HealthCheckStatus";

type StatusProps = React.ComponentProps<typeof HealthCheckStatus>;

export default {
title: "Components/HealthCheckStatus",
component: HealthCheckStatus
} as Meta;

export const Default: Story<StatusProps> = (args) => (
<HealthCheckStatus {...args} />
);

export const Mixed: Story<StatusProps> = (args) => (
<HealthCheckStatus {...args} />
);

Mixed.args = {
isMixed: true
};

export const Healthy: Story<StatusProps> = (args) => (
<HealthCheckStatus {...args} />
);

Healthy.args = {
check: {
status: "healthy"
}
};

export const Unhealthy: Story<StatusProps> = (args) => (
<HealthCheckStatus {...args} />
);

Unhealthy.args = {
check: {
status: "unhealthy"
}
};
27 changes: 27 additions & 0 deletions src/components/Status/HealthCheckStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { HealthCheck } from "../../types/healthChecks";

type StatusProps = {
check?: Pick<HealthCheck, "status">;
isMixed?: boolean;
className?: string;
};

export function HealthCheckStatus({
check,
isMixed = false,
className = ""
}: StatusProps) {
const color = isMixed
? "bg-light-orange"
: check?.status === "healthy"
? "bg-green-400"
: "bg-red-400";
return (
<span
className={`flex-shrink-0 inline-block h-3 w-3 rounded-full shadow-md ${className} ${color}`}
aria-hidden="true"
// add test id
data-testid="health-check-status"
/>
);
}
52 changes: 52 additions & 0 deletions src/components/Status/__tests__/HealthCheckStatus.unit.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { render, screen } from "@testing-library/react";
import { HealthCheckStatus } from "./../HealthCheckStatus";

describe("HealthCheckStatus", () => {
const testCases = [
{
check: {
status: "healthy"
},
isMixed: false,
className: "",
expectedColor: "bg-green-400"
},
{
check: {
status: "unhealthy"
},
isMixed: false,
className: "",
expectedColor: "bg-red-400"
},
{
check: {
status: "unhealthy"
},
isMixed: true,
className: "",
expectedColor: "bg-light-orange"
},
{
check: undefined,
isMixed: false,
className: "bg-red-400",
expectedColor: "bg-red-400"
}
];

test.each(testCases)(
"renders with check=%o, isMixed=%p, className=%p",
({ check, isMixed, className, expectedColor }) => {
render(
<HealthCheckStatus
check={check as any}
isMixed={isMixed}
className={className}
/>
);
const statusElement = screen.getByTestId("health-check-status");
expect(statusElement).toHaveClass(`${expectedColor}`);
}
);
});

0 comments on commit d049ee9

Please sign in to comment.