npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@headspinio/appium-roku-driver

v2.6.2

Published

Appium driver for Roku channels

Downloads

196

Readme

Appium Roku Driver

npm version

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

|Capability|Type|Description|Required| |----------|----|-----------|--------| |platformName|string|Appium requires this. To activate this driver, it must be Roku|Yes| |appium:automationName|string|Appium requires this. To activate this driver, it must be roku|Yes| |appium:app|string|Absolute path to zip file of dev channel. If not included, a session will simply be started on the home screen|No| |appium:rokuHost|string|The host name or IP of the Roku device|Yes| |appium:rokuEcpPort|number|The ECP port on the Roku device (usually 8060)|Yes| |appium:rokuWebPort|number|The dev web interface port on the Roku device (usually 80)|Yes| |appium:rokuWebCooldown|number|Sometimes, 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:rokuUser|string|The username you selected when turning on dev mode|Yes| |appium:rokuPass|string|The password you selected when turning on dev mode|Yes| |appium:rokuHeaderHost|string|The IP of the Roku device on its local network (usually the same as rokuHost unless you are tunneling or connecting via DNS)|Yes| |appium:keyCooldown|number|The 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.

|Command|Parameters|Description| |-------|----------|-----------| |createSession||Start 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.| |deleteSession||Stop the Appium session, which basically entails going to the home screen.| |installApp|appPath|Sideload the app found at appPath to the Roku. Installing an app causes the Roku to remove any previously sideloaded app.| |removeApp|appId|Remove the app whose id is appId. The id should be the one returned in the call to roku: getApps (see below)| |activateApp|appId, 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).| |getPageSource||Return the XML representation of the current app hierarchy. Only available if the sideloaded dev app is active.| |getScreenshot||Return a base64-encoded string representing a PNG screenshot image. Only available if the sideloaded dev app is active.|findElement|strategy, selector|Find 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.| |findElements|strategy, selector|Find 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:

|Command|Parameters|Description| |-------|----------|-----------| |click|elementId|Check 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.| |sendKeys|string|Set the given value to the element| |getAttribute|string, elementId|Return 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| |getText|elementId|Return 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).

|Command|Parameters|Description| |-------|----------|-----------| |roku: pressKey|key|Press 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: deviceInfo||Get information about the Roku device| |roku: getApps||Get 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: activeApp||Get information about the active app, in the same format as roku: getApps.| |roku: activateApp|appId (required), contentId, mediaType|Launch an app with the corresponding appId. Optionally include contentId and mediaType information (with the same properties as described above for the activateApp command)| |roku: selectElement|elementId (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: playerState||Get 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: deepLink|contentId, mediaType|As 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: ecpInput|params|This 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.

release

npm version patch # etc
npm publish
# push the local commit and tag to this repository

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.