mirror of
https://github.com/gradio-app/gradio.git
synced 2024-12-21 02:19:59 +08:00
405 lines
10 KiB
TypeScript
405 lines
10 KiB
TypeScript
|
import { test, describe, assert, afterEach, vi } from "vitest";
|
||
|
import { cleanup, render } from "@gradio/tootils";
|
||
|
import event from "@testing-library/user-event";
|
||
|
import { setupi18n } from "../app/src/i18n";
|
||
|
|
||
|
import CheckboxGroup from "./Index.svelte";
|
||
|
import type { LoadingStatus } from "@gradio/statustracker";
|
||
|
|
||
|
const loading_status: LoadingStatus = {
|
||
|
eta: 0,
|
||
|
queue_position: 1,
|
||
|
queue_size: 1,
|
||
|
status: "complete" as LoadingStatus["status"],
|
||
|
scroll_to_output: false,
|
||
|
visible: true,
|
||
|
fn_index: 0,
|
||
|
show_progress: "full"
|
||
|
};
|
||
|
|
||
|
beforeEach(() => {
|
||
|
setupi18n();
|
||
|
});
|
||
|
|
||
|
afterEach(cleanup);
|
||
|
|
||
|
describe("Values", () => {
|
||
|
test("renders correct value when passed as string: single value", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: ["choice_one"],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", "choice_one"],
|
||
|
["Choice Two", "choice_two"]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("renders correct value when passed as string: multiple values", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: ["choice_one", "choice_three"],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", "choice_one"],
|
||
|
["Choice Two", "choice_two"],
|
||
|
["Choice Three", "choice_three"]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
assert.equal(item_one.checked, true);
|
||
|
assert.equal(item_two.checked, false);
|
||
|
assert.equal(item_three.checked, true);
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("renders correct value when passed as number: single value", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: [1],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("renders correct value when passed as number: multiple values", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: [1, 3],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("component value and rendered value are in sync", async () => {
|
||
|
const { getByLabelText, debug, component } = await render(CheckboxGroup, {
|
||
|
value: [1, 3],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).toBeChecked();
|
||
|
|
||
|
expect(component.value).toEqual([1, 3]);
|
||
|
});
|
||
|
|
||
|
test("changing the component value updates the checkboxes", async () => {
|
||
|
const { getByLabelText, debug, component } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).not.toBeChecked();
|
||
|
|
||
|
component.value = [1, 3];
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("setting a value that does not exist does nothing", async () => {
|
||
|
const { getByLabelText, component } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).not.toBeChecked();
|
||
|
|
||
|
component.value = ["choice_one"];
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).not.toBeChecked();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("Events", () => {
|
||
|
test("changing the value via the UI emits a change event", async () => {
|
||
|
const { getByLabelText, listen } = await render(CheckboxGroup, {
|
||
|
loading_status,
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).not.toBeChecked();
|
||
|
|
||
|
const mock = listen("change");
|
||
|
|
||
|
await event.click(item_one);
|
||
|
expect(mock.callCount).toBe(1);
|
||
|
|
||
|
await event.click(item_three);
|
||
|
expect(mock.callCount).toBe(2);
|
||
|
});
|
||
|
|
||
|
test("changing the value from outside emits a change event", async () => {
|
||
|
const { getByLabelText, component, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
const item_two = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
const item_three = getByLabelText("Choice Three") as HTMLInputElement;
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
expect(item_two).not.toBeChecked();
|
||
|
expect(item_three).not.toBeChecked();
|
||
|
|
||
|
const mock = listen("change");
|
||
|
|
||
|
await (component.value = [1]);
|
||
|
expect(mock.callCount).toBe(1);
|
||
|
});
|
||
|
|
||
|
test("changing the value from the UI emits an input event", async () => {
|
||
|
const { getByLabelText, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
const mock = listen("input");
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(mock.callCount).toBe(1);
|
||
|
});
|
||
|
|
||
|
test("changing the value from outside DOES NOT emit an input event", async () => {
|
||
|
const { getByLabelText, component, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const mock = listen("input");
|
||
|
await (component.value = [1]);
|
||
|
|
||
|
expect(mock.callCount).toBe(0);
|
||
|
});
|
||
|
|
||
|
test("changing the value via the UI emits a select event", async () => {
|
||
|
const { getByLabelText, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
const mock = listen("select");
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(mock.callCount).toBe(1);
|
||
|
});
|
||
|
|
||
|
test("select event payload contains the selected value and index", async () => {
|
||
|
const { getByLabelText, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", "val"],
|
||
|
["Choice Two", "val_two"],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
|
||
|
const mock = listen("select");
|
||
|
await event.click(item);
|
||
|
|
||
|
expect(mock.calls[0][0].detail.data.value).toBe("val_two");
|
||
|
expect(mock.calls[0][0].detail.data.index).toBe(1);
|
||
|
});
|
||
|
|
||
|
test("select event payload contains the correct selected state", async () => {
|
||
|
const { getByLabelText, listen } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
choices: [
|
||
|
["Choice One", "val"],
|
||
|
["Choice Two", "val_two"],
|
||
|
["Choice Three", 3]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item = getByLabelText("Choice Two") as HTMLInputElement;
|
||
|
|
||
|
const mock = listen("select");
|
||
|
|
||
|
await event.click(item);
|
||
|
expect(mock.calls[0][0].detail.data.selected).toBe(true);
|
||
|
|
||
|
await event.click(item);
|
||
|
expect(mock.calls[1][0].detail.data.selected).toBe(false);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("interactive vs static", () => {
|
||
|
test("interactive component can be checked", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
interactive: true,
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(item_one).toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("static component cannot be checked", async () => {
|
||
|
const { getByLabelText } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
interactive: false,
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(item_one).not.toBeChecked();
|
||
|
});
|
||
|
|
||
|
test("interactive component updates the value", async () => {
|
||
|
const { getByLabelText, component } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
interactive: true,
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(component.value).toEqual([1]);
|
||
|
});
|
||
|
|
||
|
test("static component doe not update the value", async () => {
|
||
|
const { getByLabelText, component } = await render(CheckboxGroup, {
|
||
|
value: [],
|
||
|
label: "Dropdown",
|
||
|
interactive: false,
|
||
|
choices: [
|
||
|
["Choice One", 1],
|
||
|
["Choice Two", 2]
|
||
|
]
|
||
|
});
|
||
|
|
||
|
const item_one = getByLabelText("Choice One") as HTMLInputElement;
|
||
|
|
||
|
await event.click(item_one);
|
||
|
|
||
|
expect(component.value).toEqual([]);
|
||
|
});
|
||
|
});
|