122 lines
3.8 KiB
TypeScript
122 lines
3.8 KiB
TypeScript
import { expect, test } from "vitest";
|
|
import { h } from "preact";
|
|
import { render } from "preact-render-to-string";
|
|
import {
|
|
Alert,
|
|
Badge,
|
|
Button,
|
|
Checkbox,
|
|
Input,
|
|
Progress,
|
|
Select,
|
|
Tabs,
|
|
UrlPrefixInput,
|
|
} from "./index.ts";
|
|
|
|
test("Button primary emits both classes and merges consumer class", () => {
|
|
const html = render(h(Button, { variant: "primary", class: "x" }, "Ok"));
|
|
expect(html).toContain("sb-button sb-button-primary x");
|
|
expect(html).toContain(">Ok</button>");
|
|
expect(html).toContain('type="button"');
|
|
});
|
|
|
|
test("Button danger/icon variants", () => {
|
|
expect(render(h(Button, { variant: "danger" }, "D"))).toContain(
|
|
"sb-button-danger",
|
|
);
|
|
expect(render(h(Button, { variant: "icon" }, "I"))).toContain(
|
|
"sb-button-icon",
|
|
);
|
|
});
|
|
|
|
test("Input renders sb-input with default type text", () => {
|
|
const html = render(h(Input, { value: "hi" }));
|
|
expect(html).toContain('class="sb-input"');
|
|
expect(html).toContain('type="text"');
|
|
});
|
|
|
|
test("Input renders cleanly when onConfirm/onExit are provided", () => {
|
|
const html = render(
|
|
h(Input, { value: "hi", onConfirm: () => {}, onExit: () => {} }),
|
|
);
|
|
expect(html).toContain('class="sb-input"');
|
|
expect(html).toContain('value="hi"');
|
|
// Callback props must not leak as DOM attributes
|
|
expect(html).not.toContain("onConfirm");
|
|
expect(html).not.toContain("onExit");
|
|
});
|
|
|
|
test("Select wraps options", () => {
|
|
const html = render(h(Select, {}, h("option", {}, "A")));
|
|
expect(html).toContain('class="sb-select"');
|
|
expect(html).toContain(">A</option>");
|
|
});
|
|
|
|
test("Checkbox is a checkbox input", () => {
|
|
const html = render(h(Checkbox, { checked: true }));
|
|
expect(html).toContain('type="checkbox"');
|
|
expect(html).toContain("sb-checkbox");
|
|
});
|
|
|
|
test("Tabs marks the active tab and wires per-item onSelect", () => {
|
|
let picked = "";
|
|
const items = [
|
|
{ label: "A", active: false, onSelect: () => (picked = "a") },
|
|
{ label: "B", active: true, onSelect: () => (picked = "b") },
|
|
];
|
|
const html = render(h(Tabs, { items }));
|
|
expect(html).toContain("sb-tab sb-active");
|
|
expect(html).toContain('aria-selected="true"');
|
|
// each tab carries its own handler
|
|
items[0].onSelect();
|
|
expect(picked).toBe("a");
|
|
});
|
|
|
|
test("Alert variant class", () => {
|
|
expect(render(h(Alert, { variant: "error" }, "e"))).toContain(
|
|
"sb-alert sb-alert-error",
|
|
);
|
|
expect(render(h(Alert, { variant: "warning" }, "w"))).toContain(
|
|
"sb-alert-warning",
|
|
);
|
|
expect(render(h(Alert, { variant: "info" }, "i"))).toContain("sb-alert-info");
|
|
});
|
|
|
|
test("Badge", () => {
|
|
expect(render(h(Badge, {}, "b"))).toContain('class="sb-badge">b<');
|
|
});
|
|
|
|
test("Progress clamps value to a width percentage", () => {
|
|
expect(render(h(Progress, { value: 0.5 }))).toMatch(/width:\s*50%/);
|
|
expect(render(h(Progress, { value: 2 }))).toMatch(/width:\s*100%/);
|
|
expect(render(h(Progress, { value: -1 }))).toMatch(/width:\s*0%/);
|
|
});
|
|
|
|
test("UrlPrefixInput shows the origin it is given, not the ambient one", () => {
|
|
// The desktop app configures a *remote* sync server, so the origin cannot
|
|
// be read from `location` the way the server-hosted Space Manager does.
|
|
const html = render(
|
|
h(UrlPrefixInput, {
|
|
origin: "https://sb.example.com",
|
|
value: "/notes",
|
|
onInput: () => {},
|
|
}),
|
|
);
|
|
expect(html).toContain("sb-url-input");
|
|
expect(html).toContain(">https://sb.example.com</span>");
|
|
expect(html).toContain('value="/notes"');
|
|
});
|
|
|
|
test("UrlPrefixInput trims a trailing slash off the origin", () => {
|
|
// Sync server URLs are commonly stored with one; without trimming the
|
|
// assembled URL reads "https://h//notes".
|
|
const html = render(
|
|
h(UrlPrefixInput, {
|
|
origin: "https://sb.example.com/",
|
|
value: "/notes",
|
|
onInput: () => {},
|
|
}),
|
|
);
|
|
expect(html).toContain(">https://sb.example.com</span>");
|
|
});
|