Devices, Browsers, and Input Methods
Hosanna selects a platform separately from a target kind. A test can therefore run a platform expression in an owned browser or, where the launcher implements it, on a simulator or physical device.
Select a target
HosannaTestConfig accepts platform, target, appConfig, and device. Environment variables override the first two when config does not set them:
HS_TEST_PLATFORM=web HS_TEST_TARGET=web npm run test:ui
HS_TEST_PLATFORM=roku HS_TEST_TARGET=device npm run test:ui
Target kinds are web, sim, and device. Use the package scripts in the application repository for supported combinations rather than assuming every platform/target pair has a complete transport.
Select target-specific tests in TypeScript:
import { createHosannaTestTarget } from '@tantawowa/hosanna-tools/testing';
import config from '../hosanna-test.config';
const target = createHosannaTestTarget(config);
test.runIf(target.matches({ platform: 'roku', target: 'device' }))(
'captures a Roku screenshot',
async ({ hs }) => {
await hs.screenshot.capture('roku-home');
},
);
{ target: 'web' } means any platform expression in the browser. { platform: 'web', target: 'web' } means the web platform specifically.
Current capability matrix
The runtime descriptor reports the first seven capabilities below. Full-run video is separate launcher configuration because it records the surrounding test run rather than an in-app command. The current shared launcher supports:
| Capability | Owned browser | Physical Roku | Apple/Android native simulator | Other physical devices |
|---|---|---|---|---|
| Remote-style keys | Yes | Yes, through ECP | Yes, through the command plane | Command-plane support is advertised |
| Touch | Web/iOS/Android platform expressions | No | No | No |
| Text entry | Yes | No | No | No |
| Deep link | Yes | Yes | Yes, through relaunch arguments | Not currently implemented |
| Screenshot | Yes | Yes | Yes, through simctl or ADB | Not currently implemented |
| Registry | Yes | Yes | Yes | Advertised through the command plane |
| Logs | Yes | Yes | Yes | Advertised through the command plane |
| Full-run video | Playwright WebM | Capture-card/window capture when configured | Apple simulator recording; explicit macOS capture for Android | Not currently implemented |
Call hs.app.capabilities() when a shared test can adapt safely; otherwise make the target requirement explicit with test.runIf.
Input APIs
Remote and keyboard-style input use the same semantic keys:
await hs.remote.press('Right');
await hs.remote.pressSequence(['Down', 'Down', 'Select']);
await hs.remote.keyDown('Right');
await hs.remote.keyUp('Right');
The browser target sends these through the Hosanna debugger input path. A Roku device uses ECP. This tests application navigation semantics without pretending the transports are identical.
The public client exposes these calls for browser contexts created with touch enabled:
await hs.touch.tap(hs.control.byTestId('touch-card'));
await hs.touch.swipe({
from: { x: 900, y: 700 },
to: { x: 900, y: 300 },
durationMs: 250,
});
tap(locator) uses serialized control bounds. Prefer it over coordinates. The current public client has no separate pointer/mouse API; do not claim mouse coverage from a touch or remote test.
In the current launcher, a browser reattached through connectOverCDP can
advertise touch while Playwright rejects touchscreen.tap because hasTouch
was not enabled when that persistent context was created.
hosanna-ui-samples-public therefore uses the app-owned
integration/support/browser.ts helper to dispatch CDP touch events at the
center of semantic control bounds. Treat that helper as a documented browser
transport workaround until the owned context enables Playwright touch directly.
The same helper covers pointer activation with a real mouse click. It connects
to the fixture's browserCdpEndpoint, finds the owned test page, and clicks the
center of semantic control bounds. The pointer test is restricted to
{ platform: 'web', target: 'web' }. Keep host-specific extensions like these
out of shared cross-target helpers.
Text entry is browser-only and fills the focused native HTML input after activating the Hosanna control. Pass an envSecret result for credentials so serialized diagnostics contain only the secret label.
Sample browser profile matrix
hosanna-ui-samples-public maps HS_TEST_DEVICE into HosannaTestConfig.device and provides these scripts:
| Script | Hosanna platform/preset | Intended expression/input |
|---|---|---|
npm run test:ui:web | web, default web launch | desktop browser/remote-style tests |
npm run test:ui:ios-browser | ios + iphone-15 | phone design profile with touch |
npm run test:ui:tablet-browser | ios + ipad-10 | tablet design profile with touch |
npm run test:ui:android-browser | android + pixel-8 | phone design profile with touch |
npm run test:ui:tv-browser | apple-tv + apple-tv-4k | TV design profile with remote-style input |
npm run test:ui:devices | all five scripts in sequence | complete sample browser matrix |
A device preset expands into Hosanna launch state: platform expression, logical design size, DPI, default adapters, and orientation. These profiles exercise responsive Hosanna layout/input behavior in the web simulator.
Sample native simulator matrix
These scripts build, install, launch, and handshake with the vendor-native simulator:
| Script | Native target |
|---|---|
npm run test:ui:ios:sim | iOS Simulator |
npm run test:ui:appletv:sim | Apple TV Simulator |
npm run test:ui:android:sim | Android phone AVD |
npm run test:ui:androidtv:sim | Android TV AVD |
Set HS_TEST_DEVICE when more than one matching simulator is online. These runs support semantic commands, deep-link relaunch, and host screenshots. They still do not turn on the fixture’s touch or text-entry transports.
Browser profiles versus hardware
The owned Playwright Chromium context itself currently uses a 1920×1080 viewport. The public test config does not expose browser engine selection or an arbitrary Playwright viewport/device-scale-factor option. Phone/TV presets change the Hosanna design surface and platform expression inside that browser; they are not physical devices or vendor simulators.
Therefore:
- use the sample matrix for deterministic desktop, phone, tablet, and TV-expression application behavior;
- do not label a browser preset run as physical mobile, tablet, or television coverage;
- run native simulator/device validation through
hst runand platform-specific tests where the test transport supports the required assertions; - use real hardware for remote timing, native rendering, GPU, decoder, accessibility, and device-service behavior.
Changing the video output size does not change these limitations. For design sizing and the full preset catalog, see Device and Resolution.
Physical Roku setup
A Roku run needs a device reachable from the development machine, developer mode, ECP, installer/screenshot access, and the debug log port. Configure the IP and password through the application config/environment, for example:
HS_TEST_PLATFORM=roku \
HS_TEST_TARGET=device \
HOSANNA_ROKU_DEVICE_IP=192.168.1.50 \
HOSANNA_ROKU_DEV_PASSWORD='<developer-password>' \
npm run test:ui
Set HS_TEST_DEBUG_HOST only when automatic LAN selection chooses an address the Roku cannot reach. Keep device credentials out of source and uploaded artifacts.
Next: Running in CI.
Reference helpers: support/target.ts and the browser-only support/browser.ts.