Uno runtime-tests
Build and run Uno Platform runtime tests with proper base64 filter encoding. Use when running specific runtime tests or all runtime tests.
git clone https://github.com/unoplatform/uno
T=$(mktemp -d) && git clone --depth=1 https://github.com/unoplatform/uno "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/runtime-tests" ~/.claude/skills/unoplatform-uno-runtime-tests && rm -rf "$T"
.claude/skills/runtime-tests/SKILL.mdUser Input
$ARGUMENTS
You MUST consider the user input before proceeding (if not empty).
Overview
You are executing the Run Tests Skill. This skill builds and runs Uno Platform runtime tests with the correct base64 filter encoding that the test runner requires. It handles the non-obvious encoding requirement and provides correct platform-specific commands.
Execution Workflow
Phase 0: Parse User Input
Determine what to run from the user's input:
- All tests: No filter needed
- Specific test class: e.g.,
→ resolve to fully qualified nameGiven_Button - Specific test method: e.g.,
→ resolve to fully qualified nameGiven_Button.When_ContentSet - Multiple tests: Pipe-separated list of fully qualified names
If the user provides partial names, search
src/Uno.UI.RuntimeTests/Tests/ to resolve fully qualified test names (namespace + class + method).
Determine target platform from user input. Supported platforms:
| Platform | Keyword(s) | Default |
|---|---|---|
| Skia Desktop | , , or unspecified | Yes |
| Skia WASM | , , | No |
Default: Skia Desktop (fastest build and execution).
Choose Skia WASM only when:
- The user explicitly asks for WASM/browser testing, OR
- The bug or behavior is WASM-specific (e.g., DOM interaction, browser rendering, JS interop)
Phase 1: Build the Test App
CRITICAL: Set timeout to 15+ minutes. NEVER cancel builds.
Skia Desktop (default)
dotnet build src/SamplesApp/SamplesApp.Skia.Generic/SamplesApp.Skia.Generic.csproj -c Release -f net10.0
Skia WASM
dotnet publish src/SamplesApp/SamplesApp.Skia.WebAssembly.Browser/SamplesApp.Skia.WebAssembly.Browser.csproj -c Release -f net10.0
Note: WASM requires
publish (not just build) to produce the static web assets needed for hosting.
If the build fails:
- Read the error output
- Diagnose the issue (missing restore, compilation error, etc.)
- Fix or report the issue before attempting to run tests
Phase 2: Construct the Filter
If running specific tests (not all tests):
-
Format the filter string: Fully qualified test names, pipe-separated
- Single test:
Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml.Given_Control.When_Scenario - Multiple tests:
Test1|Test2|Test3
- Single test:
-
Base64 encode the filter (the
env var accepts ONLY base64-encoded values):UITEST_RUNTIME_TESTS_FILTERbash (Windows Git Bash / Linux / macOS):
export UITEST_RUNTIME_TESTS_FILTER=$(echo -n "fully.qualified.TestName" | base64)PowerShell:
$env:UITEST_RUNTIME_TESTS_FILTER = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("fully.qualified.TestName")) -
For multiple tests, join with
before encoding:|export UITEST_RUNTIME_TESTS_FILTER=$(echo -n "Namespace.Test1|Namespace.Test2" | base64) -
WASM-specific: When passing the filter via URL query parameter, replace
with=
in the base64 string to avoid URL parsing issues. The app reverses this substitution before decoding:!FILTER_B64=$(echo -n "fully.qualified.TestName" | base64) FILTER_B64_ESCAPED=${FILTER_B64//=/!}
Phase 3: Run Tests
Skia Desktop (default)
Navigate to the build output and execute:
cd src/SamplesApp/SamplesApp.Skia.Generic/bin/Release/net10.0 dotnet SamplesApp.Skia.Generic.dll --runtime-tests=test-results.xml
If running filtered tests, set the env var first:
export UITEST_RUNTIME_TESTS_FILTER=$(echo -n "fully.qualified.TestName" | base64) && cd src/SamplesApp/SamplesApp.Skia.Generic/bin/Release/net10.0 && dotnet SamplesApp.Skia.Generic.dll --runtime-tests=test-results.xml
Results are output in NUnit XML format to
test-results.xml (relative to CWD).
Skia WASM
WASM tests run in a browser. The published app is served over HTTP, and test parameters are passed as URL query parameters. The app writes results back via a companion HTTP server.
Step 1: Locate the publish output
PUBLISH_DIR="src/SamplesApp/SamplesApp.Skia.WebAssembly.Browser/bin/Release/net10.0/publish/wwwroot"
Step 2: Start the HTTP file server and the file-creation companion server
# Serve the published app on port 8000 python -m http.server 8000 -d "$PUBLISH_DIR" & HTTP_PID=$! # Start the companion server that receives file-write POST requests on port 8001 python build/test-scripts/skia-browserwasm-file-creation-server.py 8001 & COMPANION_PID=$! sleep 5
Step 3: Construct the URL with test parameters
The results file path must be an absolute path (the companion server writes to it):
RESULTS_FILE="$(pwd)/wasm-test-results.xml"
URL-encode the parameters and build the URL:
# Helper: basic URL encoding rawurlencode() { python -c "import urllib.parse; print(urllib.parse.quote('$1', safe=''))" } RESULTS_ENCODED=$(rawurlencode "$RESULTS_FILE")
Without filter:
http://localhost:8000/?--runtime-tests=$RESULTS_ENCODED
With filter (note the
= → ! replacement):
FILTER_B64=$(echo -n "fully.qualified.TestName" | base64) FILTER_B64_ESCAPED=${FILTER_B64//=/!} FILTER_ENCODED=$(rawurlencode "$FILTER_B64_ESCAPED") URL="http://localhost:8000/?--runtime-tests=${RESULTS_ENCODED}&--runtime-test-filter=${FILTER_ENCODED}"
Step 4: Open the URL in a browser
If the Playwright MCP tool is available (
mcp__playwright__browser_navigate), use it — no manual browser needed:
mcp__playwright__browser_navigate(url: "<the constructed URL>")
Keep the tab open until tests complete. If the results file does not appear within 10 minutes, use
mcp__playwright__browser_take_screenshot to inspect the state.
If Playwright is not available, open the URL with the OS default browser and instruct the user to keep it open:
On Windows (Git Bash):
start "" "$URL"
On Linux:
google-chrome --no-sandbox "$URL" &
On macOS:
open "$URL"
Step 5: Wait for results
The test runner writes a canary file (
$RESULTS_FILE.canary) when it starts and the actual results file when complete. Poll from bash:
# Wait for the results file (poll every 10 seconds, timeout 10 minutes) for i in $(seq 1 60); do [ -f "$RESULTS_FILE" ] && break; sleep 10; done
Step 6: Cleanup
kill $HTTP_PID $COMPANION_PID 2>/dev/null || true
Phase 4: Parse and Report Results
- Read the test results XML file (NUnit format)
- Report summary: total tests, passed, failed, skipped
- For failures: extract failure messages and stack traces
- If tests failed, suggest investigation steps:
- Check if the test is platform-specific
- Check if the failure is a known issue
- Suggest using
for complex failures/bug-investigate
Platform Quick Reference
| Skia Desktop | Skia WASM | |
|---|---|---|
| Project | | |
| Build command | | |
| Run method | | Browser navigates to URL with query params |
| Filter delivery | env var | URL query param |
Base64 handling | Standard base64 | Replace with before URL-encoding |
| Results delivery | Written directly to disk | Written via companion HTTP server on port+1 |
| Dependencies | None | Python (http.server), browser |
| Speed | Fast | Slower (publish + browser startup) |
| Recommended for | Default / local dev | WASM-specific bugs, platform divergence |
Technical Reference
Environment Variable
- Name:
UITEST_RUNTIME_TESTS_FILTER - Format: Base64-encoded, UTF-8 string
- Separator:
(pipe) between multiple test names| - Scope: Must be set in the same shell session that runs the test app (desktop), or passed as URL param (WASM)
Code Path
App.Tests.cs:HandleRuntimeTests() → SampleChooserViewModel.RunRuntimeTests() → Convert.FromBase64String() → Split("|") → UnitTestEngineConfig.Filters[]
Key Files
- Entry point:
src/SamplesApp/SamplesApp.Shared/App.Tests.cs - Filter decoding:
src/SamplesApp/SamplesApp.UnitTests.Shared/Controls/UITests/Presentation/SampleChooserViewModel.cs - Config:
src/SamplesApp/SamplesApp.UnitTests.Shared/Controls/UnitTest/UnitTestEngineConfig.cs - Test location:
src/Uno.UI.RuntimeTests/Tests/ - WASM CI script:
build/test-scripts/wasm-run-skia-runtime-tests.sh - WASM companion server:
build/test-scripts/skia-browserwasm-file-creation-server.py - Agent guide:
.github/agents/runtime-tests-agent.md
CI-Only Options
/--runtime-tests-group
: For CI test sharding--runtime-tests-group-count