215 lines
6.4 KiB
TypeScript
215 lines
6.4 KiB
TypeScript
import { cleanup, render, screen } from "@solidjs/testing-library";
|
|
import { createSignal } from "solid-js";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
|
|
import { Conditional } from "../../../src/ts/components/common/Conditional";
|
|
|
|
describe("Conditional", () => {
|
|
afterEach(() => {
|
|
cleanup();
|
|
});
|
|
|
|
describe("static rendering", () => {
|
|
it("renders then when if is true", () => {
|
|
render(() => <Conditional if={true} then={<div>then content</div>} />);
|
|
|
|
expect(screen.getByText("then content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders then when if is a truthy object", () => {
|
|
render(() => (
|
|
<Conditional if={{ value: 42 }} then={<div>then content</div>} />
|
|
));
|
|
|
|
expect(screen.getByText("then content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders then when if is a truthy string", () => {
|
|
render(() => <Conditional if="hello" then={<div>then content</div>} />);
|
|
|
|
expect(screen.getByText("then content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders else fallback when if is false", () => {
|
|
render(() => (
|
|
<Conditional
|
|
if={false}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders else fallback when if is null", () => {
|
|
render(() => (
|
|
<Conditional
|
|
if={null}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders else fallback when if is undefined", () => {
|
|
render(() => (
|
|
<Conditional
|
|
if={undefined}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders else fallback when if is 0", () => {
|
|
render(() => (
|
|
<Conditional
|
|
if={0}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("renders nothing when if is falsy and else is not provided", () => {
|
|
const { container } = render(() => (
|
|
<Conditional if={false} then={<div>then content</div>} />
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(container.firstChild).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("then as function", () => {
|
|
it("passes the truthy value to then function", () => {
|
|
const obj: { label: string } | null = { label: "hello" };
|
|
render(() => (
|
|
<Conditional if={obj} then={(value) => <div>{value().label}</div>} />
|
|
));
|
|
|
|
expect(screen.getByText("hello")).toBeInTheDocument();
|
|
});
|
|
|
|
it("does not call then function when if is falsy", () => {
|
|
const obj: { label: string } | null = null;
|
|
render(() => (
|
|
<Conditional
|
|
if={obj}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe("reactivity", () => {
|
|
it("switches from else to then when if becomes truthy", async () => {
|
|
const [condition, setCondition] = createSignal(false);
|
|
|
|
render(() => (
|
|
<Conditional
|
|
if={condition()}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
|
|
setCondition(true);
|
|
|
|
expect(screen.getByText("then content")).toBeInTheDocument();
|
|
expect(screen.queryByText("else content")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("switches from then to else when if becomes falsy", async () => {
|
|
const [condition, setCondition] = createSignal(true);
|
|
|
|
render(() => (
|
|
<Conditional
|
|
if={condition()}
|
|
then={<div>then content</div>}
|
|
else={<div>else content</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.getByText("then content")).toBeInTheDocument();
|
|
|
|
setCondition(false);
|
|
|
|
expect(screen.queryByText("then content")).not.toBeInTheDocument();
|
|
expect(screen.getByText("else content")).toBeInTheDocument();
|
|
});
|
|
|
|
it("then JSXElement updates reactively when inner signal changes", async () => {
|
|
const [label, setLabel] = createSignal("initial");
|
|
|
|
render(() => <Conditional if={true} then={<div>{label()}</div>} />);
|
|
|
|
expect(screen.getByText("initial")).toBeInTheDocument();
|
|
|
|
setLabel("updated");
|
|
|
|
expect(screen.getByText("updated")).toBeInTheDocument();
|
|
});
|
|
|
|
it("then JSXElement updates reactively when if changes from a signal", async () => {
|
|
const [data, setData] = createSignal<string | undefined>(undefined);
|
|
|
|
render(() => (
|
|
<Conditional
|
|
if={data()}
|
|
then={<div data-testid="content">{data()}</div>}
|
|
else={<div>no data</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.getByText("no data")).toBeInTheDocument();
|
|
expect(screen.queryByTestId("content")).not.toBeInTheDocument();
|
|
|
|
setData("resolved");
|
|
|
|
expect(screen.getByTestId("content")).toHaveTextContent("resolved");
|
|
expect(screen.queryByText("no data")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("then function value accessor tracks reactive if", () => {
|
|
const [data, setData] = createSignal<{ name: string } | null>(null);
|
|
|
|
render(() => (
|
|
<Conditional
|
|
if={data()}
|
|
then={(value) => <div data-testid="content">{value().name}</div>}
|
|
else={<div>no data</div>}
|
|
/>
|
|
));
|
|
|
|
expect(screen.getByText("no data")).toBeInTheDocument();
|
|
|
|
setData({ name: "Alice" });
|
|
|
|
expect(screen.getByTestId("content")).toHaveTextContent("Alice");
|
|
|
|
setData({ name: "Bob" });
|
|
|
|
expect(screen.getByTestId("content")).toHaveTextContent("Bob");
|
|
});
|
|
});
|
|
});
|