Testing and delivery
HuxerUI separates application tests, platform diagnosis, compilation, and distributable packaging. Use each layer as evidence for the contract it actually covers.
Test application logic
Section titled “Test application logic”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.
Test a controlled editor
Section titled “Test a controlled editor”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.
Diagnose before building
Section titled “Diagnose before building”Run the non-mutating environment check in CI and on a new workstation:
huxerui doctor windows,webUse 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.
Build profiles
Section titled “Build profiles”Use debug builds for diagnostics and release builds for performance and packaging:
huxerui build windows --profile debughuxerui build windows --profile releaseA 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.
Package per platform
Section titled “Package per platform”Create distributable inputs under dist/<platform>:
huxerui package windows,webThe 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. |
Release checklist
Section titled “Release checklist”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
PATHto 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.
Update the documented HuxerUI revision
Section titled “Update the documented HuxerUI revision”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:
npm run audit:revision -- /path/to/HuxerUIThe 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.
Common failures
Section titled “Common failures”HUXERUI_HOME is not found
Section titled “HUXERUI_HOME is not found”Set HUXERUI_HOME to the extracted SDK root or place the SDK’s bin/ directory on PATH, then rerun huxerui doctor.
A generated scope is not transformed
Section titled “A generated scope is not transformed”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.
Resources compile but do not load
Section titled “Resources compile but do not load”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.
A remote library changes unexpectedly
Section titled “A remote library changes unexpectedly”huxerui_use_library requires a full commit SHA for remote URLs.
Update that revision deliberately and review the dependency as application source.
A device command is ambiguous
Section titled “A device command is ambiguous”Run huxerui devices <platform> and pass --device <id>.
Automatic selection occurs only when one ready device is available.

