Files
test/frontend/__tests__/components/common/Conditional.spec.tsx
Benjamin Falch 2bc741fb78
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled
adding monkeytype
2026-04-23 13:53:44 +02:00

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");
});
});
});