{"id":13612800,"url":"https://github.com/dlenroc/appium-roku-driver","last_synced_at":"2025-04-16T02:59:33.400Z","repository":{"id":38344404,"uuid":"349760161","full_name":"dlenroc/appium-roku-driver","owner":"dlenroc","description":"WebDriver for testing channels / screensavers on roku devices","archived":false,"fork":false,"pushed_at":"2024-06-14T06:38:24.000Z","size":745,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-25T10:01:56.037Z","etag":null,"topics":["appium","roku","selenium","webdriver"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dlenroc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-20T15:17:46.000Z","updated_at":"2025-02-22T10:39:36.000Z","dependencies_parsed_at":"2023-12-21T00:19:04.602Z","dependency_job_id":"e0ea72ff-f987-4c6e-8f25-daa5649a09da","html_url":"https://github.com/dlenroc/appium-roku-driver","commit_stats":{"total_commits":54,"total_committers":2,"mean_commits":27.0,"dds":0.2407407407407407,"last_synced_commit":"a9d1b88498a57b66dc0e0293b9a96c0b285219d0"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlenroc%2Fappium-roku-driver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlenroc%2Fappium-roku-driver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlenroc%2Fappium-roku-driver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlenroc%2Fappium-roku-driver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dlenroc","download_url":"https://codeload.github.com/dlenroc/appium-roku-driver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249188373,"owners_count":21227013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appium","roku","selenium","webdriver"],"created_at":"2024-08-01T20:00:34.679Z","updated_at":"2025-04-16T02:59:33.374Z","avatar_url":"https://github.com/dlenroc.png","language":"TypeScript","funding_links":[],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"# Appium Roku Driver · [![NPM Version](https://img.shields.io/npm/v/@dlenroc/appium-roku-driver?cacheSeconds=86400)](https://www.npmjs.com/package/@dlenroc/appium-roku-driver) ![Node.js Version](https://img.shields.io/node/v/@dlenroc/appium-roku-driver) [![Node.js CI](https://github.com/dlenroc/appium-roku-driver/actions/workflows/nodejs.yml/badge.svg?branch=main)](https://github.com/dlenroc/appium-roku-driver/actions/workflows/nodejs.yml)\n\nRoku Driver is a WebDriver that allows testing channels/screensavers using any webdriver client.\n\n## Prerequisites\n\n- Appium 2\n- Roku Device with fresh OS and mentioned below settings:\n  - [Roku OS 9.4 or Newest](https://support.roku.com/en-gb/article/208755668)\n  - [Enable Developer Settings](https://developer.roku.com/en-gb/docs/developer-program/getting-started/developer-setup.md#step-1-set-up-your-roku-device-to-enable-developer-settings)\n  - [Disable Screensaver](https://www.solveyourtech.com/how-to-disable-the-screensaver-on-a-roku-tv/) (optional)\n\n## Installation\n\n```sh\nappium driver install --source npm @dlenroc/appium-roku-driver\n```\n\n## Documentation\n\nThanks to the [Appium](https://github.com/appium/appium) and [WebDriver](https://www.w3.org/TR/webdriver/) protocol, this driver works just like other web drivers, but there are a couple of things worth mentioning.\n\n### Initialization\n\nLike 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.\n\n### Locators\n\nThe following location strategies are supported: `tag name`, `link text`, `partial link text`, `css selector` and `xpath`.\n\n### Contexts\n\n- `ECP` (default) [External Control Protocol](https://github.com/dlenroc/node-roku/blob/main/packages/ecp#readme) is a context that finds elements quickly, but does not see many attributes.\n\n- `ODC` (WIP) [On Device Component](https://github.com/dlenroc/node-roku/blob/main/packages/odc#readme) is a context that finds elements slower, but see all attributes. (can be tunned using `elementResponseAttributes` setting).\n\n### Deep linking\n\n- `input` - Sends a custom event to the launched channel.\n\n  ```js\n  driver.url('roku://input?\u003ckey\u003e=\u003cvalue\u003e');\n  ```\n\n- `launch` - Launches given channel with specific arguments.\n\n  ```js\n  driver.url('roku://launch/:channel_id?\u003ckey\u003e=\u003cvalue\u003e');\n  ```\n\n### Channels\n\nIn roku `appId` is always `dev` for sideloaded channel or a number for channels installed from store (ex: `12` for Netflix).\n\n```js\ndriver.queryAppState('dev');\ndriver.queryAppState('12');\n```\n\n\u003e **Note:** most commands only work with SceneGrapth based sideloaded channels.\n\n### Screensaver / Screensaver Settings\n\nGiven driver allows testing of [Screensavers](https://developer.roku.com/en-gb/docs/developer-program/media-playback/screensavers.md) via `appium:entryPoint` capability.\n\n- `channel` (default) - Opens channel itself.\n- `screensaver` - Opens your channel screen saver.\n- `screensaver-settings` - Opens your channel screen saver settings.\n\n\u003e 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).\n\n### Registries / Arguments\n\nIn Roku world:\n\n- [Registries](https://developer.roku.com/en-gb/docs/developer-program/getting-started/architecture/file-system.md) are used to store persistent information such as sessions and settings.\n- [Input / Launch parameters](https://developer.roku.com/en-gb/docs/developer-program/discovery/implementing-deep-linking.md) are used for deep linking and/or controlling app behavior.\n\nSo, knowing this, we can significantly speed up the automation by skipping authorization/configuration steps.\n\n\u003e **Note:** `appium:arguments` and `appium:registry` will contain different values in your case.\n\n```js\nconst capabilities = {\n  ...commonCapabilities,\n\n  // Launch parameters\n  'appium:arguments': {\n    contentId: 1234,\n    mediaType: 'movie',\n  },\n\n  // Registry sections Settings\n  'appium:registry': {\n    account: {\n      token: '\u003cuser_token\u003e',\n    },\n  },\n};\n```\n\n### BrightScript Logging\n\n```js\n// Forward logs to the console\ndriver.on('log.entryAdded', (entry) =\u003e console.log(entry.text));\n\n// Subscribe to BrightScript logs\nawait driver.sessionSubscribe({ events: ['log.entryAdded'] });\n\n// Unsubscribe from BrightScript logs (optional)\nawait driver.sessionUnsubscribe({ events: ['log.entryAdded'] });\n```\n\n\u003e **Note:**\n\n### Actions\n\nThe following action types are supported:\n\n- `keyDown`, `keyUp` - presses/releases given key.\n- `pointerMove` - focuses the element using arrow buttons.\n- `pause` - waits given amounts of milliseconds.\n\nBelow are the key codes and their equivalents in the roku remote.\n\n| Code     | Keyboard Key  | Roku Key        |\n| -------- | ------------- | --------------- |\n| `\\uE002` | `Help`        | `Info`          |\n| `\\ue003` | `Backspace`   | `Backspace`     |\n| `\\ue006` | `Return`      | `Enter`         |\n| `\\ue007` | `Enter`       | `Select`        |\n| `\\ue00b` | `Pause`       | `Play`          |\n| `\\uE00C` | `Escape`      | `Back`          |\n| `\\uE00E` | `Page Up`     | `ChannelUp`     |\n| `\\uE00F` | `Page Down`   | `ChannelDown`   |\n| `\\ue011` | `Home`        | `Home`          |\n| `\\ue012` | `Arrow Left`  | `Left`          |\n| `\\ue013` | `Arrow Up`    | `Up`            |\n| `\\ue014` | `Arrow Right` | `Right`         |\n| `\\ue015` | `Arrow Down`  | `Down`          |\n| `\\uE01A` | `0`           | `InputAV1`      |\n| `\\uE01B` | `1`           | `InputHDMI1`    |\n| `\\uE01C` | `2`           | `InputHDMI2`    |\n| `\\uE01D` | `3`           | `InputHDMI3`    |\n| `\\uE01E` | `4`           | `InputHDMI4`    |\n| `\\uE01F` | `5`           | `InputTuner`    |\n| `\\uE036` | `F6`          | `InstantReplay` |\n| `\\uE037` | `F7`          | `Rev`           |\n| `\\uE038` | `F8`          | `Play`          |\n| `\\uE039` | `F9`          | `Fwd`           |\n| `\\uE03A` | `F10`         | `VolumeMute`    |\n| `\\uE03B` | `F11`         | `VolumeDown`    |\n| `\\uE03C` | `F12`         | `VolumeUp`      |\n\n## Capabilities\n\nIf adding a vendor prefix is a problem, [@appium/relaxed-caps-plugin](https://www.npmjs.com/package/@appium/relaxed-caps-plugin) can be used to get rid of them.\n\n### Roku Capabilities\n\n| Capability          | Required |  Type  | Description                                                                                                                            |\n| ------------------- | :------: | :----: | -------------------------------------------------------------------------------------------------------------------------------------- |\n| `appium:ip`         |    +     | string | The IP address of the target device                                                                                                    |\n| `appium:password`   |    +     | string | Password for the [development environment](https://developer.roku.com/en-gb/docs/developer-program/getting-started/developer-setup.md) |\n| `appium:username`   |    -     | string | Username for the [development environment](https://developer.roku.com/en-gb/docs/developer-program/getting-started/developer-setup.md) |\n| `appium:context`    |    -     | string | Sets the [context](#contexts) to be used, default `ECP`                                                                                |\n| `appium:registry`   |    -     | object | Pre-fills the registry with the specified sections/keys                                                                                |\n| `appium:arguments`  |    -     | object | Parameters to be passed to the main method                                                                                             |\n| `appium:entryPoint` |    -     | string | Specifies the channel entry point, possible values are `channel`, `screensaver`, `screensaver-settings`                                |\n\n### Appium Capabilities\n\n| Capability                            | Required |  Type   | Description                                                                                                                     |\n| ------------------------------------- | :------: | :-----: | ------------------------------------------------------------------------------------------------------------------------------- |\n| `platformName`                        |    +     | string  | Must be `roku`                                                                                                                  |\n| `appium:automationName`               |    +     | string  | Must be `roku`                                                                                                                  |\n| `appium:deviceName`                   |   +/-    | string  | Helps webdriver clients understand that they are dealing with appium                                                            |\n| `webSocketUrl`                        |    -     | boolean | Opt in to the use of the Bidi protocol. Defaults to `false`.                                                                    |\n| `appium:app`                          |    -     | string  | The absolute local path or remote http URL to channel                                                                           |\n| `appium:noReset`                      |    -     | boolean | Do not stop app, do not clear app data, and do not uninstall app                                                                |\n| `appium:printPageSourceOnFindFailure` |    -     | boolean | When a find operation fails, print the current page source. Defaults to `false`                                                 |\n| `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 |\n| `appium:settings[\u003ckey\u003e]`              |    -     |   any   | Update [driver settings](#settings) on session creation                                                                         |\n| `appiun:shouldTerminateApp`           |    -     | boolean | If `true`, the channel will be closed after the session is finished. Defaults to `false`                                        |\n\n## Settings\n\n| Name                        | Type   | Description                                                                                               |\n| --------------------------- | ------ | --------------------------------------------------------------------------------------------------------- |\n| `elementResponseAttributes` | string | Comma-separated list of element attribute names that will be available in page source and related actions |\n\n## Supported Commands\n\nThe supported commands are listed in the sections below but note that they may have a different name in the client you are using\n\nExample: calling the `setContext` command\n\n```js\n// Java\ndriver.context('ECP');\n\n// WebdriverIO\ndriver.switchContext('ECP');\n```\n\n### WebDriver Commands\n\n| Command                                                | Description                                                                                                                                                                                                                                                                                                                               |\n| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [createSession](src/commands/createSession.ts)         | Create a new session                                                                                                                                                                                                                                                                                                                      |\n| [deleteSession](src/commands/deleteSession.ts)         | End the running session                                                                                                                                                                                                                                                                                                                   |\n| [setUrl](src/commands/setUrl.ts)                       | Open a deep link                                                                                                                                                                                                                                                                                                                          |\n| [active](src/commands/active.ts)                       | Get the currently focused element                                                                                                                                                                                                                                                                                                         |\n| [findElement](src/commands/findElOrEls.ts)             | Search for an element                                                                                                                                                                                                                                                                                                                     |\n| [findElements](src/commands/findElOrEls.ts)            | Search for multiple elements                                                                                                                                                                                                                                                                                                              |\n| [findElementFromElement](src/commands/findElOrEls.ts)  | Search for an element in parent element                                                                                                                                                                                                                                                                                                   |\n| [findElementsFromElement](src/commands/findElOrEls.ts) | Search multiple elements in parent element                                                                                                                                                                                                                                                                                                |\n| [getAttribute](src/commands/getAttribute.ts)           | Get the value of an attribute from a given element                                                                                                                                                                                                                                                                                        |\n| [getProperty](src/commands/getProperty.ts)             | Get the value of an property from a given element \u003cul\u003e\u003cli\u003e`isFocused` - returns `true` if the element is focused.\u003c/li\u003e\u003cli\u003e`isInFocusChain` - returns `true` if the element or any of its descendants are focused\u003c/li\u003e\u003cli\u003e`isInFocusHierarchy` - returns `true` if the element or any of its ancestors or descendants is focused\u003c/li\u003e\u003c/ul\u003e |\n| [getText](src/commands/getText.ts)                     | Get the visible text of a given element                                                                                                                                                                                                                                                                                                   |\n| [getName](src/commands/getName.ts)                     | Get the tag name of given element                                                                                                                                                                                                                                                                                                         |\n| [getElementRect](src/commands/getElementRect.ts)       | Get the position and size of the given element                                                                                                                                                                                                                                                                                            |\n| [elementDisplayed](src/commands/elementDisplayed.ts)   | Check if the element is displayed                                                                                                                                                                                                                                                                                                         |\n| [click](src/commands/click.ts)                         | Presses the `Select` button on given element                                                                                                                                                                                                                                                                                              |\n| [clear](src/commands/clear.ts)                         | Clears the content of the given element                                                                                                                                                                                                                                                                                                   |\n| [setValue](src/commands/setValue.ts)                   | Send a sequence of keystrokes to an element                                                                                                                                                                                                                                                                                               |\n| [getPageSource](src/commands/getPageSource.ts)         | Get the XML representation of the current UI                                                                                                                                                                                                                                                                                              |\n| [execute](src/commands/execute.ts)                     | Execute an roku command                                                                                                                                                                                                                                                                                                                   |\n| [performActions](src/commands/performActions.ts)       | Performs a chain of actions                                                                                                                                                                                                                                                                                                               |\n| [releaseActions](src/commands/releaseActions.ts)       | Release depressed key                                                                                                                                                                                                                                                                                                                     |\n| [getScreenshot](src/commands/getScreenshot.ts)         | Take a screenshot                                                                                                                                                                                                                                                                                                                         |\n\n### Appium Commands\n\n| Command                                                | Description                                            |\n| ------------------------------------------------------ | ------------------------------------------------------ |\n| [installApp](src/commands/installApp.ts)               | Install the channel if it is not installed             |\n| [activateApp](src/commands/activateApp.ts)             | Launch the given channel                               |\n| [terminateApp](src/commands/terminateApp.ts)           | Terminate the channel (_Available since Roku OS 13.0_) |\n| [removeApp](src/commands/removeApp.ts)                 | Remove the given channel from the device               |\n| [isAppInstalled](src/commands/isAppInstalled.ts)       | Checks if a channel is installed                       |\n| [queryAppState](src/commands/queryAppState.ts)         | Queries the channel state                              |\n| [pushFile](src/commands/pushFile.ts)                   | Push a file to the device                              |\n| [pullFile](src/commands/pullFile.ts)                   | Pull a file from the device                            |\n| [pullFolder](src/commands/pullFolder.ts)               | Pull a folder from the device                          |\n| [updateSettings](src/commands/updateSetting.ts)        | Updates current test session settings                  |\n| [getCurrentContext](src/commands/getCurrentContext.ts) | Get the name of the current context                    |\n| [setContext](src/commands/setContext.ts)               | Switches to the given context                          |\n| [getContexts](src/commands/getContexts.ts)             | Get the names of available contexts                    |\n\n### BiDi Commands\n\n| Command                                            | Description                                                     |\n| -------------------------------------------------- | --------------------------------------------------------------- |\n| [bidiSubscribe](src/commands/bidiSubscribe.ts)     | Enables certain events either globally or for a set of contexts |\n| [bidiUnsubscribe](src/commands/bidiUnsubscribe.ts) | Disables events either globally or for a set of contexts        |\n\n### Roku Commands\n\nIn 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 `\u003ccomponent\u003e:\u003ccommand\u003e`\n\nThe following components are available: [ecp](https://npmjs.com/package/@dlenroc/roku-ecp/v/2.0.0), [debugServer](https://www.npmjs.com/package/@dlenroc/roku-debug-server/v/2.0.0), [developerServer](https://www.npmjs.com/package/@dlenroc/roku-developer-server/v/2.0.0), and [odc](https://www.npmjs.com/package/@dlenroc/roku-odc/v/2.0.1)\n\nExample:\n\n```js\n// with args\ndriver.execute('ecp:launch', [{ appId: 'dev', params: {} }]);\n\n// without args\nconst playerState = driver.execute('ecp:queryMediaPlayer');\nplayerState.duration;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlenroc%2Fappium-roku-driver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdlenroc%2Fappium-roku-driver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlenroc%2Fappium-roku-driver/lists"}