diff --git a/lib/commands/create-project.ts b/lib/commands/create-project.ts index 4fe0df3b2c..37efb74ddd 100644 --- a/lib/commands/create-project.ts +++ b/lib/commands/create-project.ts @@ -5,7 +5,7 @@ export class CreateProjectCommand implements ICommand { execute(args: string[]): IFuture { return (() => { - this.$projectService.createProject(args[0], args[1]).wait(); + this.$projectService.createProject(args[0]).wait(); }).future()(); } } diff --git a/lib/declarations.ts b/lib/declarations.ts index 465fce4400..d7f1461050 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -1,6 +1,7 @@ interface INodePackageManager { getCacheRootPath(): IFuture; - addToCache(packageName: string): IFuture; + addToCache(packageName: string, version: string): IFuture; + cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture; load(config?: any): IFuture; install(packageName: string, options?: INpmInstallOptions): IFuture; getLatestVersion(packageName: string): IFuture; diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index a5b4896964..26e8ddecaf 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -1,5 +1,5 @@ interface IProjectService { - createProject(projectName: string, projectId: string): IFuture; + createProject(projectName: string): IFuture; } interface IProjectData { diff --git a/lib/node-package-manager.ts b/lib/node-package-manager.ts index 3b5da1da89..bc8c3b3917 100644 --- a/lib/node-package-manager.ts +++ b/lib/node-package-manager.ts @@ -31,10 +31,10 @@ export class NodePackageManager implements INodePackageManager { }).future()(); } - public addToCache(packageName: string): IFuture { + public addToCache(packageName: string, version: string): IFuture { return (() => { this.load().wait(); - this.addToCacheCore(packageName).wait(); + this.addToCacheCore(packageName, version).wait(); }).future()(); } @@ -113,9 +113,22 @@ export class NodePackageManager implements INodePackageManager { return future; } - private addToCacheCore(packageName: string): IFuture { + private addToCacheCore(packageName: string, version: string): IFuture { var future = new Future(); - npm.commands["cache"].add(packageName, (err: Error, data: any) => { + npm.commands["cache"].add(packageName, version, undefined, (err: Error, data: any) => { + if(err) { + future.throw(err); + } else { + future.return(); + } + }); + return future; + } + + public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture { + var future = new Future(); + unpackTarget = unpackTarget || path.join(npm.cache, packageName, version, "package"); + npm.commands["cache"].unpack(packageName, version, unpackTarget, (err: Error, data: any) => { if(err) { future.throw(err); } else { diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 85f3371d0d..9c07b0d5cd 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -44,6 +44,7 @@ export class PlatformService implements IPlatformService { this.validatePlatform(platform); var platformPath = path.join(this.$projectData.platformsDir, platform); + if (this.$fs.exists(platformPath).wait()) { this.$errors.fail("Platform %s already added", platform); } @@ -212,7 +213,7 @@ export class PlatformService implements IPlatformService { _.each(platforms, platform => { var parts = platform.split("@"); - platform = parts[0]; + platform = parts[0].toLowerCase(); var version = parts[1]; this.validatePlatformInstalled(platform); @@ -451,7 +452,7 @@ export class PlatformService implements IPlatformService { var npmCacheDirectoryPath = this.getNpmCacheDirectoryCore(packageName, version).wait(); if(!this.$fs.exists(npmCacheDirectoryPath).wait()) { - this.$npm.addToCache(util.format("%s@%s", packageName, version)).wait(); + this.$npm.addToCache(packageName, version).wait(); } return npmCacheDirectoryPath; diff --git a/lib/services/project-service.ts b/lib/services/project-service.ts index f4132ab7db..e4c3976a1f 100644 --- a/lib/services/project-service.ts +++ b/lib/services/project-service.ts @@ -17,14 +17,14 @@ export class ProjectService implements IProjectService { private $projectNameValidator: IProjectNameValidator, private $projectTemplatesService: IProjectTemplatesService) { } - public createProject(projectName: string, projectId: string): IFuture { + public createProject(projectName: string): IFuture { return(() => { if (!projectName) { this.$errors.fail("You must specify when creating a new project."); } this.$projectNameValidator.validate(projectName); - projectId = options.appid || this.$projectHelper.generateDefaultAppId(projectName, "org.nativescript"); + var projectId = options.appid || this.$projectHelper.generateDefaultAppId(projectName, "org.nativescript"); var projectDir = path.join(path.resolve(options.path || "."), projectName); this.$fs.createDirectory(projectDir).wait(); diff --git a/package.json b/package.json index da2fce1f3d..c59fe8aa1f 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ }, "analyze": true, "devDependencies": { + "chai": "1.8.x", "grunt": "0.4.2", "grunt-contrib-clean": "0.5.0", "grunt-contrib-copy": "0.5.0", diff --git a/test/definitions/chai.d.ts b/test/definitions/chai.d.ts new file mode 100644 index 0000000000..113158d837 --- /dev/null +++ b/test/definitions/chai.d.ts @@ -0,0 +1,283 @@ +// Type definitions for chai 1.7.2 +// Project: http://chaijs.com/ +// Definitions by: Jed Hunsaker , Bart van der Schoor +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module chai { + export class AssertionError { + constructor(message: string, _props?: any, ssf?: Function); + name: string; + message: string; + showDiff: boolean; + stack: string; + } + + function expect(target: any, message?: string): Expect; + + export var assert: Assert; + export var config: Config; + + export interface Config { + includeStack: boolean; + } + + // Provides a way to extend the internals of Chai + function use(fn: (chai: any, utils: any) => void): any; + + interface ExpectStatic { + (target: any): Expect; + } + + interface Assertions { + attr(name: string, value?: string): any; + css(name: string, value?: string): any; + data(name: string, value?: string): any; + class(className: string): any; + id(id: string): any; + html(html: string): any; + text(text: string): any; + value(value: string): any; + visible: any; + hidden: any; + selected: any; + checked: any; + disabled: any; + empty: any; + exist: any; + } + + interface Expect extends LanguageChains, NumericComparison, TypeComparison, Assertions { + not: Expect; + deep: Deep; + a: TypeComparison; + an: TypeComparison; + include: Include; + contain: Include; + ok: Expect; + true: Expect; + false: Expect; + null: Expect; + undefined: Expect; + exist: Expect; + empty: Expect; + arguments: Expect; + Arguments: Expect; + equal: Equal; + equals: Equal; + eq: Equal; + eql: Equal; + eqls: Equal; + property: Property; + ownProperty: OwnProperty; + haveOwnProperty: OwnProperty; + length: Length; + lengthOf: Length; + match(RegularExpression: RegExp, message?: string): Expect; + string(string: string, message?: string): Expect; + keys: Keys; + key(string: string): Expect; + throw: Throw; + throws: Throw; + Throw: Throw; + respondTo(method: string, message?: string): Expect; + itself: Expect; + satisfy(matcher: Function, message?: string): Expect; + closeTo(expected: number, delta: number, message?: string): Expect; + members: Members; + } + + interface LanguageChains { + to: Expect; + be: Expect; + been: Expect; + is: Expect; + that: Expect; + and: Expect; + have: Expect; + with: Expect; + at: Expect; + of: Expect; + same: Expect; + } + + interface NumericComparison { + above: NumberComparer; + gt: NumberComparer; + greaterThan: NumberComparer; + least: NumberComparer; + gte: NumberComparer; + below: NumberComparer; + lt: NumberComparer; + lessThan: NumberComparer; + most: NumberComparer; + lte: NumberComparer; + within(start: number, finish: number, message?: string): Expect; + } + + interface NumberComparer { + (value: number, message?: string): Expect; + } + + interface TypeComparison { + (type: string, message?: string): Expect; + instanceof: InstanceOf; + instanceOf: InstanceOf; + } + + interface InstanceOf { + (constructor: Object, message?: string): Expect; + } + + interface Deep { + equal: Equal; + property: Property; + } + + interface Equal { + (value: any, message?: string): Expect; + } + + interface Property { + (name: string, value?: any, message?: string): Expect; + } + + interface OwnProperty { + (name: string, message?: string): Expect; + } + + interface Length extends LanguageChains, NumericComparison { + (length: number, message?: string): Expect; + } + + interface Include { + (value: Object, message?: string): Expect; + (value: string, message?: string): Expect; + (value: number, message?: string): Expect; + keys: Keys; + members: Members; + } + + interface Keys { + (...keys: string[]): Expect; + (keys: any[]): Expect; + } + + interface Members { + (set: any[], message?: string): Expect; + } + + interface Throw { + (): Expect; + (expected: string, message?: string): Expect; + (expected: RegExp, message?: string): Expect; + (constructor: Error, expected?: string, message?: string): Expect; + (constructor: Error, expected?: RegExp, message?: string): Expect; + (constructor: Function, expected?: string, message?: string): Expect; + (constructor: Function, expected?: RegExp, message?: string): Expect; + } + + export interface Assert { + (express: any, msg?: string):void; + + fail(actual?: any, expected?: any, msg?: string, operator?: string):void; + + ok(val: any, msg?: string):void; + notOk(val: any, msg?: string):void; + + equal(act: any, exp: any, msg?: string):void; + notEqual(act: any, exp: any, msg?: string):void; + + strictEqual(act: any, exp: any, msg?: string):void; + notStrictEqual(act: any, exp: any, msg?: string):void; + + deepEqual(act: any, exp: any, msg?: string):void; + notDeepEqual(act: any, exp: any, msg?: string):void; + + isTrue(val: any, msg?: string):void; + isFalse(val: any, msg?: string):void; + + isNull(val: any, msg?: string):void; + isNotNull(val: any, msg?: string):void; + + isUndefined(val: any, msg?: string):void; + isDefined(val: any, msg?: string):void; + + isFunction(val: any, msg?: string):void; + isNotFunction(val: any, msg?: string):void; + + isObject(val: any, msg?: string):void; + isNotObject(val: any, msg?: string):void; + + isArray(val: any, msg?: string):void; + isNotArray(val: any, msg?: string):void; + + isString(val: any, msg?: string):void; + isNotString(val: any, msg?: string):void; + + isNumber(val: any, msg?: string):void; + isNotNumber(val: any, msg?: string):void; + + isBoolean(val: any, msg?: string):void; + isNotBoolean(val: any, msg?: string):void; + + typeOf(val: any, type: string, msg?: string):void; + notTypeOf(val: any, type: string, msg?: string):void; + + instanceOf(val: any, type: Function, msg?: string):void; + notInstanceOf(val: any, type: Function, msg?: string):void; + + include(exp: string, inc: any, msg?: string):void; + include(exp: any[], inc: any, msg?: string):void; + + notInclude(exp: string, inc: any, msg?: string):void; + notInclude(exp: any[], inc: any, msg?: string):void; + + match(exp: any, re: RegExp, msg?: string):void; + notMatch(exp: any, re: RegExp, msg?: string):void; + + property(obj: Object, prop: string, msg?: string):void; + notProperty(obj: Object, prop: string, msg?: string):void; + deepProperty(obj: Object, prop: string, msg?: string):void; + notDeepProperty(obj: Object, prop: string, msg?: string):void; + + propertyVal(obj: Object, prop: string, val: any, msg?: string):void; + propertyNotVal(obj: Object, prop: string, val: any, msg?: string):void; + + deepPropertyVal(obj: Object, prop: string, val: any, msg?: string):void; + deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string):void; + + lengthOf(exp: any, len: number, msg?: string):void; + //alias frenzy + throw(fn: Function, msg?: string):void; + throw(fn: Function, regExp: RegExp):void; + throw(fn: Function, errType: Function, msg?: string):void; + throw(fn: Function, errType: Function, regExp: RegExp):void; + + throws(fn: Function, msg?: string):void; + throws(fn: Function, regExp: RegExp):void; + throws(fn: Function, errType: Function, msg?: string):void; + throws(fn: Function, errType: Function, regExp: RegExp):void; + + Throw(fn: Function, msg?: string):void; + Throw(fn: Function, regExp: RegExp):void; + Throw(fn: Function, errType: Function, msg?: string):void; + Throw(fn: Function, errType: Function, regExp: RegExp):void; + + doesNotThrow(fn: Function, msg?: string):void; + doesNotThrow(fn: Function, regExp: RegExp):void; + doesNotThrow(fn: Function, errType: Function, msg?: string):void; + doesNotThrow(fn: Function, errType: Function, regExp: RegExp):void; + + operator(val: any, operator: string, val2: any, msg?: string):void; + closeTo(act: number, exp: number, delta: number, msg?: string):void; + + sameMembers(set1: any[], set2: any[], msg?: string):void; + includeMembers(set1: any[], set2: any[], msg?: string):void; + + ifError(val: any, msg?: string):void; + } +} + +declare module "chai" { +export = chai; +} diff --git a/test/platform-service.ts b/test/platform-service.ts index 1bca7a384d..324d6de6a4 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -1,33 +1,190 @@ /// +"use strict"; + +import yok = require('../lib/common/yok'); +import stubs = require('./stubs'); import PlatformServiceLib = require('../lib/services/platform-service'); +import ProjectServiceLib = require("../lib/services/project-service"); import NodePackageManagerLib = require('../lib/node-package-manager'); +import ProjectDataServiceLib = require("../lib/services/project-data-service"); +import StaticConfigLib = require("../lib/config"); +import fsLib = require("../lib/common/file-system"); import ProjectLib = require('../lib/services/project-service'); -import stubs = require('./stubs'); +import ProjectServiceTestLib = require('./project-service'); +import NpmLib = require("../lib/node-package-manager"); +import HttpClientLib = require("../lib/common/http-client"); +import ProjectDataLib = require("../lib/project-data"); +import ProjectHelperLib = require("../lib/common/project-helper"); -import yok = require('../lib/common/yok'); +import path = require("path"); +import Future = require("fibers/future"); +var assert = require("chai").assert; +var options: any = require("./../lib/options"); require('should'); -var testInjector = new yok.Yok(); -testInjector.register('platformService', PlatformServiceLib.PlatformService); -testInjector.register('errors', stubs.ErrorsStub); -testInjector.register('fs', stubs.FileSystemStub); -testInjector.register('logger', stubs.LoggerStub); -testInjector.register('npm', stubs.NPMStub); -testInjector.register('projectData', stubs.ProjectDataStub); -testInjector.register('platformsData', stubs.PlatformsDataStub); -testInjector.register('devicesServices', {}); -testInjector.register('androidEmulatorServices', {}); -testInjector.register('projectDataService', {}); -testInjector.register('prompter', {}); - -describe('PlatformService', function(){ - describe('#updatePlatforms()', function(){ - it('should fail when no services provided', function(){ - var platformService = testInjector.resolve('platformService'); - (function(){return platformService.updatePlatforms().wait(); }).should.throw(); - - }) - }) +function createTestInjector() { + var testInjector = new yok.Yok(); + + testInjector.register('platformService', PlatformServiceLib.PlatformService); + testInjector.register('errors', stubs.ErrorsStub); + testInjector.register('logger', stubs.LoggerStub); + testInjector.register('npm', stubs.NPMStub); + testInjector.register('projectData', stubs.ProjectDataStub); + testInjector.register('platformsData', stubs.PlatformsDataStub); + testInjector.register('devicesServices', {}); + testInjector.register('androidEmulatorServices', {}); + testInjector.register('projectDataService', stubs.ProjectDataService); + testInjector.register('prompter', {}); + + return testInjector; +} + +describe('Platform Service Tests', () => { + var platformService: IPlatformService, testInjector: IInjector; + beforeEach(() => { + testInjector = createTestInjector(); + testInjector.register("fs", stubs.FileSystemStub); + platformService = testInjector.resolve("platformService"); + }); + + describe("add platform unit tests", () => { + describe("#add platform()", () => { + it("should fail if platform is null or undefined", () => { + (() => platformService.addPlatforms(null).wait()).should.throw(); + (() => platformService.addPlatforms(undefined).wait()).should.throw(); + }); + it("should fail if platform not supported", () => { + (() => platformService.addPlatforms(["fdhf"]).wait()).should.throw(); + (() => platformService.addPlatforms(["test"]).wait()).should.throw(); + }); + it("should not fail if platform is not normalized", () => { + var fs = testInjector.resolve("fs"); + fs.exists = () => Future.fromResult(false); + + platformService.addPlatforms(["Android"]).wait(); + platformService.addPlatforms(["ANDROID"]).wait(); + platformService.addPlatforms(["AnDrOiD"]).wait(); + platformService.addPlatforms(["androiD"]).wait(); + + platformService.addPlatforms(["iOS"]).wait(); + platformService.addPlatforms(["IOS"]).wait(); + platformService.addPlatforms(["IoS"]).wait(); + platformService.addPlatforms(["iOs"]).wait(); + }); + it("should fail if platform is already installed", () => { + // By default fs.exists returns true, so the platforms directory should exists + (() => platformService.addPlatforms(["android"]).wait()).should.throw(); + (() => platformService.addPlatforms(["ios"]).wait()).should.throw(); + }); + it("should fail if npm is unavalible", () => { + var fs = testInjector.resolve("fs"); + fs.exists = () => Future.fromResult(false); + + var errorMessage = "Npm is unavalible"; + var npm = testInjector.resolve("npm"); + npm.install = () => { throw new Error(errorMessage) }; + + try { + platformService.addPlatforms(["android"]).wait(); + } catch(err) { + assert.equal(errorMessage, err.message); + } + }); + }); + describe("#add platform(ios)", () => { + it("should call validate method", () => { + var fs = testInjector.resolve("fs"); + fs.exists = () => Future.fromResult(false); + + var errorMessage = "Xcode is not installed or Xcode version is smaller that 5.0"; + var platformsData = testInjector.resolve("platformsData"); + var platformProjectService = platformsData.getPlatformData().platformProjectService; + platformProjectService.validate = () => { + throw new Error(errorMessage); + }; + + try { + platformService.addPlatforms(["ios"]).wait(); + } catch(err) { + assert.equal(errorMessage, err.message); + } + }); + }); + describe("#add platform(android)", () => { + it("should fail if java, ant or android are not installed", () => { + var fs = testInjector.resolve("fs"); + fs.exists = () => Future.fromResult(false); + + var errorMessage = "Java, ant or android are not installed"; + var platformsData = testInjector.resolve("platformsData"); + var platformProjectService = platformsData.getPlatformData().platformProjectService; + platformProjectService.validate = () => { + throw new Error(errorMessage); + }; + + try { + platformService.addPlatforms(["android"]).wait(); + } catch(err) { + assert.equal(errorMessage, err.message); + } + }); + }); + }); + + describe("remove platform unit tests", () => { + it("should fail if platform null or undefined", () => { + (() => platformService.removePlatforms(null).wait()).should.throw(); + (() => platformService.removePlatforms(undefined).wait()).should.throw(); + }); + it("should fail when platforms are not added", () => { + testInjector.resolve("fs").exists = () => Future.fromResult(false); + + (() => platformService.removePlatforms(["android"]).wait()).should.throw(); + (() => platformService.removePlatforms(["ios"]).wait()).should.throw(); + }); + it("shouldn't fail when platforms are added", () => { + testInjector.resolve("fs").exists = () => Future.fromResult(false); + platformService.addPlatforms(["android"]).wait(); + + testInjector.resolve("fs").exists = () => Future.fromResult(true); + platformService.removePlatforms(["android"]).wait(); + }); + }); + + describe("list platform unit tests", () => { + it("fails when platforms are not added", () => { + (() => platformService.getAvailablePlatforms().wait()).should.throw(); + }); + }); + + describe("update Platform", () => { + + describe('#updatePlatforms()', function(){ + it('should fail when no services provided', () => { + (() => platformService.updatePlatforms([]).wait()).should.throw(); + }); + }); + + describe("#updatePlatform(platform)", () => { + it ("should fail if platform null or undefined", () => { + (() => platformService.updatePlatforms(null).wait()).should.throw(); + (() => platformService.updatePlatforms(undefined).wait()).should.throw(); + }); + + it ("should fail if platform not supported", () => { + (() => platformService.updatePlatforms(["unsupported"]).wait()).should.throw(); + (() => platformService.updatePlatforms(["aaa"]).wait()).should.throw(); + }); + + it ("should fail when the versions are the same", () => { + var npm: INodePackageManager = testInjector.resolve("npm"); + npm.getLatestVersion = () => (() => "0.2.0").future()(); + npm.getCacheRootPath = () => (() => "").future()(); + + (() => platformService.updatePlatforms(["android"]).wait()).should.throw(); + }); + }); + }); }); diff --git a/test/project-service.ts b/test/project-service.ts new file mode 100644 index 0000000000..34988db92a --- /dev/null +++ b/test/project-service.ts @@ -0,0 +1,141 @@ +/// +"use strict"; + +import yok = require('../lib/common/yok'); +import stubs = require('./stubs'); + +import ProjectServiceLib = require("../lib/services/project-service"); +import ProjectDataServiceLib = require("../lib/services/project-data-service"); +import ProjectHelperLib = require("../lib/common/project-helper"); +import StaticConfigLib = require("../lib/config"); +import NpmLib = require("../lib/node-package-manager"); +import HttpClientLib = require("../lib/common/http-client"); +import fsLib = require("../lib/common/file-system"); + +import path = require("path"); +import temp = require("temp"); +import util = require("util"); +import helpers = require("../lib/common/helpers"); + +var assert = require("chai").assert; +var options: any = require("./../lib/options"); +var mockProjectNameValidator = { + validate: () => { return true; } +}; + +temp.track(); + +class ProjectIntegrationTest { + private testInjector: IInjector; + + constructor() { + this.createTestInjector(); + } + + public createProject(projectName: string): IFuture { + var projectService = this.testInjector.resolve("projectService"); + return projectService.createProject(projectName); + } + + public getDefaultTemplatePath(): IFuture { + return (() => { + var npm = this.testInjector.resolve("npm"); + var fs = this.testInjector.resolve("fs"); + + var defaultTemplatePackageName = "tns-template-hello-world"; + var cacheRoot = npm.getCacheRootPath().wait(); + var defaultTemplatePath = path.join(cacheRoot, defaultTemplatePackageName); + var latestVersion = npm.getLatestVersion(defaultTemplatePackageName).wait(); + + if(!fs.exists(path.join(defaultTemplatePath, latestVersion)).wait()) { + npm.addToCache(defaultTemplatePackageName, latestVersion).wait(); + } + if(!fs.exists(path.join(defaultTemplatePath, latestVersion, "package", "app")).wait()) { + npm.cacheUnpack(defaultTemplatePackageName, latestVersion).wait(); + } + + return path.join(defaultTemplatePath, latestVersion, "package"); + }).future()(); + } + + public assertProject(tempFolder: string, projectName: string, appId: string): IFuture { + return (() => { + var fs = this.testInjector.resolve("fs"); + var projectDir = path.join(tempFolder, projectName); + var appDirectoryPath = path.join(projectDir, "app"); + var platformsDirectoryPath = path.join(projectDir, "platforms"); + var tnsProjectFilePath = path.join(projectDir, ".tnsproject"); + + assert.isTrue(fs.exists(appDirectoryPath).wait()); + assert.isTrue(fs.exists(platformsDirectoryPath).wait()); + assert.isTrue(fs.exists(tnsProjectFilePath).wait()); + + assert.isFalse(fs.isEmptyDir(appDirectoryPath).wait()); + assert.isTrue(fs.isEmptyDir(platformsDirectoryPath).wait()); + + var actualAppId = fs.readJson(tnsProjectFilePath).wait().id; + var expectedAppId = appId; + assert.equal(actualAppId, expectedAppId); + + var actualFiles = helpers.enumerateFilesInDirectorySync(options["copy-from"]); + var expectedFiles = helpers.enumerateFilesInDirectorySync(appDirectoryPath); + + assert.equal(actualFiles.length, expectedFiles.length); + _.each(actualFiles, file => { + var relativeToProjectDir = helpers.getRelativeToRootPath(options["copy-from"], file); + assert.isTrue(fs.exists(path.join(appDirectoryPath, relativeToProjectDir)).wait()); + }); + }).future()(); + } + + public dispose(): void { + this.testInjector = undefined; + } + + private createTestInjector(): void { + this.testInjector = new yok.Yok(); + + this.testInjector.register("errors", stubs.ErrorsStub); + this.testInjector.register('logger', stubs.LoggerStub); + this.testInjector.register("projectService", ProjectServiceLib.ProjectService); + this.testInjector.register("projectHelper", ProjectHelperLib.ProjectHelper); + this.testInjector.register("projectTemplatesService", stubs.ProjectTemplatesService); + this.testInjector.register("projectNameValidator", mockProjectNameValidator); + + this.testInjector.register("fs", fsLib.FileSystem); + this.testInjector.register("projectDataService", ProjectDataServiceLib.ProjectDataService); + this.testInjector.register("staticConfig", StaticConfigLib.StaticConfig); + + this.testInjector.register("npm", NpmLib.NodePackageManager); + this.testInjector.register("httpClient", HttpClientLib.HttpClient); + this.testInjector.register("config", {}); + } +} + +describe("Project Service Tests", () => { + describe("project service integration tests", () => { + it("creates valid project from default template", () => { + var projectIntegrationTest = new ProjectIntegrationTest(); + var tempFolder = temp.mkdirSync("project"); + var projectName = "myapp"; + + options.path = tempFolder; + options["copy-from"] = projectIntegrationTest.getDefaultTemplatePath().wait(); + + projectIntegrationTest.createProject(projectName).wait(); + projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp").wait(); + }); + it("creates valid project with specified id from default template", () => { + var projectIntegrationTest = new ProjectIntegrationTest(); + var tempFolder = temp.mkdirSync("project1"); + var projectName = "myapp"; + + options.path = tempFolder; + options["copy-from"] = projectIntegrationTest.getDefaultTemplatePath().wait(); + options.appid = "my.special.id"; + + projectIntegrationTest.createProject(projectName).wait(); + projectIntegrationTest.assertProject(tempFolder, projectName, options.appid).wait(); + }); + }); +}); \ No newline at end of file diff --git a/test/stubs.ts b/test/stubs.ts index d3acc5890e..0f4f89b0aa 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -38,8 +38,8 @@ export class FileSystemStub implements IFileSystem { return undefined; } - deleteDirectory(directory: string): IFuture { - return undefined; + deleteDirectory(directory: string): IFuture { + return Future.fromResult(); } getFileSize(path:string):IFuture { @@ -51,7 +51,7 @@ export class FileSystemStub implements IFileSystem { } createDirectory(path:string):IFuture { - return undefined; + return Future.fromResult(); } readDirectory(path:string):IFuture { @@ -105,11 +105,11 @@ export class FileSystemStub implements IFileSystem { } isEmptyDir(directoryPath: string): IFuture { - return undefined; + return Future.fromResult(true); } ensureDirectoryExists(directoryPath: string): IFuture { - return undefined; + return Future.fromResult(); } rename(oldPath: string, newPath: string): IFuture { @@ -141,7 +141,11 @@ export class NPMStub implements INodePackageManager { return undefined; } - addToCache(packageName: string): IFuture { + addToCache(packageName: string, version: string): IFuture { + return undefined; + } + + cacheUnpack(packageName: string, version: string): IFuture { return undefined; } @@ -150,20 +154,22 @@ export class NPMStub implements INodePackageManager { } install(packageName: string, pathToSave?: string, version?: string): IFuture { - return undefined; + return Future.fromResult(""); } getLatestVersion(packageName: string): IFuture { - return undefined; + return Future.fromResult(""); } } export class ProjectDataStub implements IProjectData { - public projectDir: string; - public platformsDir: string; - public projectFilePath: string; - public projectId: string; - public projectName: string; + projectDir: string; + projectName: string; + get platformsDir(): string { + return ""; + } + projectFilePath: string; + projectId: string; } export class PlatformsDataStub implements IPlatformsData { @@ -172,9 +178,81 @@ export class PlatformsDataStub implements IPlatformsData { } public getPlatformData(platform: string): IPlatformData { - return undefined; + return { + frameworkPackageName: "", + normalizedPlatformName: "", + platformProjectService: new PlatformProjectServiceStub(), + emulatorServices: undefined, + projectRoot: "", + deviceBuildOutputPath: "", + validPackageNamesForDevice: [], + frameworkFilesExtensions: [] + }; + } +} + +export class PlatformProjectServiceStub implements IPlatformProjectService { + get platformData(): IPlatformData { + return { + frameworkPackageName: "", + normalizedPlatformName: "", + platformProjectService: this, + emulatorServices: undefined, + projectRoot: "", + deviceBuildOutputPath: "", + validPackageNamesForDevice: [], + frameworkFilesExtensions: [] + }; + } + validate(): IFuture { + return Future.fromResult(); + } + createProject(projectRoot: string, frameworkDir: string): IFuture { + return Future.fromResult(); + } + interpolateData(projectRoot: string): IFuture { + return Future.fromResult(); + } + afterCreateProject(projectRoot: string): IFuture { + return Future.fromResult(); + } + prepareProject(platformData: IPlatformData): IFuture { + return Future.fromResult(""); + } + buildProject(projectRoot: string): IFuture { + return Future.fromResult(); + } + isPlatformPrepared(projectRoot: string): IFuture { + return Future.fromResult(false); + } +} + +export class ProjectDataService implements IProjectDataService { + initialize(projectDir: string): void { } + + getValue(propertyName: string): IFuture { + return Future.fromResult({}); + } + + setValue(key: string, value: any): IFuture { + return Future.fromResult(); } } +export class ProjectHelperStub implements IProjectHelper { + get projectDir(): string { + return ""; + } + + generateDefaultAppId(appName: string, baseAppId: string): string { + return "org.nativescript"; + } +} + +export class ProjectTemplatesService implements IProjectTemplatesService { + get defaultTemplatePath(): IFuture { + return Future.fromResult(""); + } +} diff --git a/test/test-bootstrap.ts b/test/test-bootstrap.ts index 21358bba2e..079703991d 100644 --- a/test/test-bootstrap.ts +++ b/test/test-bootstrap.ts @@ -1,6 +1,14 @@ global._ = require("underscore"); global.$injector = require("../lib/common/yok").injector; +$injector.register("analyticsService", { + trackException: (): IFuture => undefined +}); + +// Converts the js callstack to typescript +import errors = require("../lib/common/errors"); +errors.installUncaughtExceptionListener(); + process.on('exit', (code: number) => { require("fibers/future").assertNoFutureLeftBehind(); });