Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified creating angular template project #1638

Merged
merged 2 commits into from
Mar 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/man_pages/project/creation/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ create
Usage | Synopsis
---|---
Create from default JavaScript template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>]`
Create from default TypeScript template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID> --template typescript` OR `$ tns create <App Name> [--path <Directory>] [--appid <App ID> --template tsc`
Create from default TypeScript template | `$ tns create <App Name> --template typescript [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --template tsc [--path <Directory>] [--appid <App ID>]`
Create from default Angular template | `$ tns create <App Name> --template angular [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --template ng [--path <Directory>] [--appid <App ID>]` OR `$ tns create <App Name> --ng [--path <Directory>] [--appid <App ID>]`
Copy from existing project | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>] --copy-from <Directory>`
Create from custom template | `$ tns create <App Name> [--path <Directory>] [--appid <App ID>] --template <Template>`

Expand All @@ -15,6 +16,7 @@ Creates a new project for native development with NativeScript.
* `--appid` - Sets the application identifier for your project.
* `--copy-from` - Specifies a directory which contains an existing NativeScript project. If `--copy-from` and `--template` are not set, the NativeScript CLI creates the project from the default JavaScript hello-world template.
* `--template` - Specifies a valid npm package which you want to use to create your project. If `--copy-from` and `--template` are not set, the NativeScript CLI creates the project from the default JavaScript hello-world template.<% if(isHtml) { %> If one or more application assets are missing from the `App_Resources` directory in the package, the CLI adds them using the assets available in the default hello-world template.<% } %>
* `--ng` - Sets the template for your project to the Angular template.

### Attributes
* `<App Name>` is the name of project. The specified name must meet the requirements of all platforms that you want to target. <% if(isConsole) { %>For more information about the `<App Name>` requirements, run `$ tns help create`<% } %><% if(isHtml) { %>For projects that target Android, you can use uppercase or lowercase letters, numbers, and underscores. The name must start with a letter.
Expand Down
12 changes: 10 additions & 2 deletions lib/commands/create-project.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
///<reference path="../.d.ts"/>
"use strict";

import * as constants from "../constants";

export class ProjectCommandParameter implements ICommandParameter {
constructor(private $errors: IErrors,
private $logger: ILogger,
Expand All @@ -27,13 +29,19 @@ export class CreateProjectCommand implements ICommand {
private $errors: IErrors,
private $logger: ILogger,
private $projectNameValidator: IProjectNameValidator,
private $options: ICommonOptions) { }
private $options: IOptions) { }

public enableHooks = false;

execute(args: string[]): IFuture<void> {
return (() => {
this.$projectService.createProject(args[0], this.$options.template).wait();
if (this.$options.ng && this.$options.template) {
this.$errors.fail("You cannot use --ng and --template simultaneously.");
}

let selectedTemplate = this.$options.ng ? constants.ANGULAR_NAME : this.$options.template;

this.$projectService.createProject(args[0], selectedTemplate).wait();
}).future<void>()();
}

Expand Down
2 changes: 2 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ class ItunesConnectApplicationTypesClass implements IiTunesConnectApplicationTyp
}

export let ItunesConnectApplicationTypes = new ItunesConnectApplicationTypesClass();

export let ANGULAR_NAME = "angular";
39 changes: 20 additions & 19 deletions lib/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,33 @@ interface ILiveSyncService {
}

interface IOptions extends ICommonOptions {
ipa: string;
frameworkPath: string;
frameworkName: string;
framework: string;
frameworkVersion: string;
baseConfig: string;
client: boolean;
compileSdk: number;
copyFrom: string;
linkTo: string;
copyTo: string;
debugTransport: boolean;
emulator: boolean;
symlink: boolean;
forDevice: boolean;
client: boolean;
production: boolean;
keyStorePath: string;
keyStorePassword: string;
framework: string;
frameworkName: string;
frameworkPath: string;
frameworkVersion: string;
ignoreScripts: boolean;
ipa: string;
keyStoreAlias: string;
keyStoreAliasPassword: string;
keyStorePassword: string;
keyStorePath: string;
linkTo: string;
ng: boolean;
platformTemplate: string;
port: Number;
production: boolean;
sdk: string;
debugTransport: boolean;
ignoreScripts: boolean;
tnsModulesVersion: string;
staticBindings: boolean;
compileSdk: number;
port: Number;
copyTo: string;
baseConfig: string;
platformTemplate: string;
symlink: boolean;
tnsModulesVersion: string;
}

interface IInitService {
Expand Down
3 changes: 2 additions & 1 deletion lib/npm-installation-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export class NpmInstallationManager implements INpmInstallationManager {
"tns-ios": constants.PROJECT_FRAMEWORK_FOLDER_NAME,
"tns-ios-inspector": "WebInspectorUI",
"tns-template-hello-world": constants.APP_RESOURCES_FOLDER_NAME,
"tns-template-hello-world-ts": constants.APP_RESOURCES_FOLDER_NAME
"tns-template-hello-world-ts": constants.APP_RESOURCES_FOLDER_NAME,
"tns-template-hello-world-ng": constants.APP_RESOURCES_FOLDER_NAME
};

constructor(private $npm: INodePackageManager,
Expand Down
3 changes: 2 additions & 1 deletion lib/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export class Options extends commonOptionsLibPath.OptionsBase {
port: { type: OptionType.Number },
copyTo: { type: OptionType.String },
baseConfig: { type: OptionType.String },
platformTemplate: { type: OptionType.String }
platformTemplate: { type: OptionType.String },
ng: {type: OptionType.Boolean }
},
path.join($hostInfo.isWindows ? process.env.AppData : path.join(osenv.home(), ".local/share"), ".nativescript-cli"),
$errors, $staticConfig);
Expand Down
2 changes: 2 additions & 0 deletions lib/services/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ export class ProjectService implements IProjectService {
this.$fs.symlink(appSourcePath, appDestinationPath).wait();
} else {
shelljs.cp('-R', path.join(appSourcePath, "*"), appDestinationPath);
// Copy hidden files.
shelljs.cp('-R', path.join(appSourcePath, ".*"), appDestinationPath);
}

this.createBasicProjectStructure(projectDir, projectId).wait();
Expand Down
4 changes: 3 additions & 1 deletion lib/services/project-templates-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export class ProjectTemplatesService implements IProjectTemplatesService {
private static RESERVED_TEMPLATE_NAMES: IStringDictionary = {
"default": "tns-template-hello-world",
"tsc": "tns-template-hello-world-ts",
"typescript": "tns-template-hello-world-ts"
"typescript": "tns-template-hello-world-ts",
"ng": "tns-template-hello-world-ng",
"angular": "tns-template-hello-world-ng"
};

public constructor(private $errors: IErrors,
Expand Down
102 changes: 102 additions & 0 deletions test/project-commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/// <reference path=".d.ts" />
"use strict";

import { Yok } from "../lib/common/yok";
import * as stubs from "./stubs";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use:

import { LoggerStub, ErrorsStub } from "./stubs"; 

and use them directly later in your code

import { CreateProjectCommand } from "../lib/commands/create-project";
import * as constants from "../lib/constants";
import {assert} from "chai";

let selectedTemplateName: string;
let isProjectCreated: boolean;
let dummyArgs = ["dummyArgsString"];

class ProjectServiceMock implements IProjectService {
createProject(projectName: string, selectedTemplate?: string): IFuture<void> {
return (() => {
selectedTemplateName = selectedTemplate;
isProjectCreated = true;
}).future<void>()();
}
}

class ProjectNameValidatorMock implements IProjectNameValidator {
public validate(name: string): boolean {
return true;
}
}

function createTestInjector() {
let testInjector = new Yok();

testInjector.register("injector", testInjector);
testInjector.register("staticConfig", {});
testInjector.register("projectService", ProjectServiceMock);
testInjector.register("errors", stubs.ErrorsStub);
testInjector.register("logger", stubs.LoggerStub);
testInjector.register("projectNameValidator", ProjectNameValidatorMock);
testInjector.register("options", {
ng: false,
template: undefined
});
testInjector.register("createCommand", CreateProjectCommand);

return testInjector;
}

describe("Project commands tests", () => {
let testInjector: IInjector;
let options: IOptions;
let createProjectCommand: ICommand;

beforeEach(() => {
testInjector = createTestInjector();
isProjectCreated = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set selectedTemplateName to null just to be sure the tests are correct

selectedTemplateName = undefined;
options = testInjector.resolve("$options");
createProjectCommand = testInjector.resolve("$createCommand");
});

describe("#CreateProjectCommand", () => {
it("should not fail when using only --ng.", () => {
options.ng = true;

createProjectCommand.execute(dummyArgs).wait();

assert.isTrue(isProjectCreated);
});

it("should not fail when using only --template.", () => {
options.template = "ng";

createProjectCommand.execute(dummyArgs).wait();

assert.isTrue(isProjectCreated);
});

it("should set the template name correctly when used --ng.", () => {
options.ng = true;

createProjectCommand.execute(dummyArgs).wait();

assert.deepEqual(selectedTemplateName, constants.ANGULAR_NAME);
});

it("should not set the template name when --ng is not used.", () => {
options.ng = false;

createProjectCommand.execute(dummyArgs).wait();

assert.isUndefined(selectedTemplateName);
});

it("should fail when --ng and --template are used simultaneously.", () => {
options.ng = true;
options.template = "ng";

assert.throws(() => {
createProjectCommand.execute(dummyArgs).wait();
});
});
});
});
26 changes: 26 additions & 0 deletions test/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,32 @@ describe("Project Service Tests", () => {
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("tsc").wait()).wait();
});

it("creates valid project from angular template", () => {
let projectIntegrationTest = new ProjectIntegrationTest();
let tempFolder = temp.mkdirSync("projectAngular");
let projectName = "myapp";
let options = projectIntegrationTest.testInjector.resolve("options");

options.path = tempFolder;
projectIntegrationTest.createProject(projectName, "angular").wait();

let projectTemplatesService: IProjectTemplatesService = projectIntegrationTest.testInjector.resolve("projectTemplatesService");
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("angular").wait()).wait();
});

it("creates valid project from ng template", () => {
let projectIntegrationTest = new ProjectIntegrationTest();
let tempFolder = temp.mkdirSync("projectNg");
let projectName = "myapp";
let options = projectIntegrationTest.testInjector.resolve("options");

options.path = tempFolder;
projectIntegrationTest.createProject(projectName, "ng").wait();

let projectTemplatesService: IProjectTemplatesService = projectIntegrationTest.testInjector.resolve("projectTemplatesService");
projectIntegrationTest.assertProject(tempFolder, projectName, "org.nativescript.myapp", projectTemplatesService.prepareTemplate("ng").wait()).wait();
});

it("creates valid project from local directory template", () => {
let projectIntegrationTest = new ProjectIntegrationTest();
let tempFolder = temp.mkdirSync("projectLocalDir");
Expand Down