Back to Repositories

Testing MultimodalTextbox Component Functionality in Gradio

This test suite validates the MultimodalTextbox component in the Gradio application, focusing on input handling and value updates. The tests ensure proper rendering of text values and verify dynamic text input functionality.

Test Coverage Overview

The test suite provides comprehensive coverage of the MultimodalTextbox component’s core functionality.

  • Validates initial text value rendering
  • Tests interactive text input handling
  • Verifies component state updates
  • Confirms event emission on value changes

Implementation Analysis

The tests utilize Vitest and Testing Library frameworks to implement component validation. The approach combines render testing with user event simulation, effectively testing both static and interactive states of the component.

Testing patterns include component mounting, event listening, and state verification using TypeScript type safety.

Technical Details

  • Testing Framework: Vitest
  • UI Testing: @testing-library/user-event
  • Component Framework: Svelte
  • Type System: TypeScript
  • Custom Utilities: @self/tootils

Best Practices Demonstrated

The test suite exemplifies several testing best practices for component validation.

  • Proper cleanup after each test
  • Type-safe component props
  • Isolated component testing
  • Event-driven interaction testing
  • Clear test case organization

gradio-app/gradio

js/multimodaltextbox/MultimodalTextbox.test.ts

            
import { test, describe, assert, afterEach } from "vitest";
import { cleanup, render } from "@self/tootils";
import event from "@testing-library/user-event";

import MultimodalTextbox 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"
};

describe("MultimodalTextbox", () => {
	afterEach(() => cleanup());

	test("renders provided value", async () => {
		const { getByDisplayValue } = await render(MultimodalTextbox, {
			show_label: true,
			max_lines: 1,
			loading_status,
			lines: 1,
			value: { text: "hello world", files: [] },
			label: "Textbox",
			interactive: false,
			root: ""
		});

		const item: HTMLInputElement = getByDisplayValue(
			"hello world"
		) as HTMLInputElement;
		assert.equal(item.value, "hello world");
	});

	test("changing the text should update the value", async () => {
		const { component, getByDisplayValue, listen } = await render(
			MultimodalTextbox,
			{
				show_label: true,
				max_lines: 10,
				loading_status,
				lines: 1,
				value: { text: "hi ", files: [] },
				label: "MultimodalTextbox",
				interactive: true,
				root: ""
			}
		);

		const item: HTMLInputElement = getByDisplayValue("hi") as HTMLInputElement;

		const mock = listen("change");

		item.focus();
		await event.keyboard("some text");

		assert.equal(item.value, "hi some text");
		assert.equal(component.value.text, "hi some text");
		assert.equal(mock.callCount, 9);
		assert.equal(mock.calls[8][0].detail.data.text, "hi some text");
		assert.equal(mock.calls[8][0].detail.data.files.length, 0);
	});
});