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

test: render with events utility refactoring #554

Merged
merged 7 commits into from
Dec 17, 2024
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
11 changes: 6 additions & 5 deletions src/tests/lib/components/Back.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import Back from "$lib/components/Back.svelte";
import { fireEvent, render } from "@testing-library/svelte";
import { fireEvent } from "@testing-library/svelte";
import { render } from "../../utils/render.test-utils";

describe("Back", () => {
it("should forward the click event", () =>
new Promise<void>((done) => {
const { getByTestId, component } = render(Back);

component.$on("nnsBack", () => {
done();
const { getByTestId } = render(Back, {
events: {
nnsBack: () => done(),
},
});

const button = getByTestId("back") as HTMLButtonElement;
Expand Down
11 changes: 6 additions & 5 deletions src/tests/lib/components/Card.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Card from "$lib/components/Card.svelte";
import { fireEvent, render } from "@testing-library/svelte";
import { fireEvent } from "@testing-library/svelte";
import { render } from "../../utils/render.test-utils";

describe("Card", () => {
it("should render an article", () => {
Expand Down Expand Up @@ -34,10 +35,10 @@ describe("Card", () => {

it("should forward the click event", () =>
new Promise<void>((done) => {
const { container, component } = render(Card);

component.$on("click", () => {
done();
const { container } = render(Card, {
events: {
click: () => done(),
},
});

const article = container.querySelector("article");
Expand Down
45 changes: 26 additions & 19 deletions src/tests/lib/components/Checkbox.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Checkbox from "$lib/components/Checkbox.svelte";
import { fireEvent, render } from "@testing-library/svelte";
import { fireEvent } from "@testing-library/svelte";
import { render } from "../../utils/render.test-utils";

describe("Checkbox", () => {
const props: { inputId: string; checked: boolean } = {
Expand Down Expand Up @@ -63,12 +64,11 @@ describe("Checkbox", () => {

it("should trigger select on container", () =>
new Promise<void>((done) => {
const { container, component } = render(Checkbox, {
const { container } = render(Checkbox, {
props,
});

component.$on("nnsChange", () => {
done();
events: {
nnsChange: () => done(),
},
});

const div: HTMLDivElement | null =
Expand All @@ -79,12 +79,11 @@ describe("Checkbox", () => {

it("should trigger select on input", () =>
new Promise<void>((done) => {
const { container, component } = render(Checkbox, {
const { container } = render(Checkbox, {
props,
});

component.$on("nnsChange", () => {
done();
events: {
nnsChange: () => done(),
},
});

const input: HTMLInputElement | null = container.querySelector("input");
Expand Down Expand Up @@ -114,25 +113,33 @@ describe("Checkbox", () => {

it("should not trigger nnsChange event when disabled and clicked", async () => {
const mockChange = vi.fn();
const { container, component } = render(Checkbox, {
props: { ...props, disabled: true },
const { container } = render(Checkbox, {
props: {
...props,
disabled: true,
},
events: {
nnsChange: mockChange,
},
});

component.$on("nnsChange", mockChange);

await fireEvent.click(container.querySelector("div.checkbox") as Element);

expect(mockChange).not.toHaveBeenCalled();
});

it("should not trigger nnsChange event when disabled and key pressed", async () => {
const mockChange = vi.fn();
const { container, component } = render(Checkbox, {
props: { ...props, disabled: true },
const { container } = render(Checkbox, {
props: {
...props,
disabled: true,
},
events: {
nnsChange: mockChange,
},
});

component.$on("nnsChange", mockChange);

await fireEvent.keyPress(
container.querySelector("div.checkbox") as Element,
{
Expand Down
35 changes: 21 additions & 14 deletions src/tests/lib/components/Collapsible.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fireEvent } from "@testing-library/dom";
import { render } from "@testing-library/svelte";
import { tick } from "svelte";
import { render } from "../../utils/render.test-utils";
import CollapsibleTest from "./CollapsibleTest.svelte";

// props
Expand Down Expand Up @@ -111,13 +111,14 @@ describe("Collapsible", () => {
});

it("should not toggle if external toggle", async () => {
const { getByTestId, container, component } = render(
CollapsibleTest,
props({ externalToggle: true }),
);

const spyToggle = vi.fn();
component.$on("nnsToggle", spyToggle);

const { getByTestId, container } = render(CollapsibleTest, {
...props({ externalToggle: true }),
events: {
nnsToggle: spyToggle,
},
});

fireEvent.click(getByTestId("collapsible-header"));
await tick();
Expand All @@ -128,20 +129,26 @@ describe("Collapsible", () => {
expect(spyToggle).not.toHaveBeenCalled();
});

it("should emit state update", async () => {
const { getByTestId, component } = render(CollapsibleTest);
await new Promise((resolve) => {
it("should emit state update", () =>
new Promise<void>((done) => {
let callIndex = 0;

component.$on("nnsToggle", ({ detail }) => {
const onToggle = ({ detail }: CustomEvent<{ expanded: boolean }>) => {
expect(detail.expanded).toBe(callIndex++ % 2 === 0);
if (callIndex >= 4) resolve(undefined);
if (callIndex >= 4) {
done();
}
};

const { getByTestId } = render(CollapsibleTest, {
events: {
nnsToggle: onToggle,
},
});

fireEvent.click(getByTestId("collapsible-header"));
fireEvent.click(getByTestId("collapsible-header"));
fireEvent.click(getByTestId("collapsible-header"));
fireEvent.click(getByTestId("collapsible-header"));
});
});
}));
});
53 changes: 27 additions & 26 deletions src/tests/lib/components/Modal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { startBusy } from "$lib";
import Modal from "$lib/components/Modal.svelte";
import { fireEvent, render } from "@testing-library/svelte";
import { fireEvent } from "@testing-library/svelte";
import { render } from "../../utils/render.test-utils";
import ModalTest from "./ModalTest.svelte";

describe("Modal", () => {
Expand Down Expand Up @@ -109,12 +110,11 @@ describe("Modal", () => {

it("should trigger close modal on click on backdrop", () =>
new Promise<void>((done) => {
const { container, component } = render(Modal, {
const { container } = render(Modal, {
props,
});

component.$on("nnsClose", () => {
done();
events: {
nnsClose: () => done(),
},
});

const backdrop: HTMLDivElement | null =
Expand All @@ -124,41 +124,42 @@ describe("Modal", () => {

it("should trigger close modal on Esc", () =>
new Promise<void>((done) => {
const { container, component } = render(Modal, {
const { container } = render(Modal, {
props,
});

component.$on("nnsClose", () => {
done();
events: {
nnsClose: () => done(),
},
});

fireEvent.keyDown(container, { key: "Escape" });
}));

it("should not close modal on not Esc keypress", () => {
const { container, component } = render(Modal, {
const { container } = render(Modal, {
props,
});

component.$on("nnsClose", () => {
throw new Error("Should not close modal");
events: {
nnsClose: () => {
throw new Error("Should not close modal");
},
},
});

fireEvent.keyDown(container, { key: "Enter" });
fireEvent.keyDown(container, { key: "Backspace" });
});

it("should not close modal on Esc when busy = true", () => {
const { container, component } = render(Modal, {
const { container } = render(Modal, {
props,
events: {
nnsClose: () => {
throw new Error("Should not close modal");
},
},
});

startBusy({ initiator: "stake-neuron" });

component.$on("nnsClose", () => {
throw new Error("Should not close modal");
});

fireEvent.keyDown(container, { key: "Escape" });
});

Expand Down Expand Up @@ -191,12 +192,12 @@ describe("Modal", () => {

it("should trigger close modal on click on close button", () =>
new Promise<void>((done) => {
const { getByTestId, component } = render(ModalTest, {
const { getByTestId } = render(ModalTest, {
props,
});

component.$on("nnsClose", () => {
done();
// TODO: remove once events is migrated to props
events: {
nnsClose: () => done(),
},
});

const button: HTMLElement | null = getByTestId("close-modal");
Expand Down
15 changes: 10 additions & 5 deletions src/tests/lib/components/Toggle.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Toggle from "$lib/components/Toggle.svelte";
import { fireEvent, render } from "@testing-library/svelte";
import { fireEvent } from "@testing-library/svelte";
import { render } from "../../utils/render.test-utils";

describe("Toggle", () => {
const props = {
Expand Down Expand Up @@ -49,12 +50,16 @@ describe("Toggle", () => {
});

it("should toggle checked", () => {
const { component, container } = render(Toggle, { props });
const onToggle = vi.fn();

const input = container.querySelector("input") as HTMLInputElement;
const { container } = render(Toggle, {
props,
events: {
nnsToggle: onToggle,
},
});

const onToggle = vi.fn();
component.$on("nnsToggle", onToggle);
const input = container.querySelector("input") as HTMLInputElement;

fireEvent.click(input);

Expand Down
23 changes: 23 additions & 0 deletions src/tests/utils/render.test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
render as svelteRender,
type RenderResult,
} from "@testing-library/svelte";
import type { ComponentProps, ComponentType, SvelteComponent } from "svelte";

export const render = <C extends SvelteComponent>(
cmp: ComponentType<C>,
options?: {
props?: ComponentProps<C>;
peterpeterparker marked this conversation as resolved.
Show resolved Hide resolved
events?: Record<string, ($event: CustomEvent) => void>;
},
): RenderResult<C> => {
const { component, ...rest } = svelteRender(cmp, { props: options?.props });

const events = Object.entries(options?.events ?? {});

events.forEach(([event, fn]) => {
component.$on(event, fn);
});

return { component, ...rest };
};
Loading