Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend: Unit tests /components directory, convert to svg icons #8716

Merged
merged 17 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions cypress/integration/all/app/policiesflow.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,13 @@ describe("Policies flow (empty)", () => {
i: number,
expected: boolean[]
) => {
const check = expected[i] ? "compatible" : "incompatible";
const check = expected[i]
? "compatible-platform"
: "incompatible-platform";
const compatibility = expected[i] ? "compatible" : "incompatible";
assert(
el.children("img").attr("alt") === check,
`expected policy to be ${platforms[i]} ${check}`
el.children("div").attr("class").includes(check),
`expected policy to be ${platforms[i]} ${compatibility}`
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ const PlatformWrapper = ({
</p>
</div>
<RevealButton
baseClass={baseClass}
className={baseClass}
isShowing={showPlainOsquery}
hideText={"Plain osquery"}
showText={"Plain osquery"}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/BackLink/BackLink.tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("BackLink - component", () => {
render(<BackLink text="Back to software" />);

const text = screen.getByText("Back to software");
const icon = screen.getByTestId("Icon");
const icon = screen.getByTestId("icon");

expect(text).toBeInTheDocument();
expect(icon).toBeInTheDocument();
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/CustomLink/CustomLink.tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe("CustomLink - component", () => {
/>
);

const icon = screen.getByTestId("Icon");
const icon = screen.getByTestId("icon");

expect(icon).toBeInTheDocument();
expect(icon.closest("a")).toHaveAttribute("target", "_blank");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { screen } from "@testing-library/react";
import { renderWithSetup } from "test/testingUtils";

import EnrollSecretRow from "./EnrollSecretRow";

const TEAM_SECRET = {
secret: "super-secret-secret",
created_at: "",
team_id: 2,
};
describe("Enroll secret row", () => {
it("Hides secret by default and shows secret on click of eye icon", async () => {
const { user, container } = renderWithSetup(
<EnrollSecretRow secret={TEAM_SECRET} />
);

// Secret hidden by default
const secretHidden = container.querySelector("input");
expect(secretHidden?.type === "password").toBeTruthy();

// Click eye icon
const eyeIcon = screen.getByTestId("eye-icon");
await user.click(eyeIcon);

// Secret shown
const secretShown = container.querySelector("input");
expect(secretShown?.type === "text").toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ const EnrollSecretRow = ({
};

return (
<div className={`${baseClass}__secret`} key={uniqueId()}>
<div
className={`${baseClass}__secret`}
key={uniqueId()}
data-testid="osquery-secret"
>
<InputField
disabled
inputWrapperClass={`${baseClass}__secret-input`}
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const Icon = ({ name, color, direction, className, size }: IIconProps) => {
const IconComponent = ICON_MAP[name];

return (
<div className={classNames} data-testid="Icon">
<div className={classNames} data-testid="icon">
<IconComponent {...props} />
</div>
);
Expand Down
38 changes: 38 additions & 0 deletions frontend/components/LastUpdatedText/LastUpdatedText.tests.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { renderWithSetup } from "test/testingUtils";

import LastUpdatedText from "./LastUpdatedText";

describe("Last updated text", () => {
it("renders updated text", () => {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() - 2);
const twoDaysAgo = currentDate.toISOString();

render(
<LastUpdatedText whatToRetrieve="software" lastUpdatedAt={twoDaysAgo} />
);

const text = screen.getByText("Updated 2 days ago");

expect(text).toBeInTheDocument();
});
it("renders never if missing timestamp", () => {
render(<LastUpdatedText whatToRetrieve="software" />);

const text = screen.getByText("Updated never");

expect(text).toBeInTheDocument();
});

it("renders tooltip on hover", async () => {
const { user } = renderWithSetup(
<LastUpdatedText whatToRetrieve="software" />
);

await user.hover(screen.getByText("Updated never"));

expect(screen.getByText(/to retrieve software/i)).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion frontend/components/LastUpdatedText/LastUpdatedText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import TooltipWrapper from "components/TooltipWrapper";
const baseClass = "component__last-updated-text";

interface ILastUpdatedTextProps {
lastUpdatedAt: string;
lastUpdatedAt?: string;
whatToRetrieve: string;
}
const LastUpdatedText = ({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import { render, screen } from "@testing-library/react";

import PlatformCompatibility from "./PlatformCompatibility";

describe("Platform compatibility", () => {
it("renders compatible platforms", () => {
render(
<PlatformCompatibility
compatiblePlatforms={["macOS", "Windows"]}
error={null}
/>
);
const macCompatibility = screen.getByText("macOS").firstElementChild;
const windowsCompatibility = screen.getByText("Windows").firstElementChild;
const linuxCompatibility = screen.getByText("Linux").firstElementChild;

expect(macCompatibility).toHaveAttribute(
"class",
"icon compatible-platform"
);
expect(windowsCompatibility).toHaveAttribute(
"class",
"icon compatible-platform"
);
expect(linuxCompatibility).toHaveAttribute(
"class",
"icon incompatible-platform"
);
});
it("renders empty state", () => {
render(<PlatformCompatibility compatiblePlatforms={[]} error={null} />);

const text = screen.getByText(/No platforms/i);

expect(text).toBeInTheDocument();
});
it("renders error state", () => {
render(
<PlatformCompatibility
compatiblePlatforms={["macOS"]}
error={{ name: "Error", message: "The resource was not found." }}
/>
);

const text = screen.getByText(/possible syntax error/i);

expect(text).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { IOsqueryPlatform } from "interfaces/platform";
import { PLATFORM_DISPLAY_NAMES } from "utilities/constants";

import TooltipWrapper from "components/TooltipWrapper";
import CompatibleIcon from "../../../assets/images/icon-compatible-green-16x16@2x.png";
import IncompatibleIcon from "../../../assets/images/icon-incompatible-red-16x16@2x.png";
import Icon from "components/Icon";

interface IPlatformCompatibilityProps {
compatiblePlatforms: IOsqueryPlatform[] | null;
Expand Down Expand Up @@ -51,7 +50,10 @@ const PlatformCompatibility = ({
return (
<span className={baseClass}>
<b>
<TooltipWrapper tipContent="Estimated compatiblity based on <br /> the tables used in the query.">
<TooltipWrapper
tipContent="Estimated compatiblity based on <br /> the tables used in the query."
isDelayed
>
Compatible with:
</TooltipWrapper>
</b>
Expand Down Expand Up @@ -79,9 +81,12 @@ const PlatformCompatibility = ({
key={`platform-compatibility__${platform}`}
className="platform"
>
<img
alt={isCompatible ? "compatible" : "incompatible"}
src={isCompatible ? CompatibleIcon : IncompatibleIcon}
<Icon
name={isCompatible ? "check" : "ex"}
className={
isCompatible ? "compatible-platform" : "incompatible-platform"
}
color={isCompatible ? "status-success" : "status-error"}
/>
{platform}
</span>
Expand Down
12 changes: 5 additions & 7 deletions frontend/components/PlatformCompatibility/_styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
padding-top: $pad-medium;

b,
img,
svg,
span {
display: flex;
align-items: center;
Expand All @@ -17,12 +17,10 @@

.platform {
padding-left: 0px;
}

img {
height: 16px;
width: 16px;
padding-left: 12px;
padding-right: $pad-xsmall;
.icon {
padding-left: 12px;
padding-right: $pad-xsmall;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import { screen } from "@testing-library/react";
import { renderWithSetup } from "test/testingUtils";

import DropdownCell from "./DropdownCell";

const DROPDOWN_OPTIONS = [
{ disabled: false, label: "Edit", value: "edit-query" },
{ disabled: false, label: "Show query", value: "show-query" },
{ disabled: true, label: "Delete", value: "delete-query" },
];
const PLACEHOLDER = "Actions";
const ON_CHANGE = (value: string) => {
console.log(value);
};

describe("Dropdown cell", () => {
it("renders dropdown placeholder and options", async () => {
const { user } = renderWithSetup(
<DropdownCell
options={DROPDOWN_OPTIONS}
placeholder={PLACEHOLDER}
onChange={ON_CHANGE}
/>
);

await user.click(screen.getByText("Actions"));

expect(screen.getByText(/edit/i)).toBeInTheDocument();
expect(screen.getByText(/show query/i)).toBeInTheDocument();
expect(screen.getByText(/delete/i)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { screen } from "@testing-library/react";
import { createCustomRenderer } from "test/test-utils";

import IssueCell from "./IssueCell";

describe("Issue cell", () => {
it("renders icon, total issues, and failing policies tooltip", async () => {
const render = createCustomRenderer({});

const { user } = render(
<IssueCell
issues={{
total_issues_count: 4,
failing_policies_count: 2,
}}
rowId={1}
/>
);

const icon = screen.queryByTestId("icon");

await user.hover(screen.getByText("4"));

expect(screen.getByText(/failing policies/i)).toBeInTheDocument();
expect(icon).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from "react";
import ReactTooltip from "react-tooltip";
import { isEmpty } from "lodash";

import Icon from "components/Icon";

import IssueIcon from "../../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";

interface IIssueCellProps<T> {
Expand All @@ -25,7 +27,7 @@ const IssueCell = ({ issues, rowId }: IIssueCellProps<any>): JSX.Element => {
data-for={`host-issue__${rowId.toString()}`}
data-tip-disable={false}
>
<img alt="host issue" src={IssueIcon} />
<Icon name="issue" />
</span>
<ReactTooltip
place="top"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { screen } from "@testing-library/react";
import { renderWithSetup } from "test/testingUtils";
import PATHS from "router/paths";

import LinkCell from "./LinkCell";

const VALUE = "40 hosts";
describe("Link cell", () => {
it("renders text and path", async () => {
const { user } = renderWithSetup(
<LinkCell value={VALUE} path={PATHS.MANAGE_HOSTS} />
);

await user.click(screen.getByText("40 hosts"));

expect(window.location.pathname).toContain("/hosts");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { screen } from "@testing-library/react";
import { renderWithSetup } from "test/testingUtils";

import PillCell from "./PillCell";

const PERFORMANCE_IMPACT = { indicator: "Minimal", id: 3 };

describe("Pill cell", () => {
it("renders pill text and tooltip on hover", async () => {
const { user } = renderWithSetup(
<PillCell value={PERFORMANCE_IMPACT} hostDetails />
);

await user.hover(screen.getByText("Minimal"));

expect(screen.getByText(/little to no impact/i)).toBeInTheDocument();
});
});
Loading