Skip to content

Commit

Permalink
feat: add media player query command
Browse files Browse the repository at this point in the history
  • Loading branch information
jlipps committed Jan 17, 2024
1 parent 91d5aef commit da8c96e
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ await driver.executeScript('roku: pressKey', [{key: 'Home'}])
|`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](https://developer.roku.com/en-ca/docs/developer-program/dev-tools/external-control-api.md#querymedia-player-example)|

## Contributing

Expand Down
25 changes: 25 additions & 0 deletions lib/commands/roku.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export async function executeRoku (rokuCommand, opts = /** @type {TOpts} */({}))
'installApp',
'removeApp',
'selectElement',
'playerState',
];

if (!_.includes(rokuCommands, rokuCommand)) {
Expand Down Expand Up @@ -96,6 +97,30 @@ export async function roku_deviceInfo () {
return niceInfo;
}

/**
* @this RokuDriver
* @returns {Promise<any>}
*/
export async function roku_playerState () {
const playerXml = (await this.rokuEcp('/query/media-player', 'GET')).data;
const parser = new xml2js.Parser();
const info = await parser.parseStringPromise(playerXml);
const niceInfo = {player: {}};
niceInfo.player.error = info.player.$.error;
niceInfo.player.state = info.player.$.state;
for (const playerKey of Object.keys(info.player)) {
if (playerKey === '$') {
continue;
}
const data = info.player[playerKey][0].$;
niceInfo[playerKey] = {};
for (const dataKey of Object.keys(data)) {
niceInfo[playerKey][dataKey] = data[dataKey];
}
}
return niceInfo;
}

/**
* @this RokuDriver
* @returns {Promise<RokuAppData[]>}
Expand Down
2 changes: 2 additions & 0 deletions lib/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
roku_removeApp,
roku_pressKey,
roku_selectElement,
roku_playerState,
setValue,
setValueByEcp,
setValueByKeyboard,
Expand Down Expand Up @@ -136,6 +137,7 @@ export default class RokuDriver extends BaseDriver {
roku_pressKey = roku_pressKey;
roku_activeApp = roku_activeApp;
roku_selectElement = roku_selectElement;
roku_playerState = roku_playerState;
installApp = installApp.bind(this);
getPageSource = getPageSource.bind(this);
getScreenshot = getScreenshot;
Expand Down
5 changes: 5 additions & 0 deletions test/functional/driver.e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ describe('RokuDriver', function () {
const info = await driver.executeScript('roku: deviceInfo', []);
info['vendor-name'].should.eql('Roku');
});
it('should be able to get player state', async function () {
const state = await driver.executeScript('roku: playerState', []);
state.player.error.should.eql('false');
state.plugin.name.should.exist;
});
it('should be able to get app ui', async function () {
await activateByName(APP_NAME);
await driver
Expand Down

0 comments on commit da8c96e

Please sign in to comment.