Files
wehub-resource-sync adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:17:32 +08:00

270 lines
7.5 KiB
TypeScript

import { test, describe, afterEach, expect } from "vitest";
import { cleanup, render, fireEvent, waitFor } from "@self/tootils/render";
import { run_shared_prop_tests } from "@self/tootils/shared-prop-tests";
import event from "@testing-library/user-event";
import DateTime from "./Index.svelte";
import { tick } from "svelte";
const default_props = {
show_label: true,
value: "2020-10-15 12:30:00",
label: "DateTime",
include_time: true,
interactive: true
};
run_shared_prop_tests({
component: DateTime,
name: "DateTime",
base_props: { value: "", include_time: true, interactive: true },
// DateTime dispatches a bare 'change' with no payload and does not render
// a validation_error element; disable the shared validation error test.
has_validation_error: false
});
describe("DateTime", () => {
afterEach(() => cleanup());
test("renders the provided value in the input", async () => {
const { getByDisplayValue } = await render(DateTime, {
...default_props,
value: "2020-10-15 12:30:00"
});
const input = getByDisplayValue("2020-10-15 12:30:00") as HTMLInputElement;
expect(input.value).toBe("2020-10-15 12:30:00");
});
test("null value renders an empty input", async () => {
const { getByRole } = await render(DateTime, {
...default_props,
value: null
});
const input = getByRole("textbox") as HTMLInputElement;
expect(input.value).toBe("");
});
test("empty string value renders an empty input", async () => {
const { getByRole } = await render(DateTime, {
...default_props,
value: ""
});
const input = getByRole("textbox") as HTMLInputElement;
expect(input.value).toBe("");
});
});
describe("Props: include_time", () => {
afterEach(() => cleanup());
test("include_time=true shows YYYY-MM-DD HH:MM:SS placeholder", async () => {
const { getByPlaceholderText } = await render(DateTime, {
...default_props,
value: "",
include_time: true
});
expect(getByPlaceholderText("YYYY-MM-DD HH:MM:SS")).toBeTruthy();
});
test("include_time=false shows YYYY-MM-DD placeholder", async () => {
const { getByPlaceholderText } = await render(DateTime, {
...default_props,
value: "",
include_time: false
});
expect(getByPlaceholderText("YYYY-MM-DD")).toBeTruthy();
});
test("include_time=false renders a date-only value correctly", async () => {
const { getByDisplayValue } = await render(DateTime, {
...default_props,
value: "2020-10-15",
include_time: false
});
expect(getByDisplayValue("2020-10-15")).toBeTruthy();
});
});
describe("Props: interactive", () => {
afterEach(() => cleanup());
test("interactive=true enables the input", async () => {
const { getByRole } = await render(DateTime, {
...default_props,
interactive: true
});
expect(getByRole("textbox")).toBeEnabled();
});
test("interactive=false disables the input", async () => {
const { getByRole } = await render(DateTime, {
...default_props,
interactive: false
});
expect(getByRole("textbox")).toBeDisabled();
});
test("interactive=true renders the calendar button", async () => {
const { getByRole } = await render(DateTime, {
...default_props,
interactive: true
});
expect(getByRole("button")).toBeTruthy();
});
test("interactive=false hides the calendar button", async () => {
const { queryByRole } = await render(DateTime, {
...default_props,
interactive: false
});
expect(queryByRole("button")).toBeNull();
});
test.todo(
"VISUAL: interactive=false applies subdued/disabled styling to the component — needs Playwright visual regression"
);
});
describe("Props: info", () => {
afterEach(() => cleanup());
test("info text is rendered when provided", async () => {
const { getByText } = await render(DateTime, {
...default_props,
info: "Enter a date and time"
});
await waitFor(() => {
expect(getByText("Enter a date and time")).toBeTruthy();
});
});
test("info text is not rendered when not provided", async () => {
const { queryByText } = await render(DateTime, {
...default_props,
info: undefined
});
expect(queryByText("Enter a date and time")).toBeNull();
});
});
describe("Edge cases", () => {
afterEach(() => cleanup());
test("no spurious change event on mount", async () => {
const { listen } = await render(DateTime, {
...default_props,
value: "2020-10-15 12:30:00"
});
const change = listen("change", { retrospective: true });
await tick();
await tick();
expect(change).not.toHaveBeenCalled();
});
test("setting the same value twice fires change only once", async () => {
const { listen, set_data } = await render(DateTime, {
...default_props,
value: ""
});
const change = listen("change");
await set_data({ value: "2021-05-20 09:00:00" });
await set_data({ value: "2021-05-20 09:00:00" });
expect(change).toHaveBeenCalledTimes(1);
});
test.todo(
"VISUAL: invalid format input turns the text subdued — needs Playwright visual regression screenshot comparison"
);
});
describe("Events", () => {
afterEach(() => cleanup());
test("change: emitted when value is updated via set_data", async () => {
const { listen, set_data } = await render(DateTime, default_props);
const change = listen("change");
await set_data({ value: "2021-05-20 09:00:00" });
expect(change).toHaveBeenCalledTimes(1);
});
test("change: dispatched without a payload (value is accessed via get_data)", async () => {
// DateTime's change event has no payload — the new value is read via get_data.
const { listen, set_data, get_data } = await render(
DateTime,
default_props
);
const change = listen("change");
await set_data({ value: "2021-05-20 09:00:00" });
expect(change).toHaveBeenCalledTimes(1);
const data = await get_data();
expect(data.value).toBe("2021-05-20 09:00:00");
});
test("submit: emitted when Enter is pressed in the input with a new valid value", async () => {
const { getByRole, listen } = await render(DateTime, {
...default_props,
value: ""
});
const submit = listen("submit");
const input = getByRole("textbox");
input.focus();
// Type a valid date then press Enter
await event.type(input, "2021-05-20 09:00:00");
await event.keyboard("{Enter}");
expect(submit).toHaveBeenCalledTimes(1);
});
test("change: emitted on blur when a new valid value has been typed", async () => {
const { getByRole, listen } = await render(DateTime, {
...default_props,
value: ""
});
const change = listen("change");
const input = getByRole("textbox");
input.focus();
await event.type(input, "2021-05-20 09:00:00");
input.blur();
await fireEvent.blur(input);
await waitFor(() => {
expect(change).toHaveBeenCalled();
});
});
});
describe("get_data / set_data", () => {
afterEach(() => cleanup());
test("get_data returns the initial value", async () => {
const { get_data } = await render(DateTime, {
...default_props,
value: "2020-10-15 12:30:00"
});
const data = await get_data();
expect(data.value).toBe("2020-10-15 12:30:00");
});
test("set_data updates the displayed value in the input", async () => {
const { set_data, getByRole } = await render(DateTime, {
...default_props,
value: ""
});
await set_data({ value: "2021-05-20 09:00:00" });
const input = getByRole("textbox") as HTMLInputElement;
expect(input.value).toBe("2021-05-20 09:00:00");
});
test("set_data → get_data round-trip returns the set value", async () => {
const { set_data, get_data } = await render(DateTime, {
...default_props,
value: ""
});
await set_data({ value: "2021-05-20 09:00:00" });
const data = await get_data();
expect(data.value).toBe("2021-05-20 09:00:00");
});
});