diff --git a/config/config.json b/config/config.json index 10054dee4b..2eae139f10 100644 --- a/config/config.json +++ b/config/config.json @@ -5,5 +5,6 @@ "PROXY_HOSTNAME": "127.0.0.1", "TYPESCRIPT_COMPILER_OPTIONS": {}, "CI_LOGGER": false, - "ANDROID_DEBUG_UI_MAC": "Google Chrome" + "ANDROID_DEBUG_UI_MAC": "Google Chrome", + "USE_POD_SANDBOX": true } \ No newline at end of file diff --git a/lib/config.ts b/lib/config.ts index f11fcf3d25..7c619c2315 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -11,6 +11,7 @@ export class Configuration extends configBaseLib.ConfigBase implements IConfigur TYPESCRIPT_COMPILER_OPTIONS = {}; USE_PROXY = false; ANDROID_DEBUG_UI: string = null; + USE_POD_SANDBOX: boolean = true; /*don't require logger and everything that has logger as dependency in config.js due to cyclic dependency*/ constructor(protected $fs: IFileSystem) { diff --git a/lib/declarations.ts b/lib/declarations.ts index 0d6579ddd5..2d259f8d1e 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -36,6 +36,7 @@ interface IStaticConfig extends Config.IStaticConfig { } interface IConfiguration extends Config.IConfig { ANDROID_DEBUG_UI: string; + USE_POD_SANDBOX: boolean; } interface IApplicationPackage { diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index e26a1a3aed..25b95344b3 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -32,7 +32,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ private $options: IOptions, private $injector: IInjector, $projectDataService: IProjectDataService, - private $prompter: IPrompter) { + private $prompter: IPrompter, + private $config: IConfiguration) { super($fs, $projectData, $projectDataService); } @@ -495,7 +496,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ private executePodInstall(): IFuture { this.$logger.info("Installing pods..."); - return this.$childProcess.spawnFromEvent("pod", ["install"], "close", { cwd: this.platformData.projectRoot, stdio: 'inherit' }); + let podTool = this.$config.USE_POD_SANDBOX ? "sandbox-pod" : "pod"; + return this.$childProcess.spawnFromEvent(podTool, ["install"], "close", { cwd: this.platformData.projectRoot, stdio: 'inherit' }); } private prepareFrameworks(pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture { diff --git a/package.json b/package.json index e723379d9b..8b9d727a8e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "main": "./lib/nativescript-cli.js", "scripts": { - "test": "node_modules/.bin/istanbul cover node_modules/mocha/bin/_mocha -- --ui mocha-fibers --recursive --reporter spec --require test/test-bootstrap.js --timeout 60000 test/ lib/common/test/unit-tests", + "test": "node_modules/.bin/istanbul cover node_modules/mocha/bin/_mocha -- --ui mocha-fibers --recursive --reporter spec --require test/test-bootstrap.js --timeout 150000 test/ lib/common/test/unit-tests", "postinstall": "node postinstall.js", "preuninstall": "node preuninstall.js" }, diff --git a/test/project-service.ts b/test/project-service.ts index 682ab35749..ae7d25f867 100644 --- a/test/project-service.ts +++ b/test/project-service.ts @@ -4,22 +4,24 @@ import yok = require('../lib/common/yok'); import stubs = require('./stubs'); import * as constants from "./../lib/constants"; -import * as ChildProcessLib from "../lib/common/child-process"; +import {ChildProcess} from "../lib/common/child-process"; import * as ProjectServiceLib from "../lib/services/project-service"; import * as ProjectDataServiceLib from "../lib/services/project-data-service"; import * as ProjectDataLib from "../lib/project-data"; import * as ProjectHelperLib from "../lib/common/project-helper"; -import * as StaticConfigLib from "../lib/config"; +import {StaticConfig} from "../lib/config"; import * as NpmLib from "../lib/node-package-manager"; -import * as NpmInstallationManagerLib from "../lib/npm-installation-manager"; +import {NpmInstallationManager} from "../lib/npm-installation-manager"; import * as HttpClientLib from "../lib/common/http-client"; -import * as fsLib from "../lib/common/file-system"; +import {FileSystem} from "../lib/common/file-system"; import * as path from "path"; import temp = require("temp"); import * as helpers from "../lib/common/helpers"; import {assert} from "chai"; -import * as optionsLib from "../lib/options"; -import * as hostInfoLib from "../lib/common/host-info"; +import {Options} from "../lib/options"; +import {HostInfo} from "../lib/common/host-info"; +import {IOSProjectService} from "../lib/services/ios-project-service"; +import * as shell from "shelljs"; let mockProjectNameValidator = { validate: () => { return true; } @@ -39,21 +41,20 @@ class ProjectIntegrationTest { return projectService.createProject(projectName); } - public getDefaultTemplatePath(): IFuture { + public getNpmPackagePath(packageName: string): IFuture { return (() => { let npmInstallationManager = this.testInjector.resolve("npmInstallationManager"); let fs = this.testInjector.resolve("fs"); - let defaultTemplatePackageName = "tns-template-hello-world"; let cacheRoot = npmInstallationManager.getCacheRootPath(); - let defaultTemplatePath = path.join(cacheRoot, defaultTemplatePackageName); - let latestVersion = npmInstallationManager.getLatestVersion(defaultTemplatePackageName).wait(); + let defaultTemplatePath = path.join(cacheRoot, packageName); + let latestVersion = npmInstallationManager.getLatestVersion(packageName).wait(); if(!fs.exists(path.join(defaultTemplatePath, latestVersion)).wait()) { - npmInstallationManager.addToCache(defaultTemplatePackageName, latestVersion).wait(); + npmInstallationManager.addToCache(packageName, latestVersion).wait(); } if(!fs.exists(path.join(defaultTemplatePath, latestVersion, "package", "app")).wait()) { - npmInstallationManager.cacheUnpack(defaultTemplatePackageName, latestVersion).wait(); + npmInstallationManager.cacheUnpack(packageName, latestVersion).wait(); } return path.join(defaultTemplatePath, latestVersion, "package"); @@ -103,7 +104,7 @@ class ProjectIntegrationTest { private createTestInjector(): void { this.testInjector = new yok.Yok(); - this.testInjector.register("childProcess", ChildProcessLib.ChildProcess); + this.testInjector.register("childProcess", ChildProcess); this.testInjector.register("errors", stubs.ErrorsStub); this.testInjector.register('logger', stubs.LoggerStub); this.testInjector.register("projectService", ProjectServiceLib.ProjectService); @@ -111,18 +112,17 @@ class ProjectIntegrationTest { this.testInjector.register("projectTemplatesService", stubs.ProjectTemplatesService); this.testInjector.register("projectNameValidator", mockProjectNameValidator); - this.testInjector.register("fs", fsLib.FileSystem); + this.testInjector.register("fs", FileSystem); this.testInjector.register("projectDataService", ProjectDataServiceLib.ProjectDataService); - this.testInjector.register("staticConfig", StaticConfigLib.StaticConfig); + this.testInjector.register("staticConfig", StaticConfig); - this.testInjector.register("npmInstallationManager", NpmInstallationManagerLib.NpmInstallationManager); + this.testInjector.register("npmInstallationManager", NpmInstallationManager); this.testInjector.register("npm", NpmLib.NodePackageManager); this.testInjector.register("httpClient", HttpClientLib.HttpClient); - this.testInjector.register("config", {}); this.testInjector.register("lockfile", stubs.LockFile); - this.testInjector.register("options", optionsLib.Options); - this.testInjector.register("hostInfo", hostInfoLib.HostInfo); + this.testInjector.register("options", Options); + this.testInjector.register("hostInfo", HostInfo); } } @@ -135,7 +135,7 @@ describe("Project Service Tests", () => { let options = projectIntegrationTest.testInjector.resolve("options"); options.path = tempFolder; - options.copyFrom = projectIntegrationTest.getDefaultTemplatePath().wait(); + options.copyFrom = projectIntegrationTest.getNpmPackagePath("tns-template-hello-world").wait(); projectIntegrationTest.createProject(projectName).wait(); projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp").wait(); @@ -147,12 +147,50 @@ describe("Project Service Tests", () => { let options = projectIntegrationTest.testInjector.resolve("options"); options.path = tempFolder; - options.copyFrom = projectIntegrationTest.getDefaultTemplatePath().wait(); + options.copyFrom = projectIntegrationTest.getNpmPackagePath("tns-template-hello-world").wait(); options.appid = "my.special.id"; projectIntegrationTest.createProject(projectName).wait(); projectIntegrationTest.assertProject(tempFolder, projectName, options.appid).wait(); }); + it("creates ios project and tests post-install sandboxing of CocoaPods setup", () => { + if (require("os").platform() !== "darwin") { + console.log("Skipping CocoaPods sandbox test. It works only on darwin."); + return; + } + + let testDirectoryPath = "/tmp/Podfile"; + let testInjector = createInjectorForPodsTest(); + let iOSProjectService: IPlatformProjectService = testInjector.resolve("iOSProjectService"); + let fs: IFileSystem = testInjector.resolve("fs"); + let projectIntegrationTest = new ProjectIntegrationTest(); + let workingFolderPath = temp.mkdirSync("ios_project"); + let iosTemplatePath = path.join(projectIntegrationTest.getNpmPackagePath("tns-ios").wait(), "framework/"); + let postInstallCommmand = `\`cat ${testDirectoryPath}/testFile.txt > ${workingFolderPath}/copyTestFile.txt && rm -rf ${testDirectoryPath}\``; + let podfileContent = `post_install do |installer_representation| ${postInstallCommmand} end`; + let platformData = iOSProjectService.platformData; + + shell.cp("-R", iosTemplatePath, workingFolderPath); + + fs.writeFile(`${testDirectoryPath}/testFile.txt`, "Test content.").wait(); + fs.writeFile(path.join(workingFolderPath, "Podfile"), podfileContent).wait(); + + Object.defineProperty(iOSProjectService, "platformData", { + get: () => { + return { projectRoot: workingFolderPath }; + } + }); + + try { + iOSProjectService.afterPrepareAllPlugins().wait(); + } finally { + Object.defineProperty(iOSProjectService, "platformData", platformData); + } + + assert.isTrue(fs.exists(testDirectoryPath).wait()); + assert.isTrue(fs.exists(path.join(workingFolderPath, "copyTestFile.txt")).wait()); + fs.deleteDirectory(testDirectoryPath).wait(); // Clean up 'tmp' after test ends. + }); }); }); @@ -166,21 +204,56 @@ function createTestInjector() { testInjector.register("projectTemplatesService", stubs.ProjectTemplatesService); testInjector.register("projectNameValidator", mockProjectNameValidator); - testInjector.register("fs", fsLib.FileSystem); + testInjector.register("fs", FileSystem); testInjector.register("projectDataService", ProjectDataServiceLib.ProjectDataService); - testInjector.register("staticConfig", StaticConfigLib.StaticConfig); + testInjector.register("staticConfig", StaticConfig); - testInjector.register("npmInstallationManager", NpmInstallationManagerLib.NpmInstallationManager); + testInjector.register("npmInstallationManager", NpmInstallationManager); testInjector.register("httpClient", HttpClientLib.HttpClient); - testInjector.register("config", {}); testInjector.register("lockfile", stubs.LockFile); - testInjector.register("childProcess", ChildProcessLib.ChildProcess); + testInjector.register("childProcess", ChildProcess); testInjector.register('projectData', ProjectDataLib.ProjectData); - testInjector.register("options", optionsLib.Options); - testInjector.register("hostInfo", hostInfoLib.HostInfo); + testInjector.register("options", Options); + testInjector.register("hostInfo", HostInfo); + + return testInjector; +} + +function createInjectorForPodsTest() { + let testInjector = new yok.Yok(); + + testInjector.register("errors", stubs.ErrorsStub); + testInjector.register('logger', stubs.LoggerStub); + testInjector.register("projectHelper", {}); + testInjector.register("projectData", { + projectName: "__PROJECT_NAME__", + platformsDir: "" + }); + testInjector.register("iOSEmulatorServices", {}); + testInjector.register("config", { + "USE_POD_SANDBOX": true + }); + testInjector.register("prompter", {}); + testInjector.register("fs", FileSystem); + testInjector.register("staticConfig", StaticConfig); + testInjector.register("npmInstallationManager", NpmInstallationManager); + testInjector.register("iOSProjectService", IOSProjectService); + testInjector.register("projectService", ProjectServiceLib.ProjectService); + testInjector.register("pluginsService", { + getAllInstalledPlugins: () => { + return (() => { + return []; + }).future()(); + } + }); + testInjector.register("fs", FileSystem); + testInjector.register("projectDataService", ProjectDataServiceLib.ProjectDataService); + testInjector.register("options", Options); + testInjector.register("hostInfo", HostInfo); + testInjector.register("childProcess", ChildProcess); return testInjector; }