@hkvstore/taco-cli
Version:
taco-cli is a command-line interface for rapid Apache Cordova development (forked from Microsoft taco-cli)
260 lines (258 loc) • 11 kB
JavaScript
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
/// <reference path="../../typings/mocha.d.ts" />
/// <reference path="../../typings/node.d.ts" />
/// <reference path="../../typings/should.d.ts" />
/// <reference path="../../typings/tacoTestsUtils.d.ts"/>
;
/* tslint:disable:no-var-requires */
// var require needed for should module to work correctly
// Note not import: We don't want to refer to shouldModule, but we need the require to occur since it modifies the prototype of Object.
var shouldModule = require("should");
/* tslint:enable:no-var-requires */
var fs = require("fs");
var http = require("http");
var os = require("os");
var path = require("path");
var Q = require("q");
var request = require("request");
var rimraf = require("rimraf");
var ConnectionSecurityHelper = require("../cli/remoteBuild/connectionSecurityHelper");
var ServerMock = require("./utils/serverMock");
var Settings = require("../cli/utils/settings");
var RemoteMod = require("../cli/remote");
var RemoteMock = require("./utils/remoteMock");
var TacoUtility = require("taco-utils");
var tacoTestsUtils = require("taco-tests-utils");
var CommandHelper = require("./utils/commandHelper");
var utils = TacoUtility.UtilHelper;
var MemoryStream = tacoTestsUtils.MemoryStream;
var remote = CommandHelper.getCommand("remote");
describe("taco remote", function () {
var testHome = path.join(os.tmpdir(), "taco-cli", "setup");
var tacoSettingsFile = path.join(testHome, "TacoSettings.json");
before(function () {
utils.createDirectoryIfNecessary(testHome);
process.env["TACO_HOME"] = testHome;
process.env["TACO_UNIT_TEST"] = true;
if (fs.existsSync(tacoSettingsFile)) {
fs.unlinkSync(tacoSettingsFile);
}
});
after(function (done) {
if (fs.existsSync(tacoSettingsFile)) {
fs.unlinkSync(tacoSettingsFile);
}
rimraf(testHome, function (err) { done(); }); // ignore errors
});
function makeICommandData(args) {
return {
options: {},
original: args,
remain: args
};
}
var remoteRun = function (args) {
return remote.run(args);
};
it("should save in the expected format", function (mocha) {
var questionsAsked = 0;
var sessionClosed = false;
var desiredState = {
host: "localhost",
port: 3000,
pin: ""
};
var desiredMountPoint = "testMountPoint";
var expectedSequence = [
{
expectedUrl: "/modules/taco-remote",
head: {
"Content-Type": "text/plain"
},
statusCode: 200,
response: desiredMountPoint
}
];
var mockServer = http.createServer();
var serverFunction = ServerMock.generateServerFunction(mocha, expectedSequence);
var cliVersion = require("../package.json").version;
var expectedTelemetryProperties = {
subCommand: { isPii: false, value: "add" },
platform: { isPii: false, value: "ios" },
isSecure: { isPii: false, value: "false" }
};
mockServer.listen(desiredState.port);
mockServer.on("request", serverFunction);
RemoteMod.cliSession = RemoteMock.makeCliMock(mocha, function () { sessionClosed = true; }, desiredState, function () { questionsAsked++; });
Q(["add", "ios"]).then(remoteRun).then(function (telemetryParameters) {
// Verify telemetry properties
telemetryParameters.should.be.eql(expectedTelemetryProperties);
if (questionsAsked !== 3) {
throw new Error("Wrong number of questions asked: " + questionsAsked);
}
else if (!sessionClosed) {
throw new Error("CLI Session not closed");
}
}).then(function () {
return Settings.loadSettings();
}).then(function (data) {
data.remotePlatforms["ios"].should.eql({
host: desiredState.host,
port: desiredState.port,
secure: desiredState.pin !== "",
mountPoint: desiredMountPoint
});
}).finally(function () {
mockServer.close();
}).done(function () {
mocha();
}, mocha);
});
it("should print help for unknown parameters", function (mocha) {
RemoteMod.cliSession = {
question: function (question, callback) {
mocha(new Error("Should not get as far as querying the user with invalid paramters"));
},
close: function () {
mocha(new Error("Should not get as far as querying the user with invalid paramters"));
}
};
Q([]).then(remoteRun).then(function () {
mocha();
}, function (e) {
mocha(new Error("Should have printed help"));
});
});
it("should be able to configure secure connections", function (mocha) {
var mockServer = ServerMock.createSecureTestServer();
var desiredState = {
host: "localhost",
port: 3000,
pin: "123456",
mountPoint: "cordova"
};
var expectedSequence = [
{
expectedUrl: "/certs/" + desiredState.pin,
head: {
"Content-Type": "application/octet-stream"
},
statusCode: 200,
response: fs.readFileSync(path.resolve(__dirname, "resources", "certs", "client.pfx"))
},
{
expectedUrl: "/modules/taco-remote",
head: {
"Content-Type": "text/plain"
},
statusCode: 200,
response: desiredState.mountPoint
},
{
expectedUrl: "/cordova/testCertUsage",
head: {
"Content-Type": "text/plain"
},
statusCode: 200,
response: "success"
}
];
var serverFunction = ServerMock.generateServerFunction(mocha, expectedSequence);
mockServer.listen(desiredState.port);
mockServer.on("request", serverFunction);
RemoteMod.cliSession = RemoteMock.makeCliMock(mocha, utils.emptyMethod, desiredState);
Q(["add", "ios"]).then(remoteRun).then(function () {
return Settings.loadSettings();
}).then(function (data) {
data.remotePlatforms["ios"].should.eql({
host: desiredState.host,
port: desiredState.port,
secure: true,
certName: data.remotePlatforms["ios"].certName,
mountPoint: desiredState.mountPoint
});
return ConnectionSecurityHelper.getAgent(data.remotePlatforms["ios"]).then(function (agent) {
// Now that a cert is configured, try making a secure connection to the (mocked) server to make sure the cert works.
// TODO: Remove the casting once we've get some complete/up-to-date .d.ts files. See https://github.com/Microsoft/TACO/issues/18
var options = {
url: Settings.getRemoteServerUrl(data.remotePlatforms["ios"]) + "/testCertUsage",
headers: { "Accept-Language": "en" },
agent: agent
};
var deferred = Q.defer();
request.get(options, function (err, response, body) {
if (err) {
mocha(err);
}
else {
deferred.resolve({});
}
});
return deferred.promise;
});
}).finally(function () {
mockServer.close();
}).done(function () {
mocha();
}, mocha);
});
describe("Onboarding experience", function () {
// because of function overloading assigning "(buffer: string, cb?: Function) => boolean" as the type for
// stdoutWrite just doesn't work
var stdoutWrite = process.stdout.write; // We save the original implementation, so we can restore it later
var memoryStdout;
beforeEach(function () {
memoryStdout = new MemoryStream; // Each individual test gets a new and empty console
process.stdout.write = memoryStdout.writeAsFunction(); // We'll be printing into an "in-memory" console, so we can test the output
});
after(function () {
// We just need to reset the stdout just once, after all the tests have finished
process.stdout.write = stdoutWrite;
});
// Here you can write to the console with logger.log(...) and then you'll be able to
// retrieve the contents from the memory stream
it("prints the onboarding experience when adding a new remote", function (done) {
var desiredState = {
host: "localhost",
port: 3000,
pin: "",
mountPoint: "testMountPoint"
};
var expectedSequence = [
{
expectedUrl: "/modules/taco-remote",
head: {
"Content-Type": "text/plain"
},
statusCode: 200,
response: desiredState.mountPoint
}
];
var mockServer = http.createServer();
var serverFunction = ServerMock.generateServerFunction(done, expectedSequence);
mockServer.listen(desiredState.port);
mockServer.on("request", serverFunction);
RemoteMod.cliSession = RemoteMock.makeCliMock(done, utils.emptyMethod, desiredState, utils.emptyMethod);
remoteRun(["add", "ios"]).finally(function () {
mockServer.close();
}).done(function () {
var messages = ["CommandRemoteHeader",
"CommandRemoteSettingsStored",
"OnboardingExperienceTitle",
" * HowToUseCommandBuildPlatform",
" * HowToUseCommandEmulatePlatform",
" * HowToUseCommandRunPlatform",
"",
"HowToUseCommandHelp",
"HowToUseCommandDocs",
""]; // Get the expected console output
var expected = messages.join("\n");
var actual = memoryStdout.contentsAsText();
actual.should.be.equal(expected);
done();
}, done);
});
});
});
//# sourceMappingURL=remote.js.map