This commit is contained in:
214
frontend/__tests__/components/common/Conditional.spec.tsx
Normal file
214
frontend/__tests__/components/common/Conditional.spec.tsx
Normal file
@@ -0,0 +1,214 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user