Back to Repositories

Validating Event Chain and Toast Notification Workflows in Gradio

This test suite validates chained event handling and toast notifications in the Gradio application. It covers success event propagation, error handling, and various toast message types through comprehensive UI interaction tests.

Test Coverage Overview

The test suite provides thorough coverage of event chaining and notification systems in Gradio.

Key areas tested include:
  • Success event propagation and validation
  • Error handling and toast notifications
  • Consecutive event triggering
  • Different toast message types (Error, Warning, Info)

Implementation Analysis

Tests utilize Playwright’s page object model for UI interaction testing. The implementation follows an async/await pattern with explicit expectations for UI state verification.

Key patterns include:
  • Element selection using accessibility labels
  • Toast notification handling and verification
  • State change validation through value assertions

Technical Details

Testing stack includes:
  • Playwright for browser automation
  • Custom @self/tootils testing utilities
  • TestId-based element selection
  • Async test execution environment

Best Practices Demonstrated

The test suite exemplifies robust testing practices for UI applications.

Notable practices include:
  • Isolated test cases for specific functionality
  • Proper cleanup of UI elements (toast dismissal)
  • Consistent assertion patterns
  • Clear test case naming conventions

gradio-app/gradio

js/spa/test/blocks_chained_events.spec.ts

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

test(".success should not run if function fails", async ({ page }) => {
	const textbox = page.getByLabel("Result");
	await expect(textbox).toHaveValue("");

	await page.click("text=Trigger Failure");
	expect(textbox).toHaveValue("");
});

test(".success event runs after function successfully completes", async ({
	page
}) => {
	const textbox = page.getByLabel("Result");
	await page.click("text=Trigger Success");
	await expect(textbox).toHaveValue("Success event triggered");
});

test("Consecutive .success event is triggered successfully", async ({
	page
}) => {
	const textbox = page.getByLabel("Consecutive Event");
	const first = page.getByLabel("Result");

	await page.click("text=Trigger Consecutive Success");
	await expect(textbox).toHaveValue("Consecutive Event Triggered");
	expect(first).toHaveValue("First Event Trigered");
});

test("gr.Error makes the toast show up", async ({ page }) => {
	await page.click("text=Trigger Failure");

	const toast = page.getByTestId("toast-body");
	expect(toast).toContainText("Error");
	const close = page.getByTestId("toast-close");
	await close.click();
	await expect(page.getByTestId("toast-body")).toHaveCount(0);
});

test("ValueError makes the toast show up when show_error=True", async ({
	page
}) => {
	await page.click("text=Trigger Failure With ValueError");

	const toast = page.getByTestId("toast-body");
	expect(toast).toContainText("Error");
	const close = page.getByTestId("toast-close");
	await close.click();
	await expect(page.getByTestId("toast-body")).toHaveCount(0);
});

test("gr.Info makes the toast show up", async ({ page }) => {
	await page.click("text=Trigger Info");
	const toast = await page.getByTestId("toast-body");

	expect(toast).toContainText("This is some info");
	const close = await page.getByTestId("toast-close");
	await close.click();
	await expect(page.getByTestId("toast-body")).toHaveCount(0);
});

test("gr.Warning makes the toast show up", async ({ page }) => {
	await page.click("text=Trigger Warning");

	const toast = page.getByTestId("toast-body");
	expect(toast).toContainText("This is a warning!");
	const close = page.getByTestId("toast-close");
	await close.click();
	await expect(page.getByTestId("toast-body")).toHaveCount(0);
});