Skip to content

Commit

Permalink
Merge pull request #46 from dolthub/taylor/updates
Browse files Browse the repository at this point in the history
components: Fix SmallLoader, unit tests
  • Loading branch information
tbantle22 authored Feb 15, 2024
2 parents d511e39 + c6d5d37 commit 47d18b1
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 5 deletions.
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@dolthub/react-components",
"author": "DoltHub",
"description": "A collection of React components for common tasks",
"version": "0.1.0",
"version": "0.1.1",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/Popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import ReactPopup from "reactjs-popup";
import "reactjs-popup/dist/index.css";
import { PopupProps } from "reactjs-popup/dist/types";
import type { PopupProps } from "reactjs-popup/dist/types.d";

export default function Popup(props: PopupProps) {
return (
Expand Down
6 changes: 3 additions & 3 deletions packages/components/src/SmallLoader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cx from "classnames";
import React from "react";
import React, { ReactNode } from "react";
import ReactLoader from "react-loader";
import css from "./index.module.css";

Expand Down Expand Up @@ -29,7 +29,7 @@ type Props = {
loaded: boolean;
className?: string;
options?: Partial<typeof smallLoaderDefaultOptions>;
tableLoader?: boolean;
children?: ReactNode;
};

export default function SmallLoader(props: Props) {
Expand All @@ -53,7 +53,7 @@ function WithText(props: WithTextProps) {
return (
<div className={cx(css.loading, props.outerClassName)}>
<SmallLoader {...props} />
<span>{props.text}</span>
{!props.loaded && <span>{props.text}</span>}
</div>
);
}
Expand Down
16 changes: 16 additions & 0 deletions packages/components/src/__tests__/Loader.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { render, screen } from "@testing-library/react";
import React from "react";
import Loader from "../Loader";

describe("test Loader", () => {
it("does not render child if loading", () => {
render(<Loader loaded={false}>Loading...</Loader>);
const el = screen.queryByText("Loading...");
expect(el).not.toBeInTheDocument();
});
it("does render child if not loading", () => {
render(<Loader loaded>Loading...</Loader>);
const el = screen.getByText("Loading...");
expect(el).toBeVisible();
});
});
228 changes: 228 additions & 0 deletions packages/components/src/__tests__/Popup.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import React from "react";
import Popup, { PopupProps } from "../Popup";

// Taken from https://github.com/yjose/reactjs-popup/blob/master/__test__/index.test.tsx

const SimplePopup = ({ ...props }: Partial<PopupProps>) => (
<Popup trigger={<button> trigger </button>} {...props}>
<span> popup Content </span>
</Popup>
);
const popupContentShouldntExist = () => {
expect(screen.queryByText(/popup Content/)).toBeNull();
};
const popupContentShouldExist = () => {
expect(screen.getByText(/popup Content/)).toBeInTheDocument();
};

describe("Popup Component Render ", () => {
test("should render trigger correctly", () => {
render(<SimplePopup />);
expect(screen.getByText(/trigger/)).toBeInTheDocument();
});

test("should be a tooltip by default", () => {
render(<SimplePopup />);
fireEvent.click(screen.getByText("trigger"));
expect(screen.getByRole("tooltip")).toBeInTheDocument();
});

test("no Arrow for modal", () => {
render(<SimplePopup modal />);
fireEvent.click(screen.getByText("trigger"));
expect(screen.getByRole("dialog")).toBeInTheDocument();
expect(screen.queryByTestId("arrow")).toBeNull();
});

test("no Arrow on arrow= false", () => {
render(<SimplePopup arrow={false} />);
fireEvent.click(screen.getByText("trigger"));
expect(screen.getByRole("tooltip")).toBeInTheDocument();
expect(screen.queryByTestId("arrow")).toBeNull();
});

test("should render a Modal on modal=true", () => {
render(<SimplePopup modal />);
fireEvent.click(screen.getByText("trigger"));
expect(screen.getByRole("dialog")).toBeInTheDocument();
});

test("it should be closed on disabled = true ", () => {
render(<SimplePopup disabled />);
popupContentShouldntExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
});
test("should be open by default on defaultOpen= true ", () => {
render(<SimplePopup defaultOpen />);
popupContentShouldExist();
});

test("should call onOpen & onClose functions ", async () => {
const onOpen = jest.fn();
const onClose = jest.fn();
render(<SimplePopup onOpen={onOpen} onClose={onClose} />);

fireEvent.click(screen.getByText("trigger"));
await waitFor(() => {
expect(onOpen).toHaveBeenCalled();
const [event] = onOpen.mock.calls[0];
expect("target" in event).toBe(true);
});
fireEvent.click(screen.getByText("trigger"));
await waitFor(() => {
expect(onClose).toHaveBeenCalled();
const [event] = onClose.mock.calls[0];
expect("target" in event).toBe(true);
});
// expect(screen.getByRole('tooltip')).toBeInTheDocument();
});

test("should be closed on Escape", async () => {
render(<SimplePopup />);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.keyUp(document, { key: "Escape", code: "Escape" });
popupContentShouldntExist();
});
test("shouldnt close on Escape if closeOnEscape=false", async () => {
render(<SimplePopup closeOnEscape={false} />);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.keyUp(document, { key: "Escape", code: "Escape" });
popupContentShouldExist();
});

test("should be closed on ClickOutside ", async () => {
render(<SimplePopup />);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.mouseDown(document);
popupContentShouldntExist();
});
test("shouldnt close on ClickOutside if closeOnDocumentClick=false", async () => {
render(<SimplePopup closeOnDocumentClick={false} />);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.mouseDown(document);
popupContentShouldExist();
});

test("should lock Document Scroll on lockScroll=true", async () => {
render(<SimplePopup lockScroll={true} modal />);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
expect(document.body).toHaveStyle(`overflow: hidden`);
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
expect(document.body).toHaveStyle(`overflow: auto`);
});
});

// test for "on" props status
describe('Popup Component with "on" Prop ', () => {
test("it should be opened only on Click as default value ", () => {
render(<SimplePopup />);
popupContentShouldntExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
});

test('it should be opened only on Click where on="click" ', () => {
render(<SimplePopup on="click" />);
popupContentShouldntExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
});
test('it should be opened only on Right-Click where on="right-click" ', () => {
render(<SimplePopup on="right-click" />);
popupContentShouldntExist();
fireEvent.contextMenu(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.contextMenu(screen.getByText("trigger"));
popupContentShouldntExist();
});
test('it should be opened only on Hover where on="hover" ', async () => {
render(<SimplePopup on="hover" />);
popupContentShouldntExist();
fireEvent.mouseOver(screen.getByText("trigger"));
await waitFor(
() => popupContentShouldExist(),
{ timeout: 120 }, // default delay = "100"
);
fireEvent.mouseLeave(screen.getByText("trigger"));

await waitFor(
() => expect(screen.queryByText(/popup Content/)).toBeNull(),
{ timeout: 120 },
);
// should not show on click
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
});
test('it should be opened only on Focus where on="focus" ', async () => {
render(<SimplePopup on="focus" />);
popupContentShouldntExist();
fireEvent.focus(screen.getByText("trigger"));
await waitFor(
() => popupContentShouldExist(),
{ timeout: 120 }, // default delay = "100"
);
fireEvent.blur(screen.getByText("trigger"));
await waitFor(() => popupContentShouldntExist(), { timeout: 120 });
// should not show content on click
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();
});
test('it should be opened on Focus & click & focus where on=["focus","click","hover"] ', async () => {
render(<SimplePopup on={["focus", "click", "hover"]} />);
popupContentShouldntExist();
// on focus
fireEvent.focus(screen.getByText("trigger"));
await waitFor(
() => popupContentShouldExist(),
{ timeout: 120 }, // default delay = "100"
);
fireEvent.blur(screen.getByText("trigger"));
await waitFor(() => popupContentShouldntExist(), { timeout: 120 });
// on click
fireEvent.click(screen.getByText("trigger"));
popupContentShouldExist();
fireEvent.click(screen.getByText("trigger"));
popupContentShouldntExist();

// on Hover
fireEvent.mouseOver(screen.getByText("trigger"));
await waitFor(
() => popupContentShouldExist(),
{ timeout: 120 }, // default delay = "100"
);
fireEvent.mouseLeave(screen.getByText("trigger"));

await waitFor(
() => expect(screen.queryByText(/popup Content/)).toBeNull(),
{ timeout: 120 },
);
});

test("should respect mouseEnterDelay mouseLeaveDelay on Hover ", async () => {
render(
<SimplePopup on="hover" mouseEnterDelay={800} mouseLeaveDelay={800} />,
);
popupContentShouldntExist();
fireEvent.mouseOver(screen.getByText("trigger"));
await waitFor(() => popupContentShouldntExist(), { timeout: 120 });
await waitFor(() => popupContentShouldExist(), { timeout: 1000 });
fireEvent.mouseLeave(screen.getByText("trigger"));

await waitFor(() => popupContentShouldExist(), { timeout: 120 });
await waitFor(() => popupContentShouldntExist(), { timeout: 1000 });
});
});
29 changes: 29 additions & 0 deletions packages/components/src/__tests__/SmallLoader.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { render, screen } from "@testing-library/react";
import React from "react";
import SmallLoader from "../SmallLoader";

describe("test SmallLoader", () => {
it("does not render child if loading", () => {
render(<SmallLoader loaded={false}>Loading...</SmallLoader>);
const el = screen.queryByText("Loading...");
expect(el).not.toBeInTheDocument();
});
it("does render child if not loading", () => {
render(<SmallLoader loaded>Loading...</SmallLoader>);
const el = screen.getByText("Loading...");
expect(el).toBeVisible();
});
});

describe("test SmallLoader.WithText", () => {
it("does render text if loading", () => {
render(<SmallLoader.WithText loaded={false} text="Loading..." />);
const el = screen.getByText("Loading...");
expect(el).toBeVisible();
});
it("does not render text if not loading", () => {
render(<SmallLoader.WithText loaded text="Loading..." />);
const el = screen.queryByText("Loading...");
expect(el).not.toBeInTheDocument();
});
});

0 comments on commit 47d18b1

Please sign in to comment.