From 78313520bd8872bc16ec171c4189b2294f728c4e Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Wed, 9 Mar 2016 10:38:04 +0200 Subject: [PATCH 1/3] Update requirement for Android Build Tools Set minimum required Android Build Tools 23.0.0 --- lib/android-tools-info.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android-tools-info.ts b/lib/android-tools-info.ts index 2e04ac4ae6..9b2b794cdf 100644 --- a/lib/android-tools-info.ts +++ b/lib/android-tools-info.ts @@ -9,7 +9,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo { private static ANDROID_TARGET_PREFIX = "android"; private static SUPPORTED_TARGETS = ["android-17", "android-18", "android-19", "android-21", "android-22", "android-23"]; private static MIN_REQUIRED_COMPILE_TARGET = 22; - private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=22"; + private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23"; private static VERSION_REGEX = /((\d+\.){2}\d+)/; private static MIN_JAVA_VERSION = "1.7.0"; @@ -278,7 +278,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo { selectedVersion = _.find(subDirs, dir => dir.indexOf(version) !== -1); } } - + this.$logger.trace("Selected version is: ", selectedVersion); return selectedVersion; }).future()(); } From b8a305047c1a7ccd2ed4663b5ff2612587026360 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Wed, 9 Mar 2016 12:22:47 +0200 Subject: [PATCH 2/3] Verify JAVA_HOME is set correctly Our system requirements point that JAVA_HOME must be set, but `tns doctor` is not strict about this. With version 1.7.0 of the runtime, `jarsigner` from $JAVA_HOME/bin/jarsigner will be called explicitly, so we must be sure JAVA_HOME is correct. `jarsigner` does not exist in JRE, so add logic to call it in order to verify that the currently set JAVA_HOME is correct. Validate the information in the following order: 1) Check if JAVA_HOME is set. In case it is not, you cannot build for Android (`tns build android` will fail before starting). 2) Check if JAVA_HOME is correct by executing JAVA_HOME/bin/jarsigner - in case it does not exist - fail 3) Check if the version of the JAVA is correct by calling JAVA_HOME/bin/javac -version and compare it with min required one. In case it's lower - fail. `tns doctor` will print warning in case any of the above check fails. `tns build android` and any other Android related build operations will fail. --- lib/android-tools-info.ts | 57 ++++++++++++++++++++----- lib/declarations.ts | 6 +-- lib/services/android-project-service.ts | 2 +- lib/services/doctor-service.ts | 2 +- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/lib/android-tools-info.ts b/lib/android-tools-info.ts index 9b2b794cdf..afbf5eeb54 100644 --- a/lib/android-tools-info.ts +++ b/lib/android-tools-info.ts @@ -156,30 +156,65 @@ export class AndroidToolsInfo implements IAndroidToolsInfo { }).future()(); } - public validateJavacVersion(installedJavaVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture { + public validateJava(javacVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture { return ((): boolean => { - let hasProblemWithJavaVersion = false; if(options) { this.showWarningsAsErrors = options.showWarningsAsErrors; } - let additionalMessage = "You will not be able to build your projects for Android." + EOL + + let helpfulMessage = "You will not be able to build your projects for Android." + EOL + "To be able to build for Android, verify that you have installed The Java Development Kit (JDK) and configured it according to system requirements as" + EOL + " described in https://github.com/NativeScript/nativescript-cli#system-requirements."; - let matchingVersion = (installedJavaVersion || "").match(AndroidToolsInfo.VERSION_REGEX); - if(matchingVersion && matchingVersion[1]) { - if(semver.lt(matchingVersion[1], AndroidToolsInfo.MIN_JAVA_VERSION)) { - hasProblemWithJavaVersion = true; - this.printMessage(`Javac version ${installedJavaVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, additionalMessage); + + let hasProblemWithJavaHome = this.validateJavaHome(helpfulMessage).wait(); + let hasProblemWithJavaVersion: boolean; + if(!hasProblemWithJavaHome) { + hasProblemWithJavaVersion = this.validateJavacVersion(javacVersion, helpfulMessage); + } + + return hasProblemWithJavaHome || hasProblemWithJavaVersion; + }).future()(); + } + + private validateJavaHome(helpfulMessage: string): IFuture { + return ((): boolean => { + let hasProblemWithJavaHome = false; + let javaHome = process.env.JAVA_HOME; + + if(javaHome) { + // validate jarsigner as it does not exist in JRE, but is mandatory for JDK and Android Runtime + let jarSigner = path.join(javaHome, "bin", "jarsigner"); + let childProcessResult = this.$childProcess.spawnFromEvent(jarSigner, [], "close", {}, { throwError: false }).wait(); + this.$logger.trace(`Result of calling jarsigner from path: ${jarSigner}:`, childProcessResult); + if(childProcessResult.stderr || childProcessResult.exitCode !== 0) { + hasProblemWithJavaHome = true; + this.printMessage("JAVA_HOME environment variable points to incorrect path. Make sure it points to the installation directory of JDK.", helpfulMessage); } } else { - hasProblemWithJavaVersion = true; - this.printMessage("Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable.", additionalMessage); + hasProblemWithJavaHome = true; + this.printMessage("JAVA_HOME environment variable is not set.", helpfulMessage); } - return hasProblemWithJavaVersion; + return hasProblemWithJavaHome; }).future()(); } + private validateJavacVersion(installedJavaVersion: string, helpfulMessage: string): boolean { + let hasProblemWithJavaVersion = false; + let matchingVersion = (installedJavaVersion || "").match(AndroidToolsInfo.VERSION_REGEX); + if(matchingVersion && matchingVersion[1]) { + if(semver.lt(matchingVersion[1], AndroidToolsInfo.MIN_JAVA_VERSION)) { + hasProblemWithJavaVersion = true; + this.printMessage(`Javac version ${installedJavaVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, helpfulMessage); + } + } else { + hasProblemWithJavaVersion = true; + this.printMessage("Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable.", helpfulMessage); + } + + return hasProblemWithJavaVersion; + } + public getPathToAdbFromAndroidHome(): IFuture { return (() => { if(this.androidHome) { diff --git a/lib/declarations.ts b/lib/declarations.ts index bd2a9dc91c..581830a2be 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -160,12 +160,12 @@ interface IAndroidToolsInfo { validateInfo(options?: {showWarningsAsErrors: boolean, validateTargetSdk: boolean}): IFuture; /** - * Validates the information about required JAVA version. - * @param {string} installedJavaVersion The JAVA version that will be checked. + * Validates the information about required JAVA version and JAVA_HOME. + * @param {string} javacVersion The JAVA version that will be checked. * @param {any} options Defines if the warning messages should treated as error. * @return {boolean} True if there are detected issues, false otherwise. */ - validateJavacVersion(installedJavaVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture; + validateJava(javacVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture; /** * Returns the path to `android` executable. It should be `$ANDROID_HOME/tools/android`. diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 777db27d25..ebd521ed9f 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -88,7 +88,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject // this call will fail in case `android` is not set correctly. this.$androidToolsInfo.getPathToAndroidExecutable({showWarningsAsErrors: true}).wait(); - this.$androidToolsInfo.validateJavacVersion(this.$sysInfo.getSysInfo(path.join(__dirname, "..", "..", "package.json")).wait().javacVersion, {showWarningsAsErrors: true}).wait(); + this.$androidToolsInfo.validateJava(this.$sysInfo.getSysInfo(path.join(__dirname, "..", "..", "package.json")).wait().javacVersion, {showWarningsAsErrors: true}).wait(); }).future()(); } diff --git a/lib/services/doctor-service.ts b/lib/services/doctor-service.ts index edb32b1a24..3a66f3d767 100644 --- a/lib/services/doctor-service.ts +++ b/lib/services/doctor-service.ts @@ -87,7 +87,7 @@ class DoctorService implements IDoctorService { } let androidToolsIssues = this.$androidToolsInfo.validateInfo().wait(); - let javaVersionIssue = this.$androidToolsInfo.validateJavacVersion(sysInfo.javacVersion).wait(); + let javaVersionIssue = this.$androidToolsInfo.validateJava(sysInfo.javacVersion).wait(); return result || androidToolsIssues || javaVersionIssue; } From 2c52a3452cc70ec06c7f3af6c8f13d6807adf9ef Mon Sep 17 00:00:00 2001 From: Rosen Vladimirov Date: Sat, 20 Feb 2016 16:30:39 +0200 Subject: [PATCH 3/3] Add support for custom platform templates Add new option when adding platform: `--platform-template`. When it is used, CLI will use the specified template instead of the default template from the runtime. The path to the specified template will be saved in project's package.json, so next time when platform is added, the same template will be used. In case when `--platform-template` is not passed, CLI will check the package.json and if there's value for the template, it will be used. Otherwise the default template from runtime will be used. --- .../project/configuration/platform-add.md | 22 ++++---- lib/declarations.ts | 1 + lib/definitions/project.d.ts | 2 +- lib/nativescript-cli.ts | 1 + lib/options.ts | 3 +- lib/services/android-project-service.ts | 10 +++- lib/services/ios-project-service.ts | 11 ++-- lib/services/platform-service.ts | 50 +++++++++++++++++-- test/platform-commands.ts | 1 + test/platform-service.ts | 1 + 10 files changed, 81 insertions(+), 21 deletions(-) diff --git a/docs/man_pages/project/configuration/platform-add.md b/docs/man_pages/project/configuration/platform-add.md index 8e7458f310..332439f8fd 100644 --- a/docs/man_pages/project/configuration/platform-add.md +++ b/docs/man_pages/project/configuration/platform-add.md @@ -3,26 +3,28 @@ platform add Usage | Synopsis ------|------- -Android latest runtime | `$ tns platform add android [--frameworkPath ] [--symlink] [--sdk ]` -Android selected runtime | `$ tns platform add android[@] [--frameworkPath ] [--symlink] [--sdk ]` +Android latest runtime | `$ tns platform add android [--frameworkPath ] [--symlink] [--sdk ] [--platformTemplate ]` +Android selected runtime | `$ tns platform add android[@] [--frameworkPath ] [--symlink] [--sdk ] [--platformTemplate ]` <% if (isMacOS) { %>iOS latest runtime | `$ tns platform add ios [--frameworkPath ] [--symlink]` -iOS selected runtime | `$ tns platform add ios[@] [--frameworkPath ] [--symlink]`<% } %> +iOS selected runtime | `$ tns platform add ios[@] [--frameworkPath ] [--symlink] [--platformTemplate ]`<% } %> -Configures the current project to target the selected platform. <% if(isHtml) { %>When you add a target platform, the NativeScript CLI adds a corresponding platform-specific subdirectory under the platforms directory. This platform-specific directory contains the necessary files to let you build your project for the target platform.<% } %> +Configures the current project to target the selected platform. <% if(isHtml) { %>When you add a target platform, the NativeScript CLI adds a corresponding platform-specific subdirectory under the platforms directory. This platform-specific directory contains the necessary files to let you build your project for the target platform.<% } %> ### Options -* `--frameworkPath` - Sets the path to a NativeScript runtime for the specified platform that you want to use instead of the default runtime. If `--symlink` is specified, `` must point to directory in which the runtime is already extracted. If `--symlink` is not specified, `` must point to a valid npm package. +* `--frameworkPath` - Sets the path to a NativeScript runtime for the specified platform that you want to use instead of the default runtime. If `--symlink` is specified, `` must point to directory in which the runtime is already extracted. If `--symlink` is not specified, `` must point to a valid npm package. * `--symlink` - Creates a symlink to a NativeScript runtime for the specified platform that you want to use instead of the default runtime. If `--frameworkPath` is specified, creates a symlink to the specified directory. If `--frameworkPath` is not specified, creates a symlink to platform runtime installed with your current version of NativeScript. * `--sdk` - Sets the target Android SDK for the project. +* `--platformTemplate` - Sets the Android/iOS template that will be used for the native application. ### Attributes * `` is a valid Android API level. For example: 17, 19, MNC.<% if(isHtml) { %> For a complete list of the Android API levels and their corresponding Android versions, click [here](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#platform).<% } %> * `` is the complete path to a valid npm package or a directory that contains a NativeScript runtime for the selected platform. -* `` is any available version of the respective platform runtime published in npm. <% if(isHtml) { %>If `@` is not specified, the NativeScript CLI installs the latest stable runtime for the selected platform. -To list all available versions for Android, run `$ npm view tns-android versions` -To list only experimental versions for Android, run `$ npm view tns-android dist-tags` -To list all available versions for iOS, run `$ npm view tns-ios versions` -To list only experimental versions for iOS, run `$ npm view tns-ios dist-tags` +* `` is a valid npm package, path to directory, .tgz or GitHub URL that contains native Android/iOS template. +* `` is any available version of the respective platform runtime published in npm. <% if(isHtml) { %>If `@` is not specified, the NativeScript CLI installs the latest stable runtime for the selected platform. +To list all available versions for Android, run `$ npm view tns-android versions` +To list only experimental versions for Android, run `$ npm view tns-android dist-tags` +To list all available versions for iOS, run `$ npm view tns-ios versions` +To list only experimental versions for iOS, run `$ npm view tns-ios dist-tags` ### Command Limitations diff --git a/lib/declarations.ts b/lib/declarations.ts index 581830a2be..9fab8767ca 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -83,6 +83,7 @@ interface IOptions extends ICommonOptions { port: Number; copyTo: string; baseConfig: string; + platformTemplate: string; } interface IInitService { diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index f282b8ad1b..563a47cb65 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -69,7 +69,7 @@ interface IiOSBuildConfig extends IBuildConfig { interface IPlatformProjectService { platformData: IPlatformData; validate(): IFuture; - createProject(frameworkDir: string, frameworkVersion: string): IFuture; + createProject(frameworkDir: string, frameworkVersion: string, pathToTemplate?: string): IFuture; interpolateData(): IFuture; interpolateConfigurationFile(configurationFilePath?: string): IFuture; afterCreateProject(projectRoot: string): IFuture; diff --git a/lib/nativescript-cli.ts b/lib/nativescript-cli.ts index a06792c38f..3e7d989aee 100644 --- a/lib/nativescript-cli.ts +++ b/lib/nativescript-cli.ts @@ -9,6 +9,7 @@ import * as fiber from "fibers"; import Future = require("fibers/future"); import * as shelljs from "shelljs"; shelljs.config.silent = true; +shelljs.config.fatal = true; import {installUncaughtExceptionListener} from "./common/errors"; installUncaughtExceptionListener(process.exit); diff --git a/lib/options.ts b/lib/options.ts index 26b8857c29..2b9311b4b1 100644 --- a/lib/options.ts +++ b/lib/options.ts @@ -34,7 +34,8 @@ export class Options extends commonOptionsLibPath.OptionsBase { compileSdk: {type: OptionType.Number }, port: { type: OptionType.Number }, copyTo: { type: OptionType.String }, - baseConfig: { type: OptionType.String } + baseConfig: { type: OptionType.String }, + platformTemplate: { type: OptionType.String } }, path.join($hostInfo.isWindows ? process.env.AppData : path.join(osenv.home(), ".local/share"), ".nativescript-cli"), $errors, $staticConfig); diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index ebd521ed9f..b5aa5d3b2a 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -92,7 +92,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject }).future()(); } - public createProject(frameworkDir: string, frameworkVersion: string): IFuture { + public createProject(frameworkDir: string, frameworkVersion: string, pathToTemplate?: string): IFuture { return (() => { if(semver.lt(frameworkVersion, AndroidProjectService.MIN_RUNTIME_VERSION_WITH_GRADLE)) { this.$errors.failWithoutHelp(`The NativeScript CLI requires Android runtime ${AndroidProjectService.MIN_RUNTIME_VERSION_WITH_GRADLE} or later to work properly.`); @@ -111,7 +111,13 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } // These files and directories should not be symlinked as CLI is modifying them and we'll change the original values as well. - this.copy(this.platformData.projectRoot, frameworkDir, "src", "-R"); + if(pathToTemplate) { + let mainPath = path.join(this.platformData.projectRoot, "src", "main"); + this.$fs.createDirectory(mainPath).wait(); + shell.cp("-R", path.join(path.resolve(pathToTemplate), "*"), mainPath); + } else { + this.copy(this.platformData.projectRoot, frameworkDir, "src", "-R"); + } this.copy(this.platformData.projectRoot, frameworkDir, "build.gradle settings.gradle gradle.properties", "-f"); if (this.useGradleWrapper(frameworkDir)) { diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 6489528c74..345535ae5b 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -104,10 +104,16 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ }).future()(); } - public createProject(frameworkDir: string, frameworkVersion: string): IFuture { + public createProject(frameworkDir: string, frameworkVersion: string, pathToTemplate?: string): IFuture { return (() => { this.$fs.ensureDirectoryExists(path.join(this.platformData.projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER)).wait(); - if(this.$options.symlink) { + if(pathToTemplate) { + // Copy everything except the template from the runtime + this.$fs.readDirectory(frameworkDir).wait() + .filter(dirName => dirName.indexOf(IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER) === -1) + .forEach(dirName => shell.cp("-R", path.join(frameworkDir, dirName), this.platformData.projectRoot)); + shell.cp("-rf", path.join(pathToTemplate, "*"), this.platformData.projectRoot); + } else if(this.$options.symlink) { let xcodeProjectName = util.format("%s.xcodeproj", IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER); shell.cp("-R", path.join(frameworkDir, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER, "*"), path.join(this.platformData.projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER)); @@ -118,7 +124,6 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ _.each(frameworkFiles, (file: string) => { this.$fs.symlink(path.join(frameworkDir, file), path.join(this.platformData.projectRoot, file)).wait(); }); - } else { shell.cp("-R", path.join(frameworkDir, "*"), this.platformData.projectRoot); } diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 1f89838719..c673395bf9 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -8,6 +8,8 @@ import * as helpers from "../common/helpers"; import * as semver from "semver"; import * as minimatch from "minimatch"; import Future = require("fibers/future"); +import * as temp from "temp"; +temp.track(); let clui = require("clui"); export class PlatformService implements IPlatformService { @@ -29,7 +31,8 @@ export class PlatformService implements IPlatformService { private $projectFilesManager: IProjectFilesManager, private $mobileHelper: Mobile.IMobileHelper, private $hostInfo: IHostInfo, - private $xmlValidator: IXmlValidator) { } + private $xmlValidator: IXmlValidator, + private $npm: INodePackageManager) { } public addPlatforms(platforms: string[]): IFuture { return (() => { @@ -114,7 +117,10 @@ export class PlatformService implements IPlatformService { } let sourceFrameworkDir = isFrameworkPathDirectory && this.$options.symlink ? path.join(this.$options.frameworkPath, "framework") : frameworkDir; - platformData.platformProjectService.createProject(path.resolve(sourceFrameworkDir), installedVersion).wait(); + this.$projectDataService.initialize(this.$projectData.projectDir); + let customTemplateOptions = this.getPathToPlatformTemplate(this.$options.platformTemplate, platformData.frameworkPackageName).wait(); + let pathToTemplate = customTemplateOptions && customTemplateOptions.pathToTemplate; + platformData.platformProjectService.createProject(path.resolve(sourceFrameworkDir), installedVersion, pathToTemplate).wait(); if(isFrameworkPathDirectory || isFrameworkPathNotSymlinkedFile) { // Need to remove unneeded node_modules folder @@ -132,12 +138,48 @@ export class PlatformService implements IPlatformService { this.$fs.copyFile(newConfigFile, platformData.configurationFilePath).wait(); } - this.$projectDataService.initialize(this.$projectData.projectDir); - this.$projectDataService.setValue(platformData.frameworkPackageName, {version: installedVersion}).wait(); + let frameworkPackageNameData: any = {version: installedVersion}; + if(customTemplateOptions) { + frameworkPackageNameData.template = customTemplateOptions.selectedTemplate; + } + this.$projectDataService.setValue(platformData.frameworkPackageName, frameworkPackageNameData).wait(); }).future()(); } + private getPathToPlatformTemplate(selectedTemplate: string, frameworkPackageName: string): IFuture { + return (() => { + if(!selectedTemplate) { + // read data from package.json's nativescript key + // check the nativescript.tns-.template value + let nativescriptPlatformData = this.$projectDataService.getValue(frameworkPackageName).wait(); + selectedTemplate = nativescriptPlatformData && nativescriptPlatformData.template; + } + + if(selectedTemplate) { + let tempDir = temp.mkdirSync("platform-template"); + try { + /* + * Output of npm.install is array of arrays. For example: + * [ [ 'test-android-platform-template@0.0.1', + * 'C:\\Users\\~1\\AppData\\Local\\Temp\\1\\platform-template11627-15560-rm3ngx\\node_modules\\test-android-platform-template', + * undefined, + * undefined, + * '..\\..\\..\\android-platform-template' ] ] + * Project successfully created. + */ + let pathToTemplate = this.$npm.install(selectedTemplate, tempDir).wait()[0][1]; + return { selectedTemplate, pathToTemplate }; + } catch(err) { + this.$logger.trace("Error while trying to install specified template: ", err); + this.$errors.failWithoutHelp(`Unable to install platform template ${selectedTemplate}. Make sure the specified value is valid.`); + } + } + + return null; + }).future()(); + } + public getInstalledPlatforms(): IFuture { return(() => { if(!this.$fs.exists(this.$projectData.platformsDir).wait()) { diff --git a/test/platform-commands.ts b/test/platform-commands.ts index 8871fff37c..98fd5e0bdc 100644 --- a/test/platform-commands.ts +++ b/test/platform-commands.ts @@ -137,6 +137,7 @@ function createTestInjector() { testInjector.register("mobilePlatformsCapabilities", MobilePlatformsCapabilities); testInjector.register("devicePlatformsConstants", DevicePlatformsConstants); testInjector.register("xmlValidator", XmlValidator); + testInjector.register("npm", {}); return testInjector; } diff --git a/test/platform-service.ts b/test/platform-service.ts index 65f721d059..4ed9a18a8b 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -71,6 +71,7 @@ function createTestInjector() { testInjector.register("mobilePlatformsCapabilities", MobilePlatformsCapabilities); testInjector.register("devicePlatformsConstants", DevicePlatformsConstants); testInjector.register("xmlValidator", XmlValidator); + testInjector.register("npm", {}); return testInjector; }