gradio-app--gradio
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
252 行
7.3 KiB
TypeScript
252 行
7.3 KiB
TypeScript
import { test, describe, assert, afterEach } from "vitest";
|
|
import { cleanup, fireEvent, render } from "@self/tootils/render";
|
|
import { setupi18n } from "../core/src/i18n";
|
|
|
|
import HighlightedText from "./Index.svelte";
|
|
import type { ILoadingStatus as 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"
|
|
};
|
|
|
|
describe("HighlightedText", () => {
|
|
afterEach(() => cleanup());
|
|
|
|
setupi18n();
|
|
|
|
test("renders provided text and labels", async () => {
|
|
const { getByText, getAllByText } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
value: [
|
|
{ token: "The", class_or_confidence: null },
|
|
{ token: "quick", class_or_confidence: "adjective" },
|
|
{ token: " sneaky", class_or_confidence: "adjective" },
|
|
{ token: "fox", class_or_confidence: "subject" },
|
|
{ token: " jumped ", class_or_confidence: "past tense verb" },
|
|
{ token: "over the", class_or_confidence: null },
|
|
{ token: "lazy dog", class_or_confidence: "object" }
|
|
]
|
|
});
|
|
|
|
const quick = getByText("quick");
|
|
const adjectiveLabels = getAllByText("adjective");
|
|
|
|
assert.exists(quick);
|
|
assert.exists(adjectiveLabels);
|
|
assert.equal(adjectiveLabels.length, 2);
|
|
});
|
|
|
|
test.skip("renders labels with remove label buttons which trigger change", async () => {
|
|
const { getAllByLabelText, listen } = await render(HighlightedText, {
|
|
interactive: true,
|
|
loading_status,
|
|
value: [
|
|
{ token: "The", class_or_confidence: null },
|
|
{ token: "quick", class_or_confidence: "adjective" },
|
|
{ token: " sneaky", class_or_confidence: "adjective" },
|
|
{ token: "fox", class_or_confidence: "subject" },
|
|
{ token: " jumped ", class_or_confidence: "past tense verb" },
|
|
{ token: "over the", class_or_confidence: null },
|
|
{ token: "lazy dog", class_or_confidence: "object" }
|
|
]
|
|
});
|
|
|
|
const mock = listen("change");
|
|
|
|
const removeButtons = getAllByLabelText("Remove label");
|
|
|
|
assert.equal(removeButtons.length, 5);
|
|
|
|
assert.equal(mock.callCount, 0);
|
|
|
|
fireEvent.click(removeButtons[0]);
|
|
|
|
assert.equal(mock.callCount, 1);
|
|
});
|
|
|
|
describe("Score mode", () => {
|
|
test("renders tokens with numeric confidence scores", async () => {
|
|
const { getByText, getByTestId } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
value: [
|
|
{ token: "good", class_or_confidence: 0.8 },
|
|
{ token: " ", class_or_confidence: 0 },
|
|
{ token: "bad", class_or_confidence: -0.6 }
|
|
]
|
|
});
|
|
|
|
const goodToken = getByText("good");
|
|
const badToken = getByText("bad");
|
|
|
|
assert.exists(goodToken);
|
|
assert.exists(badToken);
|
|
|
|
// Score mode should render the textfield
|
|
const textfield = getByTestId("highlighted-text:textfield");
|
|
assert.exists(textfield);
|
|
});
|
|
|
|
test("does not show category labels in score mode", async () => {
|
|
const { queryAllByText } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
value: [
|
|
{ token: "positive", class_or_confidence: 0.5 },
|
|
{ token: "negative", class_or_confidence: -0.5 }
|
|
]
|
|
});
|
|
|
|
// In score mode, the numeric values should not be displayed as labels
|
|
const labels = queryAllByText("0.5");
|
|
assert.equal(labels.length, 0);
|
|
});
|
|
});
|
|
|
|
describe("Legend", () => {
|
|
test("shows category legend when show_legend is true", async () => {
|
|
const { getByTestId, getByText } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
show_legend: true,
|
|
value: [
|
|
{ token: "Hello", class_or_confidence: "greeting" },
|
|
{ token: "world", class_or_confidence: "noun" }
|
|
]
|
|
});
|
|
|
|
const legend = getByTestId("highlighted-text:category-legend");
|
|
assert.exists(legend);
|
|
|
|
// Legend should contain category names
|
|
const greetingLegend = getByText("greeting");
|
|
const nounLegend = getByText("noun");
|
|
assert.exists(greetingLegend);
|
|
assert.exists(nounLegend);
|
|
});
|
|
|
|
test("shows score legend when show_legend is true in score mode", async () => {
|
|
const { getByTestId } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
show_legend: true,
|
|
value: [
|
|
{ token: "positive", class_or_confidence: 0.8 },
|
|
{ token: "negative", class_or_confidence: -0.5 }
|
|
]
|
|
});
|
|
|
|
const legend = getByTestId("highlighted-text:color-legend");
|
|
assert.exists(legend);
|
|
});
|
|
|
|
test("hides legend when show_legend is false", async () => {
|
|
const { queryByTestId } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
show_legend: false,
|
|
value: [{ token: "Hello", class_or_confidence: "greeting" }]
|
|
});
|
|
|
|
const legend = queryByTestId("highlighted-text:category-legend");
|
|
assert.isNull(legend);
|
|
});
|
|
});
|
|
|
|
describe("Select events", () => {
|
|
test.skip("dispatches select event when clicking highlighted token", async () => {
|
|
const { getByText, listen } = await render(HighlightedText, {
|
|
interactive: true,
|
|
loading_status,
|
|
value: [{ token: "clickable", class_or_confidence: "label" }]
|
|
});
|
|
|
|
const mock = listen("select");
|
|
const token = getByText("clickable");
|
|
|
|
await fireEvent.click(token);
|
|
|
|
assert.equal(mock.callCount, 1);
|
|
assert.deepEqual(mock.calls[0][0].detail.data, {
|
|
index: 0,
|
|
value: ["clickable", "label"]
|
|
});
|
|
});
|
|
|
|
test.skip("dispatches select event in non-interactive mode too", async () => {
|
|
const { getByText, listen } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
value: [{ token: "clickable", class_or_confidence: "label" }]
|
|
});
|
|
|
|
const mock = listen("select");
|
|
const token = getByText("clickable");
|
|
|
|
await fireEvent.click(token);
|
|
|
|
assert.equal(mock.callCount, 1);
|
|
});
|
|
});
|
|
|
|
describe("Interactive editing", () => {
|
|
test("shows label input when clicking on highlighted token in interactive mode", async () => {
|
|
const { getByText, container } = await render(HighlightedText, {
|
|
interactive: true,
|
|
loading_status,
|
|
value: [{ token: "editable", class_or_confidence: "original" }]
|
|
});
|
|
|
|
const token = getByText("editable");
|
|
await fireEvent.click(token);
|
|
|
|
// After clicking, an input should appear
|
|
const input = container.querySelector(".label-input");
|
|
assert.exists(input);
|
|
});
|
|
|
|
test.skip("updates label value when editing", async () => {
|
|
const { getByText, container, listen } = await render(HighlightedText, {
|
|
interactive: true,
|
|
loading_status,
|
|
value: [{ token: "editable", class_or_confidence: "original" }]
|
|
});
|
|
|
|
const changeMock = listen("change");
|
|
const token = getByText("editable");
|
|
await fireEvent.click(token);
|
|
|
|
const input = container.querySelector(".label-input") as HTMLInputElement;
|
|
assert.exists(input);
|
|
|
|
// Change the value
|
|
await fireEvent.input(input, { target: { value: "updated" } });
|
|
await fireEvent.blur(input);
|
|
|
|
assert.isAbove(changeMock.callCount, 0);
|
|
});
|
|
|
|
test("does not show label input in non-interactive mode", async () => {
|
|
const { getByText, container } = await render(HighlightedText, {
|
|
interactive: false,
|
|
loading_status,
|
|
value: [{ token: "not-editable", class_or_confidence: "label" }]
|
|
});
|
|
|
|
const token = getByText("not-editable");
|
|
await fireEvent.click(token);
|
|
|
|
const input = container.querySelector(".label-input");
|
|
assert.isNull(input);
|
|
});
|
|
});
|
|
});
|