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

@dlenroc/appium-roku-driver

v0.12.0

Published

Appium Roku Driver

Downloads

25

Readme

Appium Roku Driver · NPM Version Node.js Version Node.js CI

Roku Driver is a WebDriver that allows testing channels/screensavers using any webdriver client.

Prerequisites

Installation

appium driver install --source npm @dlenroc/appium-roku-driver

Documentation

Thanks to the Appium and WebDriver protocol, this driver works just like other web drivers, but there are a couple of things worth mentioning.

Initialization

Like other drivers, roku-driver by default uses the so-called fast reset algorithm, in which registries are cleared before each test, and a full reinstallation occurs only if the channel differs from the one already installed.

Locators

The following location strategies are supported: tag name, link text, partial link text, css selector and xpath.

Contexts

  • ECP (default) External Control Protocol is a context that finds elements quickly, but does not see many attributes.

  • ODC (WIP) On Device Component is a context that finds elements slower, but see all attributes. (can be tunned using elementResponseAttributes setting).

Deep linking

  • input - Sends a custom event to the launched channel.

    driver.url('roku://input?<key>=<value>');
  • launch - Launches given channel with specific arguments.

    driver.url('roku://launch/:channel_id?<key>=<value>');

Channels

In roku appId is always dev for sideloaded channel or a number for channels installed from store (ex: 12 for Netflix).

driver.queryAppState('dev');
driver.queryAppState('12');

Note: most commands only work with SceneGrapth based sideloaded channels.

Screensaver / Screensaver Settings

Given driver allows testing of Screensavers via appium:entryPoint capability.

  • channel (default) - Opens channel itself.
  • screensaver - Opens your channel screen saver.
  • screensaver-settings - Opens your channel screen saver settings.

Note: Usually screensavers open on their own and close immediately after any user input is sent, but when entryPoint screensaver is used, it runs in the context of the channel, so the input interaction does not close it (BACK and HOME buttons are an exception).

Registries / Arguments

In Roku world:

So, knowing this, we can significantly speed up the automation by skipping authorization/configuration steps.

Note: appium:arguments and appium:registry will contain different values in your case.

const capabilities = {
  ...commonCapabilities,

  // Launch parameters
  'appium:arguments': {
    contentId: 1234,
    mediaType: 'movie',
  },

  // Registry sections Settings
  'appium:registry': {
    account: {
      token: '<user_token>',
    },
  },
};

BrightScript Logging

// Forward logs to the console
driver.on('log.entryAdded', (entry) => console.log(entry.text));

// Subscribe to BrightScript logs
await driver.sessionSubscribe({ events: ['log.entryAdded'] });

// Unsubscribe from BrightScript logs (optional)
await driver.sessionUnsubscribe({ events: ['log.entryAdded'] });

Note:

Actions

The following action types are supported:

  • keyDown, keyUp - presses/releases given key.
  • pointerMove - focuses the element using arrow buttons.
  • pause - waits given amounts of milliseconds.

Below are the key codes and their equivalents in the roku remote.

| Code | Keyboard Key | Roku Key | | -------- | ------------- | --------------- | | \uE002 | Help | Info | | \ue003 | Backspace | Backspace | | \ue006 | Return | Enter | | \ue007 | Enter | Select | | \ue00b | Pause | Play | | \uE00C | Escape | Back | | \uE00E | Page Up | ChannelUp | | \uE00F | Page Down | ChannelDown | | \ue011 | Home | Home | | \ue012 | Arrow Left | Left | | \ue013 | Arrow Up | Up | | \ue014 | Arrow Right | Right | | \ue015 | Arrow Down | Down | | \uE01A | 0 | InputAV1 | | \uE01B | 1 | InputHDMI1 | | \uE01C | 2 | InputHDMI2 | | \uE01D | 3 | InputHDMI3 | | \uE01E | 4 | InputHDMI4 | | \uE01F | 5 | InputTuner | | \uE036 | F6 | InstantReplay | | \uE037 | F7 | Rev | | \uE038 | F8 | Play | | \uE039 | F9 | Fwd | | \uE03A | F10 | VolumeMute | | \uE03B | F11 | VolumeDown | | \uE03C | F12 | VolumeUp |

Capabilities

If adding a vendor prefix is a problem, @appium/relaxed-caps-plugin can be used to get rid of them.

Roku Capabilities

| Capability | Required | Type | Description | | ------------------- | :------: | :----: | -------------------------------------------------------------------------------------------------------------------------------------- | | appium:ip | + | string | The IP address of the target device | | appium:password | + | string | Password for the development environment | | appium:username | - | string | Username for the development environment | | appium:context | - | string | Sets the context to be used, default ECP | | appium:registry | - | object | Pre-fills the registry with the specified sections/keys | | appium:arguments | - | object | Parameters to be passed to the main method | | appium:entryPoint | - | string | Specifies the channel entry point, possible values are channel, screensaver, screensaver-settings |

Appium Capabilities

| Capability | Required | Type | Description | | ------------------------------------- | :------: | :-----: | ------------------------------------------------------------------------------------------------------------------------------- | | platformName | + | string | Must be roku | | appium:automationName | + | string | Must be roku | | appium:deviceName | +/- | string | Helps webdriver clients understand that they are dealing with appium | | webSocketUrl | - | boolean | Opt in to the use of the Bidi protocol. Defaults to false. | | appium:app | - | string | The absolute local path or remote http URL to channel | | appium:noReset | - | boolean | Do not stop app, do not clear app data, and do not uninstall app | | appium:printPageSourceOnFindFailure | - | boolean | When a find operation fails, print the current page source. Defaults to false | | appium:newCommandTimeout | - | number | How long (in seconds) Appium will wait for a new command from the client before assuming the client quit and ending the session | | appium:settings[<key>] | - | any | Update driver settings on session creation | | appiun:shouldTerminateApp | - | boolean | If true, the channel will be closed after the session is finished. Defaults to false |

Settings

| Name | Type | Description | | --------------------------- | ------ | --------------------------------------------------------------------------------------------------------- | | elementResponseAttributes | string | Comma-separated list of element attribute names that will be available in page source and related actions |

Supported Commands

The supported commands are listed in the sections below but note that they may have a different name in the client you are using

Example: calling the setContext command

// Java
driver.context('ECP');

// WebdriverIO
driver.switchContext('ECP');

WebDriver Commands

| Command | Description | | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | createSession | Create a new session | | deleteSession | End the running session | | setUrl | Open a deep link | | active | Get the currently focused element | | findElement | Search for an element | | findElements | Search for multiple elements | | findElementFromElement | Search for an element in parent element | | findElementsFromElement | Search multiple elements in parent element | | getAttribute | Get the value of an attribute from a given element | | getProperty | Get the value of an property from a given element isFocused - returns true if the element is focused.isInFocusChain - returns true if the element or any of its descendants are focusedisInFocusHierarchy - returns true if the element or any of its ancestors or descendants is focused | | getText | Get the visible text of a given element | | getName | Get the tag name of given element | | getElementRect | Get the position and size of the given element | | elementDisplayed | Check if the element is displayed | | click | Presses the Select button on given element | | clear | Clears the content of the given element | | setValue | Send a sequence of keystrokes to an element | | getPageSource | Get the XML representation of the current UI | | execute | Execute an roku command | | performActions | Performs a chain of actions | | releaseActions | Release depressed key | | getScreenshot | Take a screenshot |

Appium Commands

| Command | Description | | ------------------------------------------------------ | ------------------------------------------------------ | | installApp | Install the channel if it is not installed | | activateApp | Launch the given channel | | terminateApp | Terminate the channel (Available since Roku OS 13.0) | | removeApp | Remove the given channel from the device | | isAppInstalled | Checks if a channel is installed | | queryAppState | Queries the channel state | | pushFile | Push a file to the device | | pullFile | Pull a file from the device | | pullFolder | Pull a folder from the device | | updateSettings | Updates current test session settings | | getCurrentContext | Get the name of the current context | | setContext | Switches to the given context | | getContexts | Get the names of available contexts |

BiDi Commands

| Command | Description | | -------------------------------------------------- | --------------------------------------------------------------- | | bidiSubscribe | Enables certain events either globally or for a set of contexts | | bidiUnsubscribe | Disables events either globally or for a set of contexts |

Roku Commands

In addition to the standard apium commands, Roku has several additional features that go beyond the appium protocol, so they are available through a javascript executor and a script in the following format <component>:<command>

The following components are available: ecp, debugServer, developerServer, and odc

Example:

// with args
driver.execute('ecp:launch', [{ appId: 'dev', params: {} }]);

// without args
const playerState = driver.execute('ecp:queryMediaPlayer');
playerState.duration;