diff --git a/server/tests/js_tests/libs/dialClient.js b/server/tests/js_tests/libs/dialClient.js index a451a0f..d6d27b5 100644 --- a/server/tests/js_tests/libs/dialClient.js +++ b/server/tests/js_tests/libs/dialClient.js @@ -142,6 +142,31 @@ function launchApplication(host, app, payload) { }); } +function sleepSystem(host, key) { + var keyComponent = key ? `&key=${key}` : ''; + return getAppsUrl(host) + // TODO: Send friendlyName query parameter for DIAL 2.1 and greater versions of server + .then(function (appsUrl) { + var request = { + url: `${appsUrl}/system?action=sleep${keyComponent}`, + method: "POST", + timeout: 6000, + headers: { + "Content-Type" : "text/plain;charset=\"utf-8\"" + } + }; + + return new Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + return resolve(response); + } + return reject(new Error("Error launching application " + error)); + }); + }); + }); +} + function stopApplication(host, app) { return new Q() .then(constructAppResourceUrl.bind(null, host, app)) @@ -164,9 +189,9 @@ function stopApplication(host, app) { return new Q.Promise(function (resolve, reject) { return httpRequest(request, function handleResponse(error, response) { if(!error) { - return resolve(response); + resolve(response); } - return reject(new Error("Error stopping application " + error)); + reject(new Error("Error stopping application " + error)); }); }); }); @@ -254,7 +279,7 @@ function constructAppResourceUrl(host, appName) { return new Q() .then(getAppsUrl.bind(null, host)) .then(function (appUrl) { - return appUrl.replace(/\/+$/, "") + "/" + appName; + return appUrl.replace(/\/+$/, `/${appName}`); }); } @@ -273,7 +298,7 @@ function getAppsUrl(host) { }); if(found) { - return appUrl; + return Promise.resolve(appUrl); } // If value is not persisted @@ -398,3 +423,4 @@ module.exports.hideApplicationInstance = hideApplicationInstance; module.exports.constructAppResourceUrl = constructAppResourceUrl; module.exports.getAppsUrl = getAppsUrl; module.exports.getLocation = getLocation; +module.exports.sleepSystem = sleepSystem; \ No newline at end of file diff --git a/server/tests/js_tests/libs/dialClient.js.orig b/server/tests/js_tests/libs/dialClient.js.orig new file mode 100644 index 0000000..a451a0f --- /dev/null +++ b/server/tests/js_tests/libs/dialClient.js.orig @@ -0,0 +1,400 @@ +"use strict"; + +var ssdp = require("node-ssdp"), + httpRequest = require("request"), + Q = require("q"); + +var Client = ssdp.Client, + client = new Client(); + +var servers = []; // Persist discovered servers + +function discover() { + servers = []; // Re-initialize persisted servers + var dialServers = {}; + // On M-Search response + client.on("response", function (headers) { + if(dialServers[headers.USN] === undefined) { //Resolve duplicates by USN + dialServers[headers.USN] = { + location : headers.LOCATION, + host : headers.LOCATION.split("http://")[1].split(":")[0], + ST : headers.ST + }; + if(headers.WAKEUP) { + var wakeup = headers.WAKEUP; + dialServers[headers.USN].mac = wakeup.split(";")[0].split("=")[1]; + dialServers[headers.USN].timeout = wakeup.split(";")[1].split("=")[1]; + } + + servers.push(dialServers[headers.USN]); + } + }); + + // Send M-Search request + client.search("urn:dial-multiscreen-org:service:dial:1"); + + return new Q.Promise(function (resolve) { + setTimeout(function () { + client.stop(); + return resolve(servers); + }, 5000); + }); +} + +function getApplicationStatus(host, app, clientDialVer) { + clientDialVer = clientDialVer || "2.1"; // To test backward compatibility, 2.1 by default + + return new Q() + .then(constructAppResourceUrl.bind(null, host, app)) + .then(function (appResourceUrl) { + appResourceUrl += clientDialVer === "2.1" ? "?clientDialVer=2.1" : ""; + return appResourceUrl; + }) + .then(function (appResourceUrl) { + return new Q.Promise(function (resolve, reject) { + // Get application status + return httpRequest({ + url: appResourceUrl, + method: "GET", + timeout: 6000 + }, function handleResponse(error, response, body) { + if(!error) { + // Check for correct header and status code + var statusCode = response.statusCode; + var contentType = response.headers["content-type"]; + if(statusCode !== 200) { + return reject(new Error("Expected statusCode 200 while querying application status but got " + statusCode)); + } + if(contentType.indexOf("text/xml") === -1) { + return reject(new Error("Expected MIME type 'text/xml' while querying application status but got " + contentType)); + } + // Extract fields from body + try { + if(body.indexOf("xmlns") === -1 || body.indexOf("") === -1 || body.indexOf("") === -1) { + return reject(new Error("One or more required fields were not present in the application status response")); + } + var parsedResponse = { + "xmlns" : body.split("xmlns=")[1].split(" ")[0].split(">")[0].replace(/\"/g, ""), + "name" : body.split("")[1].split("")[0].replace(/\s/g, ""), + "state" : body.split("")[1].split("")[0].replace(/\s/g, "") + }; + if(parsedResponse.xmlns !== "urn:dial-multiscreen-org:schemas:dial") { + return reject(new Error("xmlns is not 'urn:dial-multiscreen-org:schemas:dial' in the app status response " + parsedResponse.xmlns)); + } + + if(body.indexOf("dialVer") !== -1) { + parsedResponse.dialVer = body.split("dialVer=")[1].split(" ")[0].split(">")[0].replace(/\s/g, "").replace(/\"/g, ""); + } + if(body.indexOf("allowStop") !== -1) { + parsedResponse.allowStop = body.split("")[0].replace(/\s/g, "").replace(/\"/g, ""); + } + if(body.indexOf("")[0].replace(/\"/g, ""); + if(parsedResponse.rel !== "run") { + return reject(new Error("@rel attribute is not 'run' in the application status response")); + } + parsedResponse.href = body.split("href=")[1].split(" ")[0].split("/>")[0].replace(/\s/g, "").replace(/\"/g, ""); + } + if(body.indexOf("") !== -1) { + parsedResponse.additionalData = body.split("")[1].split("")[0].replace(/\s/g, ""); + } + return resolve(parsedResponse); + } + catch (err) { + return reject(new Error("There was a problem extracting one or more fields from application status. Status returned : \n" + body)); + } + } + return reject(new Error("Error retrieving application status " + error)); + }); + }); + }); +} + +function launchApplication(host, app, payload) { + return new Q() + .then(constructAppResourceUrl.bind(null, host, app)) + // TODO: Send friendlyName query parameter for DIAL 2.1 and greater versions of server + .then(function (appResourceUrl) { + var request = { + url: appResourceUrl, + method: "POST", + timeout: 6000, + headers: { + "Content-Type" : "text/plain;charset=\"utf-8\"" + } + }; + if(!payload) { + // Set Content-Length: 0 + request.headers["Content-Length"] = 0; + } + else { + // Set the payload + request.body = payload; + } + return new Q.Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + return resolve(response); + } + return reject(new Error("Error launching application " + error)); + }); + }); + }); +} + +function stopApplication(host, app) { + return new Q() + .then(constructAppResourceUrl.bind(null, host, app)) + .then(function (appResourceUrl) { + return getApplicationStatus(host, app) + .then(function (response) { + if(response.href) { + return appResourceUrl + "/" + response.href; // Construct Application Instance Url + } + return Q.reject(new Error("Could not get attribute @href from application status to construct Application Instance Url. " + + "This means the DIAL server does not support STOP requests for this application.")); + }); + }) + .then(function (appResourceUrl) { + var request = { + url: appResourceUrl, + method: "DELETE", + timeout: 6000 + }; + return new Q.Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + return resolve(response); + } + return reject(new Error("Error stopping application " + error)); + }); + }); + }); +} + +function hideApplication(host, app) { + return new Q() + .then(constructAppResourceUrl.bind(null, host, app)) + .then(function (appResourceUrl) { + return getApplicationStatus(host, app) + .then(function (response) { + if(response.href) { + return appResourceUrl + "/" + response.href + "/hide"; // Construct Application Instance Url + } + return Q.reject(new Error("Could not get instance href from application status to construct Application Instance Url")); + }); + }) + .then(function (appResourceUrl) { + var request = { + url: appResourceUrl, + method: "POST", + timeout: 6000 + }; + return new Q.Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + if(response.statusCode === 501) { + return reject("HIDE request returned 501 NOT IMPLEMENTED. " + + "This means the DIAL server does not support HIDE for this application."); + } + return resolve(response); + } + return reject(new Error("Error hiding application " + error)); + }); + }); + }); +} + +function stopApplicationInstance(instanceUrl) { + return new Q() + .then(function () { + var request = { + url: instanceUrl, + method: "DELETE", + timeout: 6000 + }; + return new Q.Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + return resolve(response); + } + return reject(new Error("Error stopping application " + error)); + }); + }); + }); +} + +function hideApplicationInstance(instanceUrl) { + return new Q() + .then(function () { + var request = { + url: instanceUrl, + method: "POST", + timeout: 6000 + }; + return new Q.Promise(function (resolve, reject) { + return httpRequest(request, function handleResponse(error, response) { + if(!error) { + return resolve(response); + } + return reject(new Error("Error hiding application " + error)); + }); + }); + }); +} + +function constructAppResourceUrl(host, appName) { + if(host === undefined) { + return Q.reject(new Error("Host address is required to construct Application Resource URL")); + } + if(appName === undefined) { + return Q.reject(new Error("Application name is required to construct Application Resource URL")); + } + + return new Q() + .then(getAppsUrl.bind(null, host)) + .then(function (appUrl) { + return appUrl.replace(/\/+$/, "") + "/" + appName; + }); +} + +function getAppsUrl(host) { + if(host === undefined) { + return Q.reject(new Error("Host is required to query for Application-URL")); + } + // Check if value is persisted + var found = false; + var appUrl; + servers.forEach(function (server) { + if(server.host === host && server.appUrl !== undefined) { + found = true; + appUrl = server.appUrl; + } + }); + + if(found) { + return appUrl; + } + + // If value is not persisted + return new Q() + .then(getLocation.bind(null, host)) + .then(function (location) { + return new Q.Promise(function (resolve, reject) { + return httpRequest({ + url: location, + method: "GET", + timeout: 6000 + }, function handleResponse(error, response) { + if(!error && response.statusCode === 200) { + return resolve(response.headers["application-url"]); + } + else if(!error) { + return reject(new Error("Querying for Application-URL returned status code " + response.statusCode)); + } + return reject(new Error("Querying for Application-URL returned " + error)); + }); + }); + }) + // Persist it + .then(function (applicationUrl) { + servers.forEach(function (server) { + if(server.host === host) { + server.appUrl = applicationUrl; + } + }); + return applicationUrl; + }); +} + +function getLocation(host) { + if(host === undefined) { + return Q.reject(new Error("Host address is required to get corresponding LOCATION")); + } + + var found = false; + var location; + + // Check if host is present in persisted list + servers.forEach(function (server) { + if(server.host === host) { + location = server.location; + found = true; + } + }); + if(found) { + return location; + } + + // If not persisted, perform discovery + return new Q() + .then(discoverSpecificHost.bind(null, host)) + .then(function (serverObj) { + return serverObj.location; + }); +} + +function discoverSpecificHost(host) { + if(host === undefined) { + return Q.reject(new Error("Host is required field for discoverSpecificHost function")); + } + + var found = false; + var serverObjFound; + + servers.forEach(function (server) { + if(server.host === host) { + serverObjFound = server; + found = true; + } + }); + + if(found) { + return serverObjFound; + } + return new Q.Promise(function (resolve, reject) { + // On M-Search response + client.on("response", function (headers) { + var extractedHost = headers.LOCATION.split("http://")[1].split(":")[0]; + if(host === extractedHost) { + client.stop(); + var mac, timeout; + if(headers.WAKEUP) { + var wakeup = headers.WAKEUP; + mac = wakeup.split(";")[0].split("=")[1]; + timeout = wakeup.split(";")[1].split("=")[1]; + } + var serverObj = { + location : headers.LOCATION, + host : headers.LOCATION.split("http://")[1].split(":")[0], + ST : headers.ST, + mac : mac, + timeout : timeout + }; + servers.push(serverObj); + clearTimeout(timer); + return resolve(serverObj); + } + }); + + // Send M-Search request + client.search("urn:dial-multiscreen-org:service:dial:1"); + + var timer = setTimeout(function () { + client.stop(); + return reject(new Error("Could not discover host " + host)); + }, 5000); + }); +} + +module.exports.discover = discover; +module.exports.discoverSpecificHost = discoverSpecificHost; +module.exports.getApplicationStatus = getApplicationStatus; +module.exports.launchApplication = launchApplication; +module.exports.stopApplication = stopApplication; +module.exports.hideApplication = hideApplication; +module.exports.stopApplicationInstance = stopApplicationInstance; +module.exports.hideApplicationInstance = hideApplicationInstance; +module.exports.constructAppResourceUrl = constructAppResourceUrl; +module.exports.getAppsUrl = getAppsUrl; +module.exports.getLocation = getLocation; diff --git a/server/tests/js_tests/libs/utils.js b/server/tests/js_tests/libs/utils.js index c54cf1b..f06adfa 100644 --- a/server/tests/js_tests/libs/utils.js +++ b/server/tests/js_tests/libs/utils.js @@ -31,7 +31,7 @@ function consoleFormatter(options) { switch (options.level) { case "error": return colors.red(str); case "warn": return colors.yellow(str); - case "debug": return colors.blue(str); + case "debug": return colors.cyan(str); case "info": default: return str; } @@ -46,12 +46,8 @@ function fileFormatter(options) { function setLogLevel(level) { winston.remove(winston.transports.Console); return winston.add(winston.transports.Console, { - level: "debug", - name: "log_file", - filename: "js_tests_log.txt", - json: false, - formatter: fileFormatter, - options: { flags: "w" } + level: level, + formatter: consoleFormatter }); } diff --git a/server/tests/js_tests/package-lock.json b/server/tests/js_tests/package-lock.json new file mode 100644 index 0000000..9b6e580 --- /dev/null +++ b/server/tests/js_tests/package-lock.json @@ -0,0 +1,784 @@ +{ + "name": "dialtests", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.11" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.21" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.15.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keypress": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", + "integrity": "sha1-HoBFQlABjbrUw/6USX1uZ7YmnHc=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "1.37.0" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node-ssdp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/node-ssdp/-/node-ssdp-3.3.0.tgz", + "integrity": "sha512-hFBkfUJytKC2x64jljojAbktG8aOL0C1YuNjCK54ZGBBg2382J3oTuK17T+aFgmy47noKHE5arLnYppo0JjcLw==", + "requires": { + "async": "2.6.1", + "bluebird": "3.5.2", + "debug": "3.2.6", + "extend": "3.0.2", + "ip": "1.1.5" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.6.0", + "validate-npm-package-license": "3.0.4" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.2" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.3", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.21", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.1" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.1" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "requires": { + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "3.0.2", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "winston": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", + "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "6.6.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "requires": { + "camelcase": "3.0.0" + } + } + } +} diff --git a/server/tests/js_tests/tests/checkStatusofSystemApp.js b/server/tests/js_tests/tests/checkStatusofSystemApp.js new file mode 100644 index 0000000..5a8a1ad --- /dev/null +++ b/server/tests/js_tests/tests/checkStatusofSystemApp.js @@ -0,0 +1,80 @@ +"use strict"; + +var dial = require("../libs/dialClient.js"), + utils = require("../libs/utils.js"); + +const argv = require("yargs") + .usage("\nUsage: node " + __filename.slice(__dirname.length + 1) + "[options]") + .option("host", { + describe: "IP address of host on which DIAL server under test is running", + type: "string", + demand: true + }) + .option("application", { + alias: "app", + describe: "Application to test", + type: "string", + demand: true + }) + .option("timeToWaitForStateChange", { + alias: "ttw", + describe: "Time(ms) to wait between state changes before querying application status", + type: "string", + default: 5000 + }) + .option("logLevel", { + alias: "loglevel", + describe: "The log level for displaying messages to the console, default is `info`', options are info, debug, error, warn", + type: "string", + default: "info" + }) + .help("help").alias("help", "h").argv; + +function test() { + utils.setLogLevel(argv.logLevel); + var host = argv.host; + var systemApp = "system"; + return Promise.resolve() + .then(() => { + utils.printTestInfo(__filename.slice(__dirname.length + 1), `Confirm ${systemApp} is in the hidden state.`); + }) + .then(() => { + utils.printDebug("Querying application state"); + }) + .then(dial.getApplicationStatus.bind(null, host, systemApp)) + .then((result) => { + if (!result || !result.state) { + return Q.reject(new Error("Error retrieving current " + app + " application state")); + } + return result.state; + }) + .then((state) => { + + if (state !== "hidden") { + throw new Error(`The system app should only be in the hidden state but it was in ${state} state.`); + } + else { + utils.printDebug(`Confirmed application is in ${state} state`); + } + }) + .then(() => { + utils.printDebug("Attempting to stop system application."); + }) + .then(dial.stopApplication.bind(null, host, systemApp)) + .then((response) => { + if(response.statusCode !== 403) { + throw new Error(`Tried to stop ${systemApp}. Expected statusCode: 403 but got ${response.statusCode}`); + } + }) + .then(() => { + utils.printTestSuccess() + }) + .catch((err) => { + utils.printTestFailure(err); + }); +} +module.exports.test = test; + +if (require.main === module) { + test(); +} diff --git a/server/tests/js_tests/tests/sleepTheSystemWithKeyWhenItIsRequired.js b/server/tests/js_tests/tests/sleepTheSystemWithKeyWhenItIsRequired.js new file mode 100644 index 0000000..d12ab5f --- /dev/null +++ b/server/tests/js_tests/tests/sleepTheSystemWithKeyWhenItIsRequired.js @@ -0,0 +1,53 @@ +"use strict"; + +var dial = require("../libs/dialClient.js"), + utils = require("../libs/utils.js"); + +const argv = require("yargs") + .usage("\nUsage: node " + __filename.slice(__dirname.length + 1) + "[options]") + .option("host", { + describe: "IP address of host on which DIAL server under test is running", + type: "string", + demand: true + }) + .option("application", { + alias: "app", + describe: "Application to test", + type: "string", + demand: true + }) + .option("timeToWaitForStateChange", { + alias: "ttw", + describe: "Time(ms) to wait between state changes before querying application status", + type: "string", + default: 5000 + }) + .help("help").alias("help", "h").argv; + +function test() { + var host = argv.host; + var key = "TEST"; + return dial.sleepSystem(host, key) + .then(function (response) { + utils.printTestInfo(__filename.slice(__dirname.length + 1), "Sleep the system using DIAL server and key is required and is provided. Expect response code 200."); + return response + }) + .then(function (response) { + + if (response.statusCode !== 200) { + throw new Error(`Error sleeping system while providing required key. Expected to receive a 200 from the DIAL server but instead received ${response.statusCode}`); + } + }) + .then(function () { + utils.printTestSuccess() + }) + .catch(function handleError(err) { + utils.printTestFailure(err); + }); +} + +module.exports.test = test; + +if (require.main === module) { + test(); +} diff --git a/server/tests/js_tests/tests/sleepTheSystemWithNoKeyWhenItIsRequired.js b/server/tests/js_tests/tests/sleepTheSystemWithNoKeyWhenItIsRequired.js new file mode 100644 index 0000000..38a56d9 --- /dev/null +++ b/server/tests/js_tests/tests/sleepTheSystemWithNoKeyWhenItIsRequired.js @@ -0,0 +1,52 @@ +"use strict"; + +var dial = require("../libs/dialClient.js"), + utils = require("../libs/utils.js"); + +const argv = require("yargs") + .usage("\nUsage: node " + __filename.slice(__dirname.length + 1) + "[options]") + .option("host", { + describe: "IP address of host on which DIAL server under test is running", + type: "string", + demand: true + }) + .option("application", { + alias: "app", + describe: "Application to test", + type: "string", + demand: true + }) + .option("timeToWaitForStateChange", { + alias: "ttw", + describe: "Time(ms) to wait between state changes before querying application status", + type: "string", + default: 5000 + }) + .help("help").alias("help", "h").argv; + +function test() { + var host = argv.host; + return dial.sleepSystem(host) + .then(function (response) { + utils.printTestInfo(__filename.slice(__dirname.length + 1), "Sleep the system using DIAL server and key is required but is not provided and check for response code 403."); + return response + }) + .then(function (response) { + + if (response.statusCode !== 403) { + throw new Error(`Error sleeping system without providing required key. Expected to receive a 403 from the DIAL server but instead received ${response.statusCode}`); + } + }) + .then(function () { + utils.printTestSuccess() + }) + .catch(function handleError(err) { + utils.printTestFailure(err); + }); +} + +module.exports.test = test; + +if (require.main === module) { + test(); +} diff --git a/server/tests/js_tests/tests/tests.js b/server/tests/js_tests/tests/tests.js index 0557226..7b0e3b8 100644 --- a/server/tests/js_tests/tests/tests.js +++ b/server/tests/js_tests/tests/tests.js @@ -1,8 +1,8 @@ "use strict"; -var Q = require("q"); +var utils = require("../libs/utils.js"); -const argv = require("yargs") +const argv = require("yargs") .usage("\nUsage: node " + __filename.slice(__dirname.length + 1) + "[options]") .option("host", { describe: "IP address of host on which DIAL server under test is running", @@ -21,45 +21,63 @@ const argv = require("yargs") type: "string", default: 5000 }) + .option("logLevel", { + alias: "loglevel", + describe: "The log level for displaying messages to the console, default is `info`', options are info, debug, error, warn", + type: "string", + default: "info" + }) .help("help").alias("help", "h").argv; -var discoverServerUnderTest = require("../tests/discoverServerUnderTest.js"), - launchApplicationNotRecognized = require("../tests/launchApplicationNotRecognized.js"), +utils.setLogLevel(argv.logLevel); + +var discoverServerUnderTest = require("../tests/discoverServerUnderTest.js"), + launchApplicationNotRecognized = require("../tests/launchApplicationNotRecognized.js"), launchApplicationInRunningStateWithNoPayload = require("../tests/launchApplicationInRunningStateWithNoPayload.js"), - launchApplicationInRunningStateWithPayload = require("../tests/launchApplicationInRunningStateWithPayload.js"), + launchApplicationInRunningStateWithPayload = require("../tests/launchApplicationInRunningStateWithPayload.js"), launchApplicationInStoppedStateWithNoPayload = require("../tests/launchApplicationInStoppedStateWithNoPayload.js"), - launchApplicationInStoppedStateWithPayload = require("../tests/launchApplicationInStoppedStateWithPayload.js"), - launchApplicationInHiddenStateWithNoPayload = require("../tests/launchApplicationInHiddenStateWithNoPayload.js"), - launchApplicationInHiddenStateWithPayload = require("../tests/launchApplicationInHiddenStateWithPayload.js"), - launchApplicationWithExcessPayload = require("../tests/launchApplicationWithExcessPayload.js"), - stopInvalidApplicationInstance = require("../tests/stopInvalidApplicationInstance.js"), - stopApplicationInRunningState = require("../tests/stopApplicationInRunningState.js"), - stopApplicationInStoppedState = require("../tests/stopApplicationInStoppedState.js"), - stopApplicationInHiddenState = require("../tests/stopApplicationInHiddenState.js"), - hideInvalidApplicationInstance = require("../tests/hideInvalidApplicationInstance.js"), - hideApplicationInHiddenState = require("../tests/hideApplicationInHiddenState.js"), - hideApplicationInRunningState = require("../tests/hideApplicationInRunningState.js"); + launchApplicationInStoppedStateWithPayload = require("../tests/launchApplicationInStoppedStateWithPayload.js"), + launchApplicationInHiddenStateWithNoPayload = require("../tests/launchApplicationInHiddenStateWithNoPayload.js"), + launchApplicationInHiddenStateWithPayload = require("../tests/launchApplicationInHiddenStateWithPayload.js"), + launchApplicationWithExcessPayload = require("../tests/launchApplicationWithExcessPayload.js"), + stopInvalidApplicationInstance = require("../tests/stopInvalidApplicationInstance.js"), + stopApplicationInRunningState = require("../tests/stopApplicationInRunningState.js"), + stopApplicationInStoppedState = require("../tests/stopApplicationInStoppedState.js"), + stopApplicationInHiddenState = require("../tests/stopApplicationInHiddenState.js"), + hideInvalidApplicationInstance = require("../tests/hideInvalidApplicationInstance.js"), + hideApplicationInHiddenState = require("../tests/hideApplicationInHiddenState.js"), + hideApplicationInRunningState = require("../tests/hideApplicationInRunningState.js"), + sleepTheSystemWithNoKeyWhenItIsRequired = require("../tests/sleepTheSystemWithNoKeyWhenItIsRequired"), + sleepTheSystemWithKeyWhenItIsRequired = require("../tests/sleepTheSystemWithKeyWhenItIsRequired"); -new Q() - .then(discoverServerUnderTest.test) - // Application launch tests - .then(launchApplicationNotRecognized.test) - .then(launchApplicationInRunningStateWithNoPayload.test) - .then(launchApplicationInRunningStateWithPayload.test) - .then(launchApplicationInStoppedStateWithNoPayload.test) - .then(launchApplicationInStoppedStateWithPayload.test) - .then(launchApplicationInHiddenStateWithNoPayload.test) - .then(launchApplicationInHiddenStateWithPayload.test) - .then(launchApplicationWithExcessPayload.test) +// new Q() +Promise.resolve() + // System/Sleep tests - these force the system into low power mode + .then(sleepTheSystemWithNoKeyWhenItIsRequired.test) + .then(sleepTheSystemWithKeyWhenItIsRequired.test) + + // Discovery Tests + .then(discoverServerUnderTest.test) + + // Application launch tests + .then(launchApplicationNotRecognized.test) + .then(launchApplicationInRunningStateWithNoPayload.test) + .then(launchApplicationInRunningStateWithPayload.test) + // .then(launchApplicationInStoppedStateWithNoPayload.test) + .then(launchApplicationInStoppedStateWithPayload.test) + .then(launchApplicationInHiddenStateWithNoPayload.test) + .then(launchApplicationInHiddenStateWithPayload.test) + .then(launchApplicationWithExcessPayload.test) + + // Application stop tests + .then(stopInvalidApplicationInstance.test) + .then(stopApplicationInRunningState.test) + .then(stopApplicationInStoppedState.test) + .then(stopApplicationInHiddenState.test) + + // Application hide tests + .then(hideInvalidApplicationInstance.test) + .then(hideApplicationInHiddenState.test) + .then(hideApplicationInRunningState.test) - // Application stop tests - .then(stopInvalidApplicationInstance.test) - .then(stopApplicationInRunningState.test) - .then(stopApplicationInStoppedState.test) - .then(stopApplicationInHiddenState.test) - // Application hide tests - .then(hideInvalidApplicationInstance.test) - .then(hideApplicationInHiddenState.test) - .then(hideApplicationInRunningState.test) - .done();