makepad/examples/text_input/tests/ui.rs
Sabin Regmi 0cff3fd7f6
ft makepad_test (#974)
* ft makepad_test

* Improve run handling, manifest parsing, and stdout newline

Replace dynamic free-port lookup with an ephemeral localhost SocketAddr in test runtime and remove the unused find_free_listen_address helper. Ensure headless stdout messages end with a newline. Simplify send_to_app error handling and add a test that queued bootstrap messages are delivered once an app socket connects. Substantially enhance process_manager: unify cargo flag parsing, parse Cargo.toml to determine package/bin targets, resolve the correct binary name for direct stdio runs, and build the cargo/build+exec script from the resolved args. Add unit tests for manifest parsing and script generation and adjust related call sites.

* test harness

* Preserve test attrs; return Vec for gateway binds

In the test macro (libs/makepad_test/macros/src/lib.rs) preserve wrapper-only attributes (ignore and should_panic) on the generated wrapper test while removing them from the inner function. Added Attribute import, is_wrapper_only_test_attr helper, adjusted attribute filtering and emission, and added unit tests to verify attribute placement and expansion.

In the hub (studio/hub/src/hub.rs) change gateway_bind_candidates to return a Vec<SocketAddr> instead of an iterator and special-case ephemeral port 0 to preserve ephemeral binding; otherwise collect the range of candidate ports into a Vec. Added tests to validate candidate behavior. Also minor formatting/whitespace tweaks and a small IPv6 formatting adjustment.

* Add visible Studio mode and remote client

Enable running UI tests visibly through a running Makepad Studio. Adds a new makepad-network dependency and studio_remote client (libs/makepad_test/src/studio_remote.rs) and integrates it into the runtime via a TestConnection enum. Introduces visible-mode tooling: env vars (MAKEPAD_TEST_VISIBLE, MAKEPAD_TEST_STUDIO, MAKEPAD_TEST_STUDIO_MOUNT, MAKEPAD_TEST_STARTUP_DELAY_MS, MAKEPAD_TEST_ACTION_DELAY_MS, MAKEPAD_TEST_KEEP_OPEN_MS), pacing/delays after actions, and pause-before-shutdown. Splits startup into start_headless_app/start_visible_app, clears existing visible builds before launching, and updates tests, docs (GUIDE.md, README.md), and selector/runtime minor cleanups/formatting.
2026-03-25 16:09:03 +01:00

72 lines
2.2 KiB
Rust

use makepad_test::{makepad_test, run_with_config, Selector, TestApp, TestConfig, TestError};
use std::fs;
#[makepad_test]
fn fill_clear_and_submit_singleline_input(app: TestApp) {
app.locator(Selector::id("input_singleline"))
.wait_visible()
.fill("hello")
.wait_value("hello")
.clear()
.wait_value("")
.fill("hello")
.wait_value("hello");
app.press_return();
app.locator(Selector::id("status_label"))
.wait_text("Returned from singleline: \"hello\"");
app.wait_for_log_contains("Returned from singleline: \"hello\"");
}
#[makepad_test]
fn waits_for_visible_inputs(app: TestApp) {
app.locator(Selector::id("input_email")).wait_visible();
}
#[makepad_test]
fn missing_selector_reports_useful_error(app: TestApp) -> Result<(), TestError> {
let err = app
.locator(Selector::id("input_missing"))
.try_click()
.unwrap_err();
assert!(err.message().contains("matched no visible widgets"));
Ok(())
}
#[makepad_test]
fn type_selector_reports_multiple_matches(app: TestApp) -> Result<(), TestError> {
let err = app
.locator(Selector::widget_type("TextInput"))
.try_click()
.unwrap_err();
assert!(err.message().contains("matched multiple widgets"));
assert!(err.message().contains("input_singleline"));
Ok(())
}
#[test]
fn captures_failure_artifacts() {
let config = TestConfig::current_package(
env!("CARGO_MANIFEST_DIR"),
env!("CARGO_PKG_NAME"),
"ui::captures_failure_artifacts",
)
.unwrap();
let artifact_dir = config.artifacts_dir.clone();
let _ = fs::remove_dir_all(&artifact_dir);
let err = run_with_config(config, |_app| -> Result<(), TestError> {
Err(TestError::new("intentional failure for artifact capture"))
})
.unwrap_err();
assert!(
err.message().contains("intentional failure"),
"{}",
err.message()
);
assert!(artifact_dir.join("failure.txt").exists());
assert!(artifact_dir.join("logs.txt").exists());
assert!(artifact_dir.join("widget-tree.txt").exists());
assert!(artifact_dir.join("widget-snapshot.json").exists());
assert!(artifact_dir.join("failure-screenshot.png").exists());
}