roku-test-automation
Advanced tools
Comparing version 1.0.37 to 1.0.38
@@ -1,2 +0,1 @@ | ||
import { RokuDevice } from './RokuDevice'; | ||
import { ActiveAppResponse } from './types/ActiveAppResponse'; | ||
@@ -11,3 +10,4 @@ import { ConfigOptions } from './types/ConfigOptions'; | ||
readonly Key: typeof ECPKeys; | ||
constructor(device: RokuDevice, config?: ConfigOptions); | ||
constructor(config?: ConfigOptions); | ||
getConfig(): import("./types/ConfigOptions").ECPConfigOptions | undefined; | ||
sendText(text: string, wait?: number): Promise<void>; | ||
@@ -14,0 +14,0 @@ sendKeyPress(key: ECPKeys, wait?: number): Promise<void>; |
@@ -50,14 +50,24 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var RokuDevice_1 = require("./RokuDevice"); | ||
var ECPKeys_1 = require("./types/ECPKeys"); | ||
var utils = require("./utils"); | ||
var utils_1 = require("./utils"); | ||
var ECP = /** @class */ (function () { | ||
function ECP(device, config) { | ||
function ECP(config) { | ||
//store the import on the class to make testing easier | ||
this.utils = utils; | ||
this.utils = utils_1.utils; | ||
this.Key = ECP.Key; | ||
this.device = device; | ||
this.config = config; | ||
this.device = new RokuDevice_1.RokuDevice(config); | ||
} | ||
ECP.prototype.getConfig = function () { | ||
var _a; | ||
var section = 'ECP'; | ||
if (!this.config) { | ||
var config = utils_1.utils.getOptionalConfigFromEnvironment(); | ||
utils_1.utils.validateRTAConfigSchema(config, [section]); | ||
this.config = config; | ||
} | ||
return (_a = this.config) === null || _a === void 0 ? void 0 : _a[section]; | ||
}; | ||
ECP.prototype.sendText = function (text, wait) { | ||
if (wait === void 0) { wait = 0; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -88,11 +98,13 @@ var _i, text_1, char, value; | ||
if (wait === void 0) { wait = 0; } | ||
var _a, _b, _c; | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
var keyPressDelay; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: return [4 /*yield*/, this.device.sendECP("keypress/" + encodeURIComponent(key), {}, '')]; | ||
case 1: | ||
_d.sent(); | ||
if (!wait) { | ||
wait = (_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.defaults) === null || _b === void 0 ? void 0 : _b.ecp.keyPressDelay) !== null && _c !== void 0 ? _c : wait; | ||
_c.sent(); | ||
keyPressDelay = (_b = (_a = this.getConfig()) === null || _a === void 0 ? void 0 : _a.default) === null || _b === void 0 ? void 0 : _b.keyPressDelay; | ||
if (!wait && keyPressDelay) { | ||
wait = keyPressDelay; | ||
} | ||
@@ -102,4 +114,4 @@ if (!wait) return [3 /*break*/, 3]; | ||
case 2: | ||
_d.sent(); | ||
_d.label = 3; | ||
_c.sent(); | ||
_c.label = 3; | ||
case 3: return [2 /*return*/]; | ||
@@ -111,3 +123,2 @@ } | ||
ECP.prototype.sendKeyPressSequence = function (keys, wait) { | ||
if (wait === void 0) { wait = 0; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -144,5 +155,5 @@ var _i, keys_1, key; | ||
if (!channelId) { | ||
configChannelId = (_h = (_g = this.config) === null || _g === void 0 ? void 0 : _g.channel) === null || _h === void 0 ? void 0 : _h.id; | ||
configChannelId = (_h = (_g = this.getConfig()) === null || _g === void 0 ? void 0 : _g.default) === null || _h === void 0 ? void 0 : _h.launchChannelId; | ||
if (!configChannelId) { | ||
throw utils.makeError('sendLaunchChannelChannelIdMissing', 'Channel id required and not supplied'); | ||
throw utils_1.utils.makeError('sendLaunchChannelChannelIdMissing', 'Channel id required and not supplied'); | ||
} | ||
@@ -179,3 +190,3 @@ channelId = configChannelId; | ||
if (!success) | ||
throw utils.makeError('sendLaunchChannelVerifyLaunch', "Could not launch channel with id of '" + channelId); | ||
throw utils_1.utils.makeError('sendLaunchChannelVerifyLaunch', "Could not launch channel with id of '" + channelId); | ||
_l.label = 8; | ||
@@ -198,3 +209,3 @@ case 8: return [2 /*return*/]; | ||
if (!children) | ||
throw utils.makeError('getActiveAppInvalidResponse', 'Received invalid active-app response from device'); | ||
throw utils_1.utils.makeError('getActiveAppInvalidResponse', 'Received invalid active-app response from device'); | ||
response = {}; | ||
@@ -201,0 +212,0 @@ for (_i = 0, children_1 = children; _i < children_1.length; _i++) { |
@@ -1,10 +0,15 @@ | ||
import * as utils from './utils'; | ||
import { utils } from './utils'; | ||
export { utils }; | ||
export * from './ECP'; | ||
export * from './NetworkProxy'; | ||
export * from './OnDeviceComponent'; | ||
export * from './RokuDevice'; | ||
export * from './types/ECPKeys'; | ||
import { ECP } from './ECP'; | ||
declare const ecp: ECP; | ||
export { ECP, ecp }; | ||
import { OnDeviceComponent } from './OnDeviceComponent'; | ||
declare const odc: OnDeviceComponent; | ||
export { OnDeviceComponent, odc }; | ||
import { RokuDevice } from './RokuDevice'; | ||
declare const device: RokuDevice; | ||
export { RokuDevice, device }; | ||
export * from './types/ActiveAppResponse'; | ||
export * from './types/ConfigOptions'; | ||
export * from './types/ECPKeys'; | ||
export * from './types/OnDeviceComponentRequest'; |
@@ -6,9 +6,18 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils = require("./utils"); | ||
exports.utils = utils; | ||
__export(require("./ECP")); | ||
__export(require("./NetworkProxy")); | ||
__export(require("./OnDeviceComponent")); | ||
__export(require("./RokuDevice")); | ||
var utils_1 = require("./utils"); | ||
exports.utils = utils_1.utils; | ||
var ECP_1 = require("./ECP"); | ||
exports.ECP = ECP_1.ECP; | ||
var ecp = new ECP_1.ECP(); | ||
exports.ecp = ecp; | ||
var OnDeviceComponent_1 = require("./OnDeviceComponent"); | ||
exports.OnDeviceComponent = OnDeviceComponent_1.OnDeviceComponent; | ||
var odc = new OnDeviceComponent_1.OnDeviceComponent(); | ||
exports.odc = odc; | ||
var RokuDevice_1 = require("./RokuDevice"); | ||
exports.RokuDevice = RokuDevice_1.RokuDevice; | ||
var device = new RokuDevice_1.RokuDevice(); | ||
exports.device = device; | ||
__export(require("./types/ConfigOptions")); | ||
__export(require("./types/ECPKeys")); | ||
__export(require("./types/OnDeviceComponentRequest")); |
@@ -1,4 +0,3 @@ | ||
import { RokuDevice } from './RokuDevice'; | ||
import { ConfigOptions } from './types/ConfigOptions'; | ||
import { ODCCallFuncArgs, ODCRequestOptions, ODCGetValueAtKeyPathArgs, ODCGetValuesAtKeyPathsArgs, ODCObserveFieldArgs, ODCSetValueAtKeyPathArgs, ODCIsInFocusChainArgs, ODCHasFocusArgs, ODCNodeFields, ODCGetFocusedNodeArgs } from '.'; | ||
import { ODCCallFuncArgs, ODCRequestOptions, ODCGetValueAtKeyPathArgs, ODCGetValuesAtKeyPathsArgs, ODCObserveFieldArgs, ODCSetValueAtKeyPathArgs, ODCIsInFocusChainArgs, ODCHasFocusArgs, ODCNodeRepresentation, ODCGetFocusedNodeArgs } from '.'; | ||
export declare class OnDeviceComponent { | ||
@@ -10,3 +9,3 @@ defaultTimeout: number; | ||
private device; | ||
private config; | ||
private config?; | ||
private client; | ||
@@ -18,11 +17,10 @@ private sentRequests; | ||
private handshakePromise?; | ||
constructor(device: RokuDevice, config: ConfigOptions); | ||
constructor(config?: ConfigOptions); | ||
getConfig(): import(".").OnDeviceComponentConfigOptions | undefined; | ||
callFunc(args: ODCCallFuncArgs, options?: ODCRequestOptions): Promise<{ | ||
success: boolean; | ||
value: any; | ||
}>; | ||
getFocusedNode(args?: ODCGetFocusedNodeArgs, options?: ODCRequestOptions): Promise<ODCNodeFields>; | ||
getFocusedNode(args?: ODCGetFocusedNodeArgs, options?: ODCRequestOptions): Promise<ODCNodeRepresentation>; | ||
getValueAtKeyPath(args: ODCGetValueAtKeyPathArgs, options?: ODCRequestOptions): Promise<{ | ||
found: boolean; | ||
success: boolean; | ||
value: any; | ||
@@ -33,4 +31,2 @@ }>; | ||
found: boolean; | ||
success: boolean; | ||
value: any; | ||
}>; | ||
@@ -40,9 +36,7 @@ hasFocus(args: ODCHasFocusArgs, options?: ODCRequestOptions): Promise<boolean>; | ||
observeField(args: ODCObserveFieldArgs, options?: ODCRequestOptions): Promise<{ | ||
/** Whether the observer was actually fired or a match value was provided and already equaled the requested value */ | ||
/** If a match value was provided and already equaled the requested value the observer won't get fired. This lets you be able to check if that occurred or not */ | ||
observerFired: boolean; | ||
value: any; | ||
}>; | ||
setValueAtKeyPath(args: ODCSetValueAtKeyPathArgs, options?: ODCRequestOptions): Promise<{ | ||
success: boolean; | ||
}>; | ||
setValueAtKeyPath(args: ODCSetValueAtKeyPathArgs, options?: ODCRequestOptions): Promise<{}>; | ||
private sendHandShakeRequest; | ||
@@ -49,0 +43,0 @@ private breakOutFieldFromKeyPath; |
@@ -52,5 +52,7 @@ "use strict"; | ||
var express = require("express"); | ||
var utils = require("./utils"); | ||
var portfinder = require("portfinder"); | ||
var RokuDevice_1 = require("./RokuDevice"); | ||
var utils_1 = require("./utils"); | ||
var OnDeviceComponent = /** @class */ (function () { | ||
function OnDeviceComponent(device, config) { | ||
function OnDeviceComponent(config) { | ||
this.defaultTimeout = 5000; | ||
@@ -61,5 +63,15 @@ this.debugLog = false; | ||
this.app = this.setupExpress(); | ||
this.device = device; | ||
this.config = config; | ||
this.device = new RokuDevice_1.RokuDevice(config); | ||
} | ||
OnDeviceComponent.prototype.getConfig = function () { | ||
var _a; | ||
var section = 'OnDeviceComponent'; | ||
if (!this.config) { | ||
var config = utils_1.utils.getOptionalConfigFromEnvironment(); | ||
utils_1.utils.validateRTAConfigSchema(config, [section]); | ||
this.config = config; | ||
} | ||
return (_a = this.config) === null || _a === void 0 ? void 0 : _a[section]; | ||
}; | ||
OnDeviceComponent.prototype.callFunc = function (args, options) { | ||
@@ -150,8 +162,9 @@ return __awaiter(this, void 0, void 0, function () { | ||
match = args.match; | ||
if (match) { | ||
if (!('keyPath' in match)) { | ||
if (match !== undefined) { | ||
// Check if it's an object. Also have to check constructor as array is also an instanceof Object, make sure it has the keyPath key | ||
if (!((match instanceof Object) && (match.constructor.name === 'Object') && ('keyPath' in match))) { | ||
args.match = { | ||
base: args.base, | ||
keyPath: args.keyPath, | ||
value: match.value | ||
value: match | ||
}; | ||
@@ -200,3 +213,3 @@ } | ||
version: OnDeviceComponent.version, | ||
logLevel: (_b = (_a = this.config.device.odc) === null || _a === void 0 ? void 0 : _a.logLevel) !== null && _b !== void 0 ? _b : 'info' | ||
logLevel: (_b = (_a = this.getConfig()) === null || _a === void 0 ? void 0 : _a.logLevel) !== null && _b !== void 0 ? _b : 'info' | ||
}; | ||
@@ -253,3 +266,3 @@ return [4 /*yield*/, this.sendRequestCore('handshake', args, { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var requestId, request, body, promise, timeout; | ||
var requestId, request, body, promise, host, timeout; | ||
return __generator(this, function (_b) { | ||
@@ -260,3 +273,3 @@ switch (_b.label) { | ||
_b.sent(); | ||
requestId = utils.randomStringGenerator(); | ||
requestId = utils_1.utils.randomStringGenerator(); | ||
request = { | ||
@@ -282,5 +295,6 @@ id: requestId, | ||
this.sentRequests[requestId] = request; | ||
host = this.device.getConfig().host; | ||
if (this.debugLog) | ||
console.log("Sending request to " + this.device.ip + " with body: " + body); | ||
this.client.send(body, 9000, this.device.ip, function (err) { | ||
console.log("Sending request to " + host + " with body: " + body); | ||
this.client.send(body, 9000, host, function (err) { | ||
if (err) { | ||
@@ -291,3 +305,3 @@ throw err; | ||
timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : this.defaultTimeout; | ||
return [2 /*return*/, utils.promiseTimeout(promise, timeout, request.type + " request " + requestId + " timed out after " + timeout + "ms")]; | ||
return [2 /*return*/, utils_1.utils.promiseTimeout(promise, timeout, request.type + " request " + requestId + " timed out after " + timeout + "ms")]; | ||
} | ||
@@ -299,21 +313,23 @@ }); | ||
OnDeviceComponent.prototype.startServer = function () { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var callbackListenPort; | ||
var _this = this; | ||
return __generator(this, function (_b) { | ||
if (this.server) { | ||
return [2 /*return*/]; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (this.server) { | ||
return [2 /*return*/]; | ||
} | ||
return [4 /*yield*/, portfinder.getPortPromise()]; | ||
case 1: | ||
callbackListenPort = _a.sent(); | ||
if (this.debugLog) | ||
console.log("Starting callback server"); | ||
this.server = this.app.listen(callbackListenPort, function () { | ||
if (_this.debugLog) | ||
console.log("Listening for callbacks on " + callbackListenPort); | ||
}); | ||
this.callbackListenPort = callbackListenPort; | ||
return [2 /*return*/]; | ||
} | ||
callbackListenPort = (_a = this.config.server) === null || _a === void 0 ? void 0 : _a.callbackListenPort; | ||
if (!callbackListenPort) | ||
throw new Error('Config did not have a callback listen port'); | ||
if (this.debugLog) | ||
console.log("Starting callback server"); | ||
this.server = this.app.listen(callbackListenPort, function () { | ||
if (_this.debugLog) | ||
console.log("Listening for callbacks on " + callbackListenPort); | ||
}); | ||
this.callbackListenPort = callbackListenPort; | ||
return [2 /*return*/]; | ||
}); | ||
@@ -320,0 +336,0 @@ }); |
/// <reference types="mocha" /> | ||
import * as needle from 'needle'; | ||
import { ScreenshotFormat } from './types/ConfigOptions'; | ||
import { ConfigOptions } from './types/ConfigOptions'; | ||
export declare class RokuDevice { | ||
ip: string; | ||
password: string; | ||
private debugProxy?; | ||
private screenshotFormat; | ||
config?: ConfigOptions; | ||
private needle; | ||
constructor(ip: string, password: string, screenshotFormat?: ScreenshotFormat); | ||
setDebugProxy(debugProxy: string): void; | ||
constructor(config?: ConfigOptions); | ||
getConfig(): import("./types/ConfigOptions").DeviceConfigOptions; | ||
sendECP(path: string, params?: object, body?: needle.BodyData): Promise<needle.NeedleResponse>; | ||
@@ -13,0 +10,0 @@ /** |
@@ -41,13 +41,18 @@ "use strict"; | ||
var querystring = require("needle/lib/querystring"); | ||
var utils = require("./utils"); | ||
var utils_1 = require("./utils"); | ||
var RokuDevice = /** @class */ (function () { | ||
function RokuDevice(ip, password, screenshotFormat) { | ||
if (screenshotFormat === void 0) { screenshotFormat = 'jpg'; } | ||
function RokuDevice(config) { | ||
this.needle = needle; | ||
this.ip = ip; | ||
this.password = password; | ||
this.screenshotFormat = screenshotFormat; | ||
this.config = config; | ||
} | ||
RokuDevice.prototype.setDebugProxy = function (debugProxy) { | ||
this.debugProxy = debugProxy; | ||
RokuDevice.prototype.getConfig = function () { | ||
var _a, _b; | ||
var section = 'RokuDevice'; | ||
if (!this.config) { | ||
var config = utils_1.utils.getConfigFromEnvironment(); | ||
utils_1.utils.validateRTAConfigSchema(config, [section]); | ||
this.config = config; | ||
} | ||
var configSection = (_a = this.config) === null || _a === void 0 ? void 0 : _a[section]; | ||
return configSection.devices[(_b = configSection.deviceIndex) !== null && _b !== void 0 ? _b : 0]; | ||
}; | ||
@@ -58,3 +63,3 @@ RokuDevice.prototype.sendECP = function (path, params, body) { | ||
return __generator(this, function (_a) { | ||
url = "http://" + this.ip + ":8060/" + path; | ||
url = "http://" + this.getConfig().host + ":8060/" + path; | ||
if (params && Object.keys(params).length) { | ||
@@ -93,3 +98,3 @@ url = url.replace(/\?.*|$/, '?' + querystring.build(params)); | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.getScreenshot(utils.getTestTitlePath(contextOrSuite).join('/'))]; | ||
case 0: return [4 /*yield*/, this.getScreenshot(utils_1.utils.getTestTitlePath(contextOrSuite).join('/'))]; | ||
case 1: | ||
@@ -108,3 +113,3 @@ _a.sent(); | ||
case 0: | ||
url = "http://" + this.ip + "/plugin_inspect"; | ||
url = "http://" + this.getConfig().host + "/plugin_inspect"; | ||
data = { | ||
@@ -124,12 +129,14 @@ archive: '', | ||
return __awaiter(this, void 0, void 0, function () { | ||
var options, ext, url, result; | ||
var config, options, ext, url, result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, utils.ensureDirExistForFilePath(outputFilePath)]; | ||
case 0: | ||
config = this.getConfig(); | ||
return [4 /*yield*/, utils_1.utils.ensureDirExistForFilePath(outputFilePath)]; | ||
case 1: | ||
_a.sent(); | ||
options = this.getOptions(true); | ||
ext = "." + this.screenshotFormat; | ||
ext = "." + config.screenshotFormat; | ||
options.output = outputFilePath + ext; | ||
url = "http://" + this.ip + "/pkgs/dev" + ext; | ||
url = "http://" + config.host + "/pkgs/dev" + ext; | ||
return [4 /*yield*/, this.needle('get', url, options)]; | ||
@@ -151,8 +158,7 @@ case 2: | ||
options.username = 'rokudev'; | ||
options.password = this.password; | ||
options.password = this.getConfig().password; | ||
options.auth = 'digest'; | ||
} | ||
if (this.debugProxy) { | ||
options.proxy = this.debugProxy; | ||
} | ||
/** Useful for debugging port 80 and ECP communication between Roku and server */ | ||
options.proxy = ''; | ||
return options; | ||
@@ -159,0 +165,0 @@ }; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var utils = require("../utils"); | ||
var utils_1 = require("../utils"); | ||
var __1 = require("../"); | ||
utils_1.utils.setupEnvironmentFromConfigFile(); | ||
after(function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, utils.shutdownAll()]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
__1.odc.shutdown(); | ||
}); |
@@ -40,3 +40,3 @@ "use strict"; | ||
var fsExtra = require("fs-extra"); | ||
var utils = require("../utils"); | ||
var utils_1 = require("../utils"); | ||
function getMock(mockFilePath) { | ||
@@ -60,3 +60,3 @@ return __awaiter(this, void 0, void 0, function () { | ||
case 0: | ||
mockFilePath = 'src/test/mocks/' + utils.generateFileNameForTest(contextOrSuite, extension); | ||
mockFilePath = 'src/test/mocks/' + utils_1.utils.generateFileNameForTest(contextOrSuite, extension); | ||
return [4 /*yield*/, getMock(mockFilePath)]; | ||
@@ -63,0 +63,0 @@ case 1: |
import { ODCLogLevels } from './OnDeviceComponentRequest'; | ||
export declare enum ConfigBaseKeyEnum { | ||
RokuDevice = 0, | ||
ECP = 1, | ||
OnDeviceComponent = 2 | ||
} | ||
export declare type ConfigBaseKeyTypes = keyof typeof ConfigBaseKeyEnum; | ||
export interface ConfigOptions { | ||
device: DeviceConfigOptions; | ||
channel?: ChannelConfigOptions; | ||
server?: ServerConfigOptions; | ||
defaults?: DefaultConfigOptions; | ||
/** strictly for schema validation not used internally */ | ||
$schema?: string; | ||
RokuDevice: RokuDeviceConfigOptions; | ||
ECP?: ECPConfigOptions; | ||
OnDeviceComponent?: OnDeviceComponentConfigOptions; | ||
} | ||
export interface RokuDeviceConfigOptions { | ||
devices: DeviceConfigOptions[]; | ||
deviceIndex?: number; | ||
} | ||
export interface DeviceConfigOptions { | ||
ip: string; | ||
/** The IP address or hostname of the target Roku device. */ | ||
host: string; | ||
/** The password for logging in to the developer portal on the target Roku device */ | ||
password: string; | ||
debugProxy?: string; | ||
odc?: { | ||
logLevel?: ODCLogLevels; | ||
/** User defined list of properties for this device (name, isLowEnd, etc) */ | ||
properties: {}; | ||
/** Devices default to jpg but if you've changed to png you'll need so supply this */ | ||
screenshotFormat?: 'png' | 'jpg'; | ||
} | ||
export interface ECPConfigOptions { | ||
default?: { | ||
/** The default keyPressDelay to use if not provided at the call site */ | ||
keyPressDelay?: number; | ||
/** The default channel id to launch if one isn't passed in */ | ||
launchChannelId?: string; | ||
}; | ||
screenshotFormat?: ScreenshotFormat; | ||
} | ||
export interface ServerConfigOptions { | ||
callbackListenPort: number; | ||
export interface OnDeviceComponentConfigOptions { | ||
logLevel?: ODCLogLevels; | ||
} | ||
export interface ChannelConfigOptions { | ||
id: string; | ||
} | ||
export interface DefaultECPConfigOptions { | ||
keyPressDelay: number; | ||
} | ||
export interface DefaultConfigOptions { | ||
ecp: DefaultECPConfigOptions; | ||
} | ||
export declare type ScreenshotFormat = 'png' | 'jpg'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var ConfigBaseKeyEnum; | ||
(function (ConfigBaseKeyEnum) { | ||
ConfigBaseKeyEnum[ConfigBaseKeyEnum["RokuDevice"] = 0] = "RokuDevice"; | ||
ConfigBaseKeyEnum[ConfigBaseKeyEnum["ECP"] = 1] = "ECP"; | ||
ConfigBaseKeyEnum[ConfigBaseKeyEnum["OnDeviceComponent"] = 2] = "OnDeviceComponent"; | ||
})(ConfigBaseKeyEnum = exports.ConfigBaseKeyEnum || (exports.ConfigBaseKeyEnum = {})); |
@@ -59,7 +59,6 @@ import * as express from 'express'; | ||
keyPath: string; | ||
value: any; | ||
} | { | ||
value: any; | ||
}; | ||
value: ODCObserveFieldMatchValueTypes; | ||
} | ODCObserveFieldMatchValueTypes; | ||
} | ||
export declare type ODCObserveFieldMatchValueTypes = string | number | boolean; | ||
export interface ODCSetValueAtKeyPathArgs { | ||
@@ -83,5 +82,5 @@ base?: ODCKeyPathBaseTypes; | ||
} | ||
export interface ODCNodeFields { | ||
export interface ODCNodeRepresentation { | ||
id: string; | ||
focusedChild: ODCNodeFields; | ||
focusedChild: ODCNodeRepresentation; | ||
focusable: boolean; | ||
@@ -88,0 +87,0 @@ change: { |
import * as Mocha from 'mocha'; | ||
import { RokuDevice } from './RokuDevice'; | ||
import { ECP } from './ECP'; | ||
import { OnDeviceComponent } from './OnDeviceComponent'; | ||
import { ConfigOptions } from './types/ConfigOptions'; | ||
export declare function readConfigFile(configFilePath?: string): ConfigOptions; | ||
export declare function setupFromConfig(config: ConfigOptions): { | ||
device: RokuDevice; | ||
ecp: ECP; | ||
odc: OnDeviceComponent; | ||
}; | ||
export declare function setupFromConfigFile(configFilePath?: string): { | ||
device: RokuDevice; | ||
ecp: ECP; | ||
odc: OnDeviceComponent; | ||
}; | ||
export declare function shutdownAll(): Promise<void>; | ||
export declare function sleep(milliseconds: number): Promise<unknown>; | ||
export declare function promiseTimeout<T>(promise: Promise<T>, milliseconds: number, message?: string): Promise<T>; | ||
export declare function makeError(name: string, message: string): Error; | ||
export declare function getTestTitlePath(contextOrSuite: Mocha.Context | Mocha.Suite): string[]; | ||
export declare function generateFileNameForTest(contextOrSuite: Mocha.Context | Mocha.Suite, extension: string): string; | ||
export declare function ensureDirExistForFilePath(filePath: string): Promise<void>; | ||
export declare function randomStringGenerator(length?: number): any; | ||
export declare function addRandomPostfix(message: string, length?: number): string; | ||
import { ConfigOptions, DeviceConfigOptions, ConfigBaseKeyTypes } from './types/ConfigOptions'; | ||
declare class Utils { | ||
parseJsonFile(filePath: string): any; | ||
getMatchingDevices(config: ConfigOptions, deviceSelector: {}): { | ||
[key: string]: DeviceConfigOptions; | ||
}; | ||
/** Helper for setting up process.env from a config */ | ||
setupEnvironmentFromConfigFile(configFilePath?: string, deviceSelector?: {} | number): void; | ||
/** Validates the ConfigOptions schema the current class is using | ||
* @param sectionsToValidate - if non empty array will only validate the sections provided instead of the whole schema | ||
*/ | ||
validateRTAConfigSchema(config: any, propertiesToValidate?: ConfigBaseKeyTypes[]): void; | ||
getConfigFromEnvironment(): ConfigOptions; | ||
getOptionalConfigFromEnvironment(): ConfigOptions | undefined; | ||
sleep(milliseconds: number): Promise<unknown>; | ||
promiseTimeout<T>(promise: Promise<T>, milliseconds: number, message?: string): Promise<T>; | ||
makeError(name: string, message: string): Error; | ||
getTestTitlePath(contextOrSuite: Mocha.Context | Mocha.Suite): string[]; | ||
generateFileNameForTest(contextOrSuite: Mocha.Context | Mocha.Suite, extension: string): string; | ||
ensureDirExistForFilePath(filePath: string): Promise<void>; | ||
randomStringGenerator(length?: number): any; | ||
addRandomPostfix(message: string, length?: number): string; | ||
} | ||
declare const utils: Utils; | ||
export { utils }; |
@@ -49,151 +49,143 @@ "use strict"; | ||
var Mocha = require("mocha"); | ||
var RokuDevice_1 = require("./RokuDevice"); | ||
var ECP_1 = require("./ECP"); | ||
var OnDeviceComponent_1 = require("./OnDeviceComponent"); | ||
var ConfigOptions_ti_1 = require("./types/ConfigOptions-ti"); | ||
var ts_interface_checker_1 = require("ts-interface-checker"); | ||
function readConfigFile(configFilePath) { | ||
if (configFilePath === void 0) { configFilePath = 'rta-config.json'; } | ||
var config = JSON.parse(fsExtra.readFileSync(configFilePath, 'utf-8')); | ||
try { | ||
ts_interface_checker_1.createCheckers(ConfigOptions_ti_1.default).ConfigOptions.check(config); | ||
var Ajv = require("ajv"); | ||
var ajv = new Ajv(); | ||
var Utils = /** @class */ (function () { | ||
function Utils() { | ||
} | ||
catch (e) { | ||
throw new Error("Config '" + configFilePath + "' failed validation: " + e.message); | ||
} | ||
return config; | ||
} | ||
exports.readConfigFile = readConfigFile; | ||
var deviceClasses = {}; | ||
function setupFromConfig(config) { | ||
try { | ||
ts_interface_checker_1.createCheckers(ConfigOptions_ti_1.default).ConfigOptions.check(config); | ||
} | ||
catch (e) { | ||
throw new Error("Config failed validation: " + e.message); | ||
} | ||
var deviceConfig = config.device; | ||
if (deviceClasses[deviceConfig.ip]) | ||
return deviceClasses[deviceConfig.ip]; | ||
var device = new RokuDevice_1.RokuDevice(deviceConfig.ip, deviceConfig.password, deviceConfig.screenshotFormat); | ||
if (deviceConfig.debugProxy) { | ||
device.setDebugProxy(deviceConfig.debugProxy); | ||
} | ||
var ecp = new ECP_1.ECP(device, config); | ||
var odc = new OnDeviceComponent_1.OnDeviceComponent(device, config); | ||
var classes = { | ||
device: device, | ||
ecp: ecp, | ||
odc: odc | ||
Utils.prototype.parseJsonFile = function (filePath) { | ||
return JSON.parse(fsExtra.readFileSync(filePath, 'utf-8')); | ||
}; | ||
deviceClasses[deviceConfig.ip] = classes; | ||
return classes; | ||
} | ||
exports.setupFromConfig = setupFromConfig; | ||
function setupFromConfigFile(configFilePath) { | ||
if (configFilePath === void 0) { configFilePath = 'rta-config.json'; } | ||
var config = readConfigFile(configFilePath); | ||
return setupFromConfig(config); | ||
} | ||
exports.setupFromConfigFile = setupFromConfigFile; | ||
function shutdownAll() { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, _b, _i, key, _c, odc, ecp; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
_a = []; | ||
for (_b in deviceClasses) | ||
_a.push(_b); | ||
_i = 0; | ||
_d.label = 1; | ||
case 1: | ||
if (!(_i < _a.length)) return [3 /*break*/, 4]; | ||
key = _a[_i]; | ||
_c = deviceClasses[key], odc = _c.odc, ecp = _c.ecp; | ||
return [4 /*yield*/, ecp.sendKeyPress(ecp.Key.HOME)]; | ||
case 2: | ||
_d.sent(); | ||
odc.shutdown(); | ||
_d.label = 3; | ||
case 3: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 4: return [2 /*return*/]; | ||
Utils.prototype.getMatchingDevices = function (config, deviceSelector) { | ||
var matchingDevices = {}; | ||
config.RokuDevice.devices.forEach(function (device, index) { | ||
for (var key in deviceSelector) { | ||
var requestedValue = deviceSelector[key]; | ||
if (device.properties[key] !== requestedValue) | ||
continue; | ||
} | ||
matchingDevices[index] = device; | ||
}); | ||
}); | ||
} | ||
exports.shutdownAll = shutdownAll; | ||
function sleep(milliseconds) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, milliseconds); }); | ||
} | ||
exports.sleep = sleep; | ||
function promiseTimeout(promise, milliseconds, message) { | ||
var timeout = new Promise(function (resolve, reject) { | ||
setTimeout(function () { | ||
if (message === undefined) { | ||
message = 'Timed out after ' + milliseconds + 'ms.'; | ||
return matchingDevices; | ||
}; | ||
/** Helper for setting up process.env from a config */ | ||
Utils.prototype.setupEnvironmentFromConfigFile = function (configFilePath, deviceSelector) { | ||
if (configFilePath === void 0) { configFilePath = 'rta-config.json'; } | ||
if (deviceSelector === void 0) { deviceSelector = 0; } | ||
var config = this.parseJsonFile(configFilePath); | ||
if (typeof deviceSelector === 'number') { | ||
config.deviceIndex = deviceSelector; | ||
} | ||
else { | ||
var matchingDevices = this.getMatchingDevices(config, deviceSelector); | ||
var keys = Object.keys(matchingDevices); | ||
if (keys.length === 0) { | ||
throw utils.makeError('NoMatchingDevicesFound', 'No devices matched the device selection criteria'); | ||
} | ||
reject(message); | ||
}, milliseconds); | ||
}); | ||
// Returns a race between our timeout and the passed in promise | ||
return Promise.race([ | ||
promise, | ||
timeout | ||
]); | ||
} | ||
exports.promiseTimeout = promiseTimeout; | ||
function makeError(name, message) { | ||
var error = new Error(message); | ||
error.name = name; | ||
return error; | ||
} | ||
exports.makeError = makeError; | ||
function getTestTitlePath(contextOrSuite) { | ||
var ctx; | ||
if (contextOrSuite instanceof Mocha.Context) { | ||
ctx = contextOrSuite; | ||
} | ||
else if (contextOrSuite instanceof Mocha.Suite) { | ||
ctx = contextOrSuite.ctx; | ||
} | ||
else { | ||
throw new Error('Neither Mocha.Context or Mocha.Suite passed in'); | ||
} | ||
if (!(ctx.test instanceof Mocha.Test)) { | ||
throw new Error('Mocha.Context did not contain test. At least surrounding Mocha.Suite must use non arrow function'); | ||
} | ||
return ctx.test.titlePath(); | ||
} | ||
exports.getTestTitlePath = getTestTitlePath; | ||
function generateFileNameForTest(contextOrSuite, extension) { | ||
var titlePath = getTestTitlePath(contextOrSuite); | ||
return titlePath.join('/') + ("." + extension); | ||
} | ||
exports.generateFileNameForTest = generateFileNameForTest; | ||
function ensureDirExistForFilePath(filePath) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fsExtra.ensureDir(path.dirname(filePath))]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
config.deviceIndex = parseInt(keys[0]); | ||
} | ||
process.env.rtaConfig = JSON.stringify(config); | ||
}; | ||
/** Validates the ConfigOptions schema the current class is using | ||
* @param sectionsToValidate - if non empty array will only validate the sections provided instead of the whole schema | ||
*/ | ||
Utils.prototype.validateRTAConfigSchema = function (config, propertiesToValidate) { | ||
if (propertiesToValidate === void 0) { propertiesToValidate = []; } | ||
var _a, _b; | ||
var schema = utils.parseJsonFile('rta-config.schema.json'); | ||
if (propertiesToValidate.length > 0) { | ||
for (var _i = 0, propertiesToValidate_1 = propertiesToValidate; _i < propertiesToValidate_1.length; _i++) { | ||
var key = propertiesToValidate_1[_i]; | ||
if (!ajv.validate(schema.properties[key], config[key])) { | ||
var error = (_a = ajv.errors) === null || _a === void 0 ? void 0 : _a[0]; | ||
throw utils.makeError('ConfigValidationError', "" + key + (error === null || error === void 0 ? void 0 : error.dataPath) + " " + (error === null || error === void 0 ? void 0 : error.message)); | ||
} | ||
} | ||
} | ||
else { | ||
if (!ajv.validate(schema, config)) { | ||
var error = (_b = ajv.errors) === null || _b === void 0 ? void 0 : _b[0]; | ||
throw utils.makeError('ConfigValidationError', (error === null || error === void 0 ? void 0 : error.dataPath) + " " + (error === null || error === void 0 ? void 0 : error.message)); | ||
} | ||
} | ||
}; | ||
Utils.prototype.getConfigFromEnvironment = function () { | ||
var config = this.getOptionalConfigFromEnvironment(); | ||
if (!config) { | ||
throw this.makeError('MissingEnvironmentError', 'Did not contain config at "process.env.rtaConfig"'); | ||
} | ||
return config; | ||
}; | ||
Utils.prototype.getOptionalConfigFromEnvironment = function () { | ||
if (!process.env.rtaConfig) | ||
return undefined; | ||
var config = JSON.parse(process.env.rtaConfig); | ||
return config; | ||
}; | ||
Utils.prototype.sleep = function (milliseconds) { | ||
return new Promise(function (resolve) { return setTimeout(resolve, milliseconds); }); | ||
}; | ||
Utils.prototype.promiseTimeout = function (promise, milliseconds, message) { | ||
var timeout = new Promise(function (resolve, reject) { | ||
setTimeout(function () { | ||
if (message === undefined) { | ||
message = 'Timed out after ' + milliseconds + 'ms.'; | ||
} | ||
reject(message); | ||
}, milliseconds); | ||
}); | ||
}); | ||
} | ||
exports.ensureDirExistForFilePath = ensureDirExistForFilePath; | ||
function randomStringGenerator(length) { | ||
if (length === void 0) { length = 7; } | ||
var p = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
return __spreadArrays(Array(length)).reduce(function (a) { return a + p[~~(Math.random() * p.length)]; }, ''); | ||
} | ||
exports.randomStringGenerator = randomStringGenerator; | ||
function addRandomPostfix(message, length) { | ||
if (length === void 0) { length = 2; } | ||
return message + "-" + randomStringGenerator(length); | ||
} | ||
exports.addRandomPostfix = addRandomPostfix; | ||
// Returns a race between our timeout and the passed in promise | ||
return Promise.race([ | ||
promise, | ||
timeout | ||
]); | ||
}; | ||
Utils.prototype.makeError = function (name, message) { | ||
var error = new Error(message); | ||
error.name = name; | ||
return error; | ||
}; | ||
Utils.prototype.getTestTitlePath = function (contextOrSuite) { | ||
var ctx; | ||
if (contextOrSuite instanceof Mocha.Context) { | ||
ctx = contextOrSuite; | ||
} | ||
else if (contextOrSuite instanceof Mocha.Suite) { | ||
ctx = contextOrSuite.ctx; | ||
} | ||
else { | ||
throw new Error('Neither Mocha.Context or Mocha.Suite passed in'); | ||
} | ||
if (!(ctx.test instanceof Mocha.Test)) { | ||
throw new Error('Mocha.Context did not contain test. At least surrounding Mocha.Suite must use non arrow function'); | ||
} | ||
return ctx.test.titlePath(); | ||
}; | ||
Utils.prototype.generateFileNameForTest = function (contextOrSuite, extension) { | ||
var titlePath = this.getTestTitlePath(contextOrSuite); | ||
return titlePath.join('/') + ("." + extension); | ||
}; | ||
Utils.prototype.ensureDirExistForFilePath = function (filePath) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fsExtra.ensureDir(path.dirname(filePath))]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Utils.prototype.randomStringGenerator = function (length) { | ||
if (length === void 0) { length = 7; } | ||
var p = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
return __spreadArrays(Array(length)).reduce(function (a) { return a + p[~~(Math.random() * p.length)]; }, ''); | ||
}; | ||
Utils.prototype.addRandomPostfix = function (message, length) { | ||
if (length === void 0) { length = 2; } | ||
return message + "-" + this.randomStringGenerator(length); | ||
}; | ||
return Utils; | ||
}()); | ||
var utils = new Utils(); | ||
exports.utils = utils; |
{ | ||
"name": "roku-test-automation", | ||
"version": "1.0.37", | ||
"version": "1.0.38", | ||
"description": "Helps with automating functional tests", | ||
@@ -14,3 +14,3 @@ "main": "dist/index.js", | ||
"test:all": "nyc mocha --full-trace src/**/*.spec.ts", | ||
"buildTypeCheckFiles": "ts-interface-builder src/types/ConfigOptions.ts" | ||
"buildConfigSchema": "typescript-json-schema src/types/ConfigOptions.ts ConfigOptions --out rta-config.schema.json --noExtraProps --refs false" | ||
}, | ||
@@ -28,8 +28,9 @@ "repository": { | ||
"dependencies": { | ||
"ajv": "^6.12.2", | ||
"express": "^4.17.1", | ||
"fs-extra": "^7.0.1", | ||
"http-proxy-middleware": "^1.0.3", | ||
"needle": "^2.3.2", | ||
"path": "^0.12.7", | ||
"ts-interface-checker": "^0.1.10", | ||
"http-proxy-middleware": "^1.0.3" | ||
"portfinder": "^1.0.26" | ||
}, | ||
@@ -47,2 +48,3 @@ "devDependencies": { | ||
"mocha": "^7.2.0", | ||
"mocha-parallel-tests": "^2.3.0", | ||
"nyc": "^14.1.1", | ||
@@ -55,3 +57,4 @@ "rimraf": "^2.7.1", | ||
"tslint": "^5.20.1", | ||
"typescript": "^3.8.3" | ||
"typescript": "^3.8.3", | ||
"typescript-json-schema": "^0.42.0" | ||
}, | ||
@@ -85,5 +88,2 @@ "nyc": { | ||
"mocha": { | ||
"spec": [ | ||
"./src/**/*.spec.ts" | ||
], | ||
"timeout": 5000, | ||
@@ -90,0 +90,0 @@ "file": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
102255
1574
7
20
35
2
0
5
+ Addedajv@^6.12.2
+ Addedportfinder@^1.0.26
+ Addedajv@6.12.6(transitive)
+ Addedasync@2.6.4(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedportfinder@1.0.32(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addeduri-js@4.4.1(transitive)
- Removedts-interface-checker@^0.1.10
- Removedts-interface-checker@0.1.13(transitive)