Skip to content

Testing and delivery

HuxerUI separates application tests, platform diagnosis, compilation, and distributable packaging. Use each layer as evidence for the contract it actually covers.

Keep state reducers, parsers, route codecs, validation rules, and service code independent of a native window where possible. They can use the project’s ordinary C++ test framework and link the same HuxerUI target as the application.

For UI behavior, test controlled outputs rather than implementation details:

  • Provide an authoritative value and verify the component emits the requested change.
  • Exercise disabled and cancellation paths as well as success.
  • Use stable keys when a test inserts, removes, or reorders stateful siblings.
  • Drive deterministic time for animation tests instead of sleeping.
  • Verify semantic roles, labels, values, and actions for accessibility-sensitive controls.

Platform adapters still require integration tests on their real host because native text input, accessibility, clipboard, windows, and graphics services cannot be proven by a shared unit test alone.

Use a separate test executable with <huxerui/testing/ui_test.h>. The fixture runs the real shared Runtime without an OS window. The application root owns its scope, so this example needs no composable annotation.

#include <huxerui/huxerui.h>
#include <huxerui/testing/ui_test.h>
#include <stdexcept>
using namespace huxerui;
using namespace huxerui::testing;
View EditorApp() {
auto value = UseState(TextEditingValue::FromText(""));
return Column {
TextField(value).Key("editor"),
Text(value->text).Key("preview"),
}.With(Padding(16.0F));
}
int main() {
const Application application{EditorApp, {.show_debug_overlay = false}};
UiTest ui(application, {.viewport = {390.0F, 844.0F}});
auto editor = ui.Find(UiSelector::Key("editor"));
editor.Tap();
editor.ReplaceText("Ada");
const auto preview = ui.Find(UiSelector::AllOf(UiSelector::Key("preview"), UiSelector::Text("Ada")));
if (!preview.Exists()) {
throw std::runtime_error("The controlled editor did not update its preview");
}
}

Save this translation unit as editor_test.cpp and use:

cmake_minimum_required(VERSION 3.20)
project(editor_tests LANGUAGES CXX)
find_package(HuxerUI CONFIG REQUIRED COMPONENTS testing)
add_executable(editor_test editor_test.cpp)
target_compile_features(editor_test PRIVATE cxx_std_20)
target_link_libraries(editor_test PRIVATE HuxerUI::testing)
enable_testing()
add_test(NAME editor_test COMMAND editor_test)

Configure with your installed SDK and compatible host toolchain, build, then run CTest. Source consumers enable HUXERUI_BUILD_TESTING_LIBRARY. Request COMPONENTS testing static or testing shared only when explicitly selecting an available core form. Reusable annotated functions still need the usual codegen integration; keep the test main separate from the application’s generated platform entry.

Test transitions, semantics, and responsive state

Section titled “Test transitions, semantics, and responsive state”

High-level editing and pointer helpers pump their input automatically. Raw input and direct configuration changes require an explicit Pump before inspecting results. To test animation, advance virtual time rather than sleeping:

const auto before = ui.CaptureSnapshot();
ui.Pump(std::chrono::milliseconds(100));
const auto during = ui.CaptureSnapshot();
ui.PumpUntil([&] { return ui.Find(UiSelector::Text("Done")).Exists(); });

The fixture’s virtual timeout does not wait for real workers or HTTP. Supply controlled services where possible and give the test runner a separate wall-clock timeout. Use FindSemantics and UiSemanticSelector to verify accessible labels, roles, state, and actions independently from physical hit testing.

Queries re-resolve after each frame. One and actions require unique targets; scope repeated labels under a stable parent key. Exists can find offscreen retained nodes and does not guarantee Tap will succeed. Snapshot strings represent structure/render intent, not pixels; store and approve baselines through your existing test runner.

Resources must be supplied through UiTestOptions::resource_provider. The reference text profile is deterministic but does not reproduce platform shaping, bidi, typography, or complex grapheme behavior. Native platform services still require host tests. See UI testing API for precise query, time, ownership, and failure contracts.

Run the non-mutating environment check in CI and on a new workstation:

Terminal window
huxerui doctor windows,web

Use huxerui setup <platforms> only in provisioning jobs that are allowed to install tools. For repeatable CI, pin the HuxerUI SDK and external platform SDK versions rather than relying on the newest globally available tools.

Use debug builds for diagnostics and release builds for performance and packaging:

Terminal window
huxerui build windows --profile debug
huxerui build windows --profile release

A release build is not proof of a valid installer, store archive, or signed binary. Run the packaged application from its staged directory so missing runtime libraries and resource packages are visible before distribution.

Create distributable inputs under dist/<platform>:

Terminal window
huxerui package windows,web

The platform driver replaces its destination directory on each successful package operation. Apply signing and publication after this boundary:

Platform Typical next step
Windows Installer or archive creation, code signing, clean-machine launch test.
macOS Bundle signing, notarization, and distribution packaging.
iOS Xcode archive, provisioning validation, and App Store export.
Android Release signing and Play-compatible bundle or APK workflow.
Linux Distribution-specific package or portable archive.
Web Deploy the generated site with correct MIME types, caching, and cross-origin policy.

Before publishing an application:

  • Run focused tests and the full shared suite used by the project.
  • Build every affected platform from an available supported host.
  • Verify generated resources and localized fallback strings.
  • Exercise startup activation, warm activation, suspend/background transitions, and route restoration.
  • Test keyboard, pointer, touch, text input, selection, and accessibility on applicable devices.
  • Run without a developer SDK on PATH to expose accidental runtime dependencies.
  • Record the HuxerUI SDK version and external toolchain versions used by the release.

Treat a platform unavailable to CI as explicitly unverified, not implicitly passing.

The website has one framework source of truth: huxerui-source.json pins the repository commit and the Web example list published by the site. API contracts, source links, extracted documentation examples, and WebAssembly builds all resolve that same commit.

Before changing the pin, audit a candidate checkout without editing the website configuration:

Terminal window
npm run audit:revision -- /path/to/HuxerUI

The audit reports added or removed public headers, explicit contract drift, missing or changed configured examples, and reference pages affected by public-header changes. Review those pages, update the explicit contracts in scripts/api-coverage.mjs, then change the revision and run the complete website checks. A clean audit does not replace API review: signature contracts and compiled examples are the checks that expose a changed overload, enum, or usage pattern.

The site intentionally remains single-version. Do not add a second documentation tree when advancing the pin; update the manual and its validation contract together.

Set HUXERUI_HOME to the extracted SDK root or place the SDK’s bin/ directory on PATH, then rerun huxerui doctor.

Keep the marked definition in a .cpp, .cc, or .cxx source and ensure huxerui_enable_codegen runs after the target owns that source. Applications and libraries created by HuxerUI CMake helpers already enable it.

Use huxerui_add_app, huxerui_add_library, or huxerui_add_resources so the generated header and binary package share one namespace and packaging owner. Do not copy only the generated header.

huxerui_use_library requires a full commit SHA for remote URLs. Update that revision deliberately and review the dependency as application source.

Run huxerui devices <platform> and pass --device <id>. Automatic selection occurs only when one ready device is available.