@hkvstore/taco-cli
Version:
taco-cli is a command-line interface for rapid Apache Cordova development (forked from Microsoft taco-cli)
371 lines (369 loc) • 16.5 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/archiver.d.ts"/>
/// <reference path="../../typings/mocha.d.ts"/>
/// <reference path="../../typings/rimraf.d.ts"/>
/// <reference path="../../typings/should.d.ts"/>
/// <reference path="../../typings/tacoKits.d.ts"/>
/// <reference path="../../typings/tacoUtils.d.ts"/>
/// <reference path="../../typings/wrench.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 archiver = require("archiver");
var fs = require("fs");
var os = require("os");
var path = require("path");
var Q = require("q");
var rimraf = require("rimraf");
var wrench = require("wrench");
var TacoErrorCodes = require("../cli/tacoErrorCodes");
var tacoUtils = require("taco-utils");
var templateManager = require("../cli/utils/templateManager");
var utils = tacoUtils.UtilHelper;
describe("TemplateManager", function () {
// Template info
var testTemplateId = "testTemplate";
var testTemplateId2 = "testTemplate2";
var testTemplateId3 = "testTemplate3";
var testKitId = "testKit";
var testDisplayName = "Blank template for the Default kit";
var testDisplayName2 = "Blank Typescript template for the Default kit";
var testDisplayName3 = "Azure conencted services template for the Default kit";
// Project info
var testAppId = "testId";
var testAppName = "testAppName";
// Important paths
var runFolder = path.resolve(os.tmpdir(), "taco_cli_templates_test_run");
var tacoHome = path.join(runFolder, "taco_home");
var testTemplateKitSrc = path.resolve(__dirname, "resources", "templates", testKitId);
var testTemplateNoWwwPath = path.join(testTemplateKitSrc, testTemplateId);
var testTemplateWithWwwPath = path.join(testTemplateKitSrc, testTemplateId2);
var testTemplateWithGitFilesPath = path.join(testTemplateKitSrc, testTemplateId3);
var testTemplateArchiveFolder = path.join(runFolder, "template-archives", testKitId);
var testTemplateArchive = path.join(testTemplateArchiveFolder, testTemplateId + ".zip");
// ITemplateOverrideInfo objects
var testTemplateOverrideInfo = {
kitId: testKitId,
templateId: testTemplateId,
templateInfo: {
name: testDisplayName,
url: testTemplateArchive
}
};
var testTemplateOverrideInfo2 = {
kitId: testKitId,
templateId: testTemplateId2,
templateInfo: {
name: testDisplayName2,
url: path.join(runFolder, "pathThatDoesntExist")
}
};
var testTemplateOverrideInfo3 = {
kitId: testKitId,
templateId: testTemplateId3,
templateInfo: {
name: testDisplayName3,
url: path.join(runFolder, "pathThatDoesntExist")
}
};
// Mock for the KitHelper
var mockKitHelper = {
getTemplateOverrideInfo: function (kitId, templateId) {
switch (templateId) {
case testTemplateId2:
return Q.resolve(testTemplateOverrideInfo2);
case testTemplateId3:
return Q.resolve(testTemplateOverrideInfo3);
default:
return Q.resolve(testTemplateOverrideInfo);
}
},
getTemplatesForKit: function (kitId) {
var templateOverrides = [testTemplateOverrideInfo, testTemplateOverrideInfo2, testTemplateOverrideInfo3];
var kitTemplatesOverrideInfo = {
kitId: testKitId,
templates: templateOverrides
};
return Q.resolve(kitTemplatesOverrideInfo);
},
getAllTemplates: function () {
var templateOverrides = [testTemplateOverrideInfo, testTemplateOverrideInfo2, testTemplateOverrideInfo3];
return Q.resolve(templateOverrides);
}
};
before(function (done) {
// Set ResourcesManager to test mode
process.env["TACO_UNIT_TEST"] = true;
// Delete existing run folder if necessary
rimraf(runFolder, function (err) {
if (err) {
done(err);
}
else {
// Create the run folder for our tests
wrench.mkdirSyncRecursive(runFolder, 511); // 511 decimal is 0777 octal
// Prepare the test template (archive it)
wrench.mkdirSyncRecursive(testTemplateArchiveFolder, 511); // 511 decimal is 0777 octal
var archive = archiver("zip");
var outputStream = fs.createWriteStream(testTemplateArchive);
archive.on("error", function (archiveError) {
done(archiveError);
});
outputStream.on("close", function () {
done();
});
archive.pipe(outputStream);
archive.bulk({ expand: true, cwd: testTemplateNoWwwPath, src: ["**"] }).finalize();
}
});
});
after(function (done) {
// Delete run folder
rimraf(runFolder, done);
});
describe("acquireFromTacoKits()", function () {
it("should correctly extract a template to a temporary directory", function (done) {
// Create a test TemplateManager
var templates = new templateManager(mockKitHelper, runFolder);
// Call acquireFromTacoKits()
templates.acquireFromTacoKits(testTemplateId, testKitId)
.then(function (tempTemplatePath) {
// Verify the returned path is under the right folder
tempTemplatePath.indexOf(runFolder).should.equal(0);
// Verify the directory starts with the proper prefix
path.basename(tempTemplatePath).indexOf("taco_template_").should.be.equal(0);
// Verify the TemplateManager correctly extracted the template archive to the temporary location
fs.existsSync(path.join(tempTemplatePath, "a.txt")).should.be.exactly(true, "The template was not correctly cached (missing some files)");
fs.existsSync(path.join(tempTemplatePath, "folder1", "b.txt")).should.be.exactly(true, "The template was not correctly cached (missing some files)");
done();
})
.catch(function (err) {
done(new Error(err));
});
});
it("should return the appropriate error when templates are not available", function (done) {
// Create a test TemplateManager
var templates = new templateManager(mockKitHelper, runFolder);
// Call acquireFromTacoKits() with a template ID that has an archive path pointing to a location that doesn't exist
templates.acquireFromTacoKits(testTemplateId3, testKitId)
.then(function (tempTemplatePath) {
// The promise was resolved, this is an error
done(new Error("The operation completed successfully when it should have returned an error"));
}, function (error) {
error.errorCode.should.equal(TacoErrorCodes.CommandCreateTemplatesUnavailable);
done();
})
.catch(function (err) {
done(new Error(err));
});
});
});
describe("performTokenReplacements()", function () {
var replacedLines = [
"some text",
testAppName,
testAppId,
"$appID$",
"$randomToken$$$$",
"more text",
"<xml_node xml_attribute=\"" + testAppName + "\">" + testAppId + "</xml_node>"
];
function verifyFileContent(filePath) {
var lr = new wrench.LineReader(filePath);
var lineNumber = 0;
while (lr.hasNextLine()) {
var currentLine = lr.getNextLine().trim();
var correctLine = replacedLines[lineNumber];
if (currentLine !== correctLine) {
fs.closeSync(lr.fd);
throw new Error("Line wasn't correctly replaced");
}
lineNumber++;
}
fs.closeSync(lr.fd);
}
it("should correctly replace all tokens in all files, recursively", function (done) {
// Copy template items to a new folder
var testProjectPath = path.join(runFolder, "testProject");
wrench.mkdirSyncRecursive(testProjectPath, 511); // 511 decimal is 0777 octal
utils.copyRecursive(testTemplateNoWwwPath, testProjectPath)
.then(function () {
// Call performTokenReplacement()
return templateManager.performTokenReplacements(testProjectPath, testAppId, testAppName);
})
.then(function () {
// Read both text files in the project and ensure replacements were correctly made
var fileA = path.join(testProjectPath, "a.txt");
var fileB = path.join(testProjectPath, "folder1", "b.txt");
verifyFileContent(fileA);
verifyFileContent(fileB);
done();
})
.catch(function (err) {
done(new Error(err));
});
});
});
describe("getTemplatesForKit()", function () {
it("should return the correct list of templates", function (done) {
// Create a test TemplateManager
var templates = new templateManager(mockKitHelper, runFolder);
// Build the expected result
var expectedResult = {
kitId: testKitId,
templates: [
{
id: testTemplateOverrideInfo.templateId,
name: testTemplateOverrideInfo.templateInfo.name
},
{
id: testTemplateOverrideInfo2.templateId,
name: testTemplateOverrideInfo2.templateInfo.name
},
{
id: testTemplateOverrideInfo3.templateId,
name: testTemplateOverrideInfo3.templateInfo.name
}
]
};
var expectedResultStringified = JSON.stringify(expectedResult);
templates.getTemplatesForKit(testKitId)
.then(function (templateList) {
JSON.stringify(templateList).should.equal(expectedResultStringified);
done();
})
.catch(function (err) {
done(new Error(err));
});
});
});
describe("getAllTemplates()", function () {
it("should return all available templates", function (done) {
// Create a test TemplateManager
var templates = new templateManager(mockKitHelper, runFolder);
// Build the expected result
var expectedResult = {
kitId: "",
templates: [
{
id: testTemplateOverrideInfo.templateId,
name: testTemplateOverrideInfo.templateInfo.name
},
{
id: testTemplateOverrideInfo2.templateId,
name: testTemplateOverrideInfo2.templateInfo.name
},
{
id: testTemplateOverrideInfo3.templateId,
name: testTemplateOverrideInfo3.templateInfo.name
}
]
};
var expectedResultStringified = JSON.stringify(expectedResult);
templates.getAllTemplates()
.then(function (templateList) {
JSON.stringify(templateList).should.equal(expectedResultStringified);
done();
})
.catch(function (err) {
done(new Error(err));
});
});
});
describe("getTemplateEntriesCount()", function () {
it("should return the correct count of template entries", function (done) {
// Create a test TemplateManager
var templates = new templateManager(mockKitHelper, runFolder);
// Count entries for the test template and make sure count is as expected
templates.getTemplateEntriesCount(testKitId, testTemplateId)
.then(function (count) {
// We should have 3 items: "a.txt", "folder1" and "folder1/b.txt"
try {
count.should.equal(3);
}
catch (err) {
done(err);
}
done();
});
});
});
describe("copyTemplateItemsToProject()", function () {
var testProjectPath = path.join(runFolder, "testProject");
beforeEach(function () {
rimraf.sync(testProjectPath);
wrench.mkdirSyncRecursive(testProjectPath, 511); // 511 decimal is 0777 octal
});
it("should copy items to the project when the template has a www folder", function (done) {
var templates = new templateManager(mockKitHelper, runFolder);
var cordovaParameters = {
appId: "test",
appName: "test",
cordovaConfig: {},
projectPath: testProjectPath,
copyFrom: testTemplateWithWwwPath
};
templateManager.copyTemplateItemsToProject(cordovaParameters)
.then(function () {
// Since the template has a www folder, a copy should happen; there should be 4 items in the project: "www", "a.txt", "folder1", "b.txt"
try {
wrench.readdirSyncRecursive(testProjectPath).length.should.equal(4);
}
catch (assertException) {
done(assertException);
return;
}
done();
});
});
it("should skip the copy step when the template doesn't have a www folder", function (done) {
var templates = new templateManager(mockKitHelper, runFolder);
var cordovaParameters = {
appId: "test",
appName: "test",
cordovaConfig: {},
projectPath: testProjectPath,
copyFrom: testTemplateNoWwwPath
};
templateManager.copyTemplateItemsToProject(cordovaParameters)
.then(function () {
// Template doesn't have a "www" folder, so the copy step should be skipped and resulting project should be empty
try {
wrench.readdirSyncRecursive(testProjectPath).length.should.equal(0);
}
catch (assertException) {
done(assertException);
return;
}
done();
});
});
it("should ignore git-specific files and .taco-ignore files", function (done) {
var templates = new templateManager(mockKitHelper, runFolder);
var cordovaParameters = {
appId: "test",
appName: "test",
cordovaConfig: {},
projectPath: testProjectPath,
copyFrom: testTemplateWithGitFilesPath
};
templateManager.copyTemplateItemsToProject(cordovaParameters)
.then(function () {
// Since the template has a www folder, a copy should happen; the 3 git files should be ignored, so there should be 4 items in the project: "www", "a.txt", "folder1", "b.txt"
try {
wrench.readdirSyncRecursive(testProjectPath).length.should.equal(4);
}
catch (assertException) {
done(assertException);
return;
}
done();
});
});
});
});
//# sourceMappingURL=templateManager.js.map