Skip to main content

Roku WebDriver

Introduction

This page is a reference for the element model, supported commands, and key mappings of the Roku WebDriver integration.

The Roku WebDriver integration is written by TV Labs for the Roku platform. It is Appium compatible, so all Appium driver commands are available. The integration interfaces with the device over ECP — Roku's External Control Protocol (HTTP and websocket) — and the device's developer web server.

The roku: execute methods are documented on the Execute Methods page.

Sessions

Select a build with the tvlabs:build capability and it is sideloaded onto the device and launched when the session starts. A sideloaded channel always has the app id dev.

A session started without a build is still a valid session — the device is returned to the home screen and no channel is launched. Element commands are unavailable until a developer channel is running; see Finding elements.

Finding elements

The element tree is the running channel's SceneGraph hierarchy, read from ECP's /query/app-ui.

warning

Roku only serves /query/app-ui for the sideloaded developer channel. A store channel answers "Not authorized" and the home screen answers "No active app", and element commands return a no such element error carrying that message. This is a Roku restriction, not a TV Labs one.

getPageSource returns that hierarchy rooted at a synthetic <AppiumAUT> element, and locators are evaluated against the same document you get back from it.

Locator strategies

StrategyMatches
xpathEvaluated against the page source
id, nameThe node's name attribute
accessibility idThe node's uiElementId attribute
class nameThe node's tag — its SceneGraph node type, e.g. Label, Poster
tag nameThe node's tag

Any other strategy returns an invalid selector error, as does an XPath expression the server can't parse.

findElement and findElements honor the session's implicit wait, re-reading the tree from the device until the timeout expires. Set it once and let it cover the channel's own render latency:

await driver.setTimeout({ implicit: 10000 });

const playButton = await driver.$('//Label[@text="Play"]');

Element references

Roku's tree is re-read from the device on every element command, so an element reference is resolved fresh each time rather than pointing at a cached node. An element that has left the tree returns a stale element reference error, and a reference that no longer identifies a single node returns unknown error asking for a more specific selector.

Interacting with elements

Clicking

Roku has no pointer. click moves focus onto the element by pressing direction keys, then presses Select.

This means clicking depends on the channel drawing a focus path to the element:

  • Something on screen has to report focus for the walk to have a direction to move from. If nothing does, the click returns element not interactable.
  • Neither the element nor any of its ancestors having a focused sibling returns element not interactable as well — there is nowhere to walk from.
  • The walk gives up after 20 key presses, also with element not interactable.

To move focus onto an element without activating it, use roku: selectElement.

Entering text

sendKeys looks for Roku's on-screen keyboard in the element tree, presses Select on the element to summon one if there isn't one already, types the string, and then dismisses the keyboard — pressing its OK button when the dialog has one, and Back otherwise.

const searchField = await driver.$('//TextEditBox');

await searchField.setValue('planet earth');

clear is not supported. Clear a field with the remote instead, for example by pressing Backspace with roku: pressKey once per character.

Element properties

CommandBehavior on Roku
getTextThe node's text attribute
getAttributeThe SceneGraph attribute of that name, or null when the node doesn't carry it
getPropertyThe same as getAttribute — SceneGraph nodes have fields, not a separate property model
getRectThe node's bounds, or a zero rect when it has none
isSelectedWhether the remote's focus is on the element
isDisplayed, isEnabledtrue for any element that resolves — the tree carries no visibility or disabled state
getComputedRoleThe node's tag
getComputedLabelThe node's text attribute
note

bounds is a node's box in its parent's coordinate space, not the screen's. A label inside a container positioned at {225, 375} reports its own origin as {0, 0}. Compare rects between siblings, not across containers.

Session-level commands

CommandBehavior on Roku
getPageSourceThe <AppiumAUT>-rooted element hierarchy
getActiveElementThe innermost focused node
takeScreenshotServed from the device's video capture
getWindowRectThe device's UI render resolution, which is the space bounds is expressed in
minimizeWindowPresses Home and returns the window rect
getContextsAlways the single NATIVE_APP context

Roku sessions are native-only, so the commands that need a web context are not available: arbitrary JavaScript through executeScript, navigation commands such as back, the cookie endpoints, and element screenshots all return an error. Press the remote's Back button with roku: pressKey instead.

Key map

The following key names are accepted by roku: pressKey and roku: longPress. Both spellings of each key work and matching is case-insensitive, so InstantReplay, instantreplay, and replay are the same key.

ECP keycodeAlternate nameDescription
HomehomeHome
BackbackBack
UpupUp
DowndownDown
LeftleftLeft
RightrightRight
Selectselect, okOK / Select
RevrewindRewind
FwdforwardFast forward
PlayplayPlay / Pause
InstantReplayreplayInstant replay
InfoinfoInfo / *
BackspacebackspaceBackspace
SearchsearchSearch
EnterenterEnter
VolumeUpvolume_upVolume up
VolumeDownvolume_downVolume down
VolumeMutevolume_mute, muteMute toggle
ChannelUpchannel_upChannel up
ChannelDownchannel_downChannel down
InputTunerinput_tunerTuner input
InputHDMI1input_hdmi1HDMI 1 input
InputHDMI2input_hdmi2HDMI 2 input
InputHDMI3input_hdmi3HDMI 3 input
InputHDMI4input_hdmi4HDMI 4 input
InputAV1input_av1AV 1 input
PowerpowerPower toggle
PowerOnpower_onPower on
PowerOffpower_offPower off
FindRemotefind_remoteFind remote
note

The volume, input, and channel keys only have an effect on Roku TVs. A streaming player has no tuner, inputs, or speakers of its own.

A key name that isn't in the table is sent to ECP verbatim, so any keycode Roku accepts works — including the Lit_ literal-character form:

await driver.execute('roku: pressKey', { key: 'Lit_a' });