2.6.0 • Published 2 months ago

@headspinio/appium-roku-driver v2.6.0

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
2 months ago

Appium Roku Driver

This project is an Appium 2.x driver for automation of Roku channels (in the Roku world, "channel" means "app").

Background

Roku's developer portal is essential reading for using this driver well. As with any Appium driver, the more knowledge you have on how the underlying platform works, including development experience on that platform, the more successful you will be in troubleshooting any issues that arise during use of the driver.

To support its features, the Appium Roku Driver uses the following technologies provided by Roku:

Roku also provides its own WebDriver implementation, however it is lacking in many respects and doesn't respect the WebDriver standard, nor is it Appium-compatible. The Appium team recommends this driver instead, for the time being.

Requirements

Before using the driver, please ensure the following are in place:

  • Your Roku device has developer mode enabled
  • You have access to your dev channel code in the .zip format expected by the Roku dev sideload utility
  • The Roku device is accessible via TCP/IP from the machine where the Appium server is running (further, if you are SSH-tunneling to Roku dev ports via another machine, you'll need the IP address of the Roku on its local network)
  • You have a working and updated Appium 2.0 server

Limitations

We are limited to working with the tools that Roku has provided, which means many traditional ways of working with UI-based applications are off the table. As a set of examples:

  • It is not possible to work directly with UI element objects. Appium provides element objects as a convenience only.
  • It is not possible to retrieve the source or screenshot of an app which is not your dev channel.
  • Only one dev channel may be sideloaded at a time
  • Screenshots taken which include videos will not include video content for DRM reasons.

Installation

With Appium 2.0's driver CLI, installation is as easy as:

appium driver install --source=npm @headspinio/appium-roku-driver

Capabilities

CapabilityTypeDescriptionRequired
platformNamestringAppium requires this. To activate this driver, it must be RokuYes
appium:automationNamestringAppium requires this. To activate this driver, it must be rokuYes
appium:appstringAbsolute path to zip file of dev channel. If not included, a session will simply be started on the home screenNo
appium:rokuHoststringThe host name or IP of the Roku deviceYes
appium:rokuEcpPortnumberThe ECP port on the Roku device (usually 8060)Yes
appium:rokuWebPortnumberThe dev web interface port on the Roku device (usually 80)Yes
appium:rokuWebCooldownnumberSometimes, multiple requests to the Roku web server in quick succession result in failures. By default the Appium driver waits 500ms before each request to the server to avoid this problem. You can tune this value (in ms) with this capability.No
appium:rokuUserstringThe username you selected when turning on dev modeYes
appium:rokuPassstringThe password you selected when turning on dev modeYes
appium:rokuHeaderHoststringThe IP of the Roku device on its local network (usually the same as rokuHost unless you are tunneling or connecting via DNS)Yes
appium:keyCooldownnumberThe number of milliseconds to wait between remote key presses. Can be useful for waiting to ensure the UI catches up with the remote. Defaults to 0.No

Supported Commands

The following table details the commands available via this driver. The command name is simply the internal Appium command name; it is not necessarily what you would call from your client code. Visit your client's documentation to see how you would call these commands from, e.g., the Java or Python client.

CommandParametersDescription
createSessionStart an Appium session on the Roku. If no appium:app capability is provided, the session will simply begin at the Home screen. If an appium:app capability is provided, the app will be sideloaded and launched.
deleteSessionStop the Appium session, which basically entails going to the home screen.
installAppappPathSideload the app found at appPath to the Roku. Installing an app causes the Roku to remove any previously sideloaded app.
removeAppappIdRemove the app whose id is appId. The id should be the one returned in the call to roku: getApps (see below)
activateAppappId, contentId (optional), mediaType (optional)Launch the app whose id is appId. You can optionally include content ID and media type parameters as defined in Roku's deep linking docs (you do not need to URL-encode the value of contentId; the driver will do that for you).
getPageSourceReturn the XML representation of the current app hierarchy. Only available if the sideloaded dev app is active.
getScreenshotReturn a base64-encoded string representing a PNG screenshot image. Only available if the sideloaded dev app is active.findElementstrategy, selectorFind an element in the app hierarchy matching selector. Only the xpath strategy is supported. If no matching element is found, the driver will respond with a NoSuchElement error.
findElementsstrategy, selectorFind a (possibly-empty) list of elements in the app hierarchy matching selector. Only the xpath strategy is supported.

Element Commands

Once you have an element ID, you can run these commands as well:

CommandParametersDescription
clickelementIdCheck whether the element represented by elementId is marked as focused in the source XML. If not, determine which remote keypress will move the focus closer to the desired element. Repeat this process until the element is focused, and press the 'Select' button.
sendKeysstringSet the given value to the element
getAttributestring, elementIdReturn the value of attribute key string of the element represented by elementId. If attribute key is not present for the element, method will return null
getTextelementIdReturn the value of the text attribute for an element. If the text attribute is not present, this method will return null.

A note about stale element references: when you attempt to click an element, the driver will retrieve the current app source XML, and attempt to re-find the element based on the original locator criteria. If the find results in an XML node that matches the element reference, all is well. If not, the driver understands the element hierarchy to have changed and will respond with a Stale Element Exception.

Roku Commands

Using the Roku APIs listed above, we have access to functionality that goes beyond standard Appium protocol commands. This extra functionality is made available via the executeScript command. This command takes a string (the script), and an array of objects (the arguments for the script) as parameters.

These special Roku commands all follow the same format: their script string should start with roku:, and they should have a single argument in the argument list, which is an object whose values represent the command arguments. Let's take, for example, the roku: pressKey command. To press the Home key, we need to execute the roku: pressKey script, and the argument should be an array with a single element, namely an object of the form {"key": "Home"}. In the WebdriverIO client bindings, this would look like:

await driver.executeScript('roku: pressKey', [{key: 'Home'}])

(And of course it would look different in every other language/library).

CommandParametersDescription
roku: pressKeykeyPress the remote key whose value matches key (must be one of the supported key values from the Roku documentation). As addressed in the documentation, Roku TVs also support additioanl keys such as PowerOff and PowerOn.
roku: deviceInfoGet information about the Roku device
roku: getAppsGet a list of apps installed on the device. The response will be a list of objects with the following keys: id, type, subtype, version, and name.
roku: activeAppGet information about the active app, in the same format as roku: getApps.
roku: activateAppappId (required), contentId, mediaTypeLaunch an app with the corresponding appId. Optionally include contentId and mediaType information (with the same properties as described above for the activateApp command)
roku: selectElementelementId (required)Moves the focus on a element having locator xpath as elementId. If it is unable to focus on the element, the driver will respond with a error.
roku: playerStateGet the state of the media player. The data will be returned as a JSON object, corresponding to the information included in the query/media-player ECP result
roku: deepLinkcontentId, mediaTypeAs described in the Roku dev docs, you can deep link into content in the running application using a content ID and media type. For this command, contentId is required, and mediaType defaults to movie and must be one of the valid media types. Note that this command acts on the currently-running app. If you want to test deep-linking into an app that is not launched, use activateApp instead.
roku: ecpInputparamsThis command allows calling the /input ECP command directly. An arbitrary set of key/value pairs can be sent in as a JSON object. No url-encoding of the values needs to be done. For example, to represent the parameters in the ECP command POST /input?acceleration.x=0.0&acceleration.y=0.0&acceleration.z=9.8 from the ECP docs, you would construct a params of {"acceleration.x": "0.0", "acceleration.y": "0.0", "acceleration.z": "9.8"}

Contributing

We would love for you to contribute to this project! Check out the contribution guide for more info.

Credits

  • Development for this driver is sponsored by HeadSpin.
  • Special thanks to @sharkyStudy for help with the NPM package as well as developing another implementation in parallel before joining to assist with this project.
2.6.0

2 months ago

2.5.2

3 months ago

2.5.1

3 months ago

2.5.0

4 months ago

2.4.0

4 months ago

2.3.0

6 months ago

2.2.0

6 months ago

2.1.1

11 months ago

2.0.5

1 year ago

2.0.7

1 year ago

2.0.6

1 year ago

2.0.8

1 year ago

2.1.0

1 year ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.4

2 years ago

1.1.4

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago