Back to Repositories

Testing Image Editor Event Handling Implementation in Gradio

This test suite validates image editor event handling in Gradio’s interface, covering upload, draw, erase, and save functionality. The tests ensure proper event triggering and state management for the image editor component.

Test Coverage Overview

The test suite provides comprehensive coverage of image editor events including:

  • File upload events and validation
  • Drawing tool interactions and event emission
  • Erase functionality and associated events
  • Save/Apply action event handling
  • Event counter validation for input and change events

Implementation Analysis

The tests utilize Playwright’s page object model for UI interaction testing. The implementation follows an event-driven approach, verifying both user actions and corresponding state updates through event counters. The testing pattern demonstrates clear separation of concerns between action triggers and assertions.

Technical Details

  • Testing Framework: Playwright
  • Custom Utilities: drag_and_drop_file
  • Test Scope: Component-level event handling
  • Key Methods: page.locator(), expect(), click(), setInputFiles()
  • Test Assets: Sample image files for upload testing

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases for each event type
  • Consistent assertion patterns
  • Clear test descriptions
  • Proper element selection using labels and selectors
  • Verification of both user actions and system responses

gradio-app/gradio

js/spa/test/image_editor_events.spec.ts

            
import { test, expect, drag_and_drop_file } from "@self/tootils";

test("upload events work as expected", async ({ page }) => {
	await page.getByLabel("Upload button").first().click();
	const uploader = page.locator("input[type=file]").first();
	await uploader.setInputFiles(["./test/files/cheetah1.jpg"]);

	await expect(page.locator("#upload h2")).toContainText("1");
});

test("change events work as expected", async ({ page }) => {
	const change_text = page.locator("#change h2");

	await page.getByLabel("Draw button").click();
	await page.getByLabel("Draw button").click();
	const canvas = page.locator("canvas");
	await canvas.click({ position: { x: 100, y: 100 } });
	await expect(change_text).toContainText("1");
});

test("input events work as expected", async ({ page }) => {
	const input_text = page.locator("#input h2");

	await page.getByLabel("Draw button").click();
	await page.getByLabel("Draw button").click();
	const canvas = page.locator("canvas");
	await canvas.click({ position: { x: 100, y: 100 } });
	await expect(input_text).toContainText("1");
});

test("erase triggers change and input events", async ({ page }) => {
	const canvas = page.locator("canvas");
	const input_text = page.locator("#input h2");
	const change_text = page.locator("#change h2");

	await page.getByLabel("Erase button").click();
	await canvas.click({ position: { x: 50, y: 50 } });
	await expect(input_text).toContainText("1");
	await expect(change_text).toContainText("1");
});

test("apply events work as expected", async ({ page }) => {
	const apply_text = page.locator("#apply h2");
	const apply_button = page.getByLabel("Save changes").first();

	await page.getByLabel("Draw button").first().click();
	await page.getByLabel("Draw button").first().click();
	const canvas = page.locator("canvas").first();
	await canvas.click({ position: { x: 100, y: 100 } });
	await apply_button.click();
	await expect(apply_text).toContainText("1");
});