Skip to content

feat(react): official quick create for --react app #5336

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

Merged
merged 2 commits into from
Jun 27, 2020
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
1 change: 1 addition & 0 deletions docs/man_pages/project/creation/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Template | Command
`Angular - Hello World`, `--ng`, `--angular` | tns create --template tns-template-hello-world-ng
`Angular - SideDrawer` | tns create --template tns-template-drawer-navigation-ng
`Angular - Tabs` | tns create --template tns-template-tab-navigation-ng
`React - Hello World`, `--react`, `--reactjs` | tns create --template tns-template-blank-react
`Vue.js - Blank`, `--vue`, `--vuejs` | tns create --template tns-template-blank-vue
`Vue.js - SideDrawer`, | tns create --template tns-template-drawer-navigation-vue
`Vue.js - Tabs` | tns create --template tns-template-tab-navigation-vue
Expand Down
20 changes: 18 additions & 2 deletions lib/commands/create-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export class CreateProjectCommand implements ICommand {
selectedTemplate = constants.ANGULAR_NAME;
} else if (this.$options.vue) {
selectedTemplate = constants.VUE_NAME;
} else if (this.$options.react) {
selectedTemplate = constants.REACT_NAME;
} else {
selectedTemplate = this.$options.template;
}
Expand Down Expand Up @@ -82,6 +84,7 @@ export class CreateProjectCommand implements ICommand {
private async interactiveFlavorSelection(adverb: string) {
const flavorSelection = await this.$prompter.promptForDetailedChoice(`${adverb}, which style of NativeScript project would you like to use:`, [
{ key: constants.NgFlavorName, description: "Learn more at https://nativescript.org/angular" },
{ key: constants.ReactFlavorName, description: "Learn more at https://github.com/shirakaba/react-nativescript" },
{ key: constants.VueFlavorName, description: "Learn more at https://nativescript.org/vue" },
{ key: constants.TsFlavorName, description: "Learn more at https://nativescript.org/typescript" },
{ key: constants.JsFlavorName, description: "Use NativeScript without any framework" },
Expand All @@ -96,8 +99,7 @@ export class CreateProjectCommand implements ICommand {
this.$logger.printMarkdown(`# Let’s create a NativeScript app!`);
this.$logger.printMarkdown(`
Answer the following questions to help us build the right app for you. (Note: you
can skip this prompt next time using the --template option, or the --ng, --vue, --ts,
or --js flags.)
can skip this prompt next time using the --template option, or the --ng, --react, --vue, --ts, or --js flags.)
`);
}
}
Expand All @@ -114,6 +116,10 @@ or --js flags.)
selectedFlavorTemplates.push(...this.getNgTemplates());
break;
}
case constants.ReactFlavorName: {
selectedFlavorTemplates.push(...this.getReactTemplates());
break;
}
case constants.VueFlavorName: {
selectedFlavorTemplates.push(...this.getVueTemplates());
break;
Expand Down Expand Up @@ -200,6 +206,16 @@ or --js flags.)
return templates;
}

private getReactTemplates() {
const templates = [{
key: CreateProjectCommand.HelloWorldTemplateKey,
value: constants.RESERVED_TEMPLATE_NAMES.react,
description: CreateProjectCommand.HelloWorldTemplateDescription
}];

return templates;
}

private getVueTemplates() {
const templates = [{
key: CreateProjectCommand.BlankTemplateKey,
Expand Down
8 changes: 4 additions & 4 deletions lib/common/commands/preuninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { doesCurrentNpmCommandMatch, isInteractive } from "../helpers";
import { TrackActionNames, AnalyticsEventLabelDelimiter } from "../../constants";

export class PreUninstallCommand implements ICommand {
// disabled for now (6/24/2020)
// disabled for now (6/24/2020)
// private static FEEDBACK_FORM_URL = "https://www.nativescript.org/uninstall-feedback";

public allowedParameters: ICommandParameter[] = [];
Expand Down Expand Up @@ -38,11 +38,11 @@ export class PreUninstallCommand implements ICommand {
}

private async handleFeedbackForm(): Promise<void> {
// disabled for now (6/24/2020)
// disabled for now (6/24/2020)
// if (isInteractive()) {
// this.$opener.open(PreUninstallCommand.FEEDBACK_FORM_URL);
// }
return Promise.resolve();
// }
return Promise.resolve();
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/common/test/unit-tests/preuninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe("preuninstall", () => {
assert.isTrue(isClearInspectorCacheCalled, "When uninstall is called, `clearInspectorCache` method must be called");
});

// disabled (6/24/2020)
// disabled (6/24/2020)
// it("opens the uninstall feedback form when terminal is interactive and uninstall is called", async () => {
// helpers.doesCurrentNpmCommandMatch = () => true;
// helpers.isInteractive = () => true;
Expand Down
6 changes: 5 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ export const RESERVED_TEMPLATE_NAMES: IStringDictionary = {
"vue": "tns-template-blank-vue",
"typescript": "tns-template-hello-world-ts",
"ng": "tns-template-hello-world-ng",
"angular": "tns-template-hello-world-ng"
"angular": "tns-template-hello-world-ng",
"react": "tns-template-blank-react",
"reactjs": "tns-template-blank-react"
};

export const ANALYTICS_LOCAL_TEMPLATE_PREFIX = "localTemplate_";
Expand Down Expand Up @@ -138,8 +140,10 @@ export const VUE_NAME = "vue";
export const ANGULAR_NAME = "angular";
export const JAVASCRIPT_NAME = "javascript";
export const TYPESCRIPT_NAME = "typescript";
export const REACT_NAME = "react";
export const NgFlavorName = "Angular";
export const VueFlavorName = "Vue.js";
export const ReactFlavorName = "React";
export const TsFlavorName = "Plain TypeScript";
export const JsFlavorName = "Plain JavaScript";
export class ProjectTypes {
Expand Down
1 change: 1 addition & 0 deletions lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ interface IOptions extends IRelease, IDeviceIdentifier, IJustLaunch, IAvd, IAvai
typescript: boolean;
ng: boolean;
angular: boolean;
react: boolean;
vue: boolean;
vuejs: boolean;
js: boolean;
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"main": "./lib/nativescript-cli-lib.js",
"scripts": {
"grunt": "grunt",
"build": "grunt",
"build.all": "grunt test",
"setup": "npm i --ignore-scripts && ./node_modules/.bin/grunt",
"test": "istanbul cover ./node_modules/mocha/bin/_mocha",
"postinstall": "node postinstall.js",
Expand Down
31 changes: 31 additions & 0 deletions test/project-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let validateProjectCallsCount: number;
const dummyArgs = ["dummyArgsString"];
const expectedFlavorChoices = [
{ key: "Angular", description: "Learn more at https://nativescript.org/angular" },
{ key: "React", description: "Learn more at https://github.com/shirakaba/react-nativescript" },
{ key: "Vue.js", description: "Learn more at https://nativescript.org/vue" },
{ key: "Plain TypeScript", description: "Learn more at https://nativescript.org/typescript" },
{ key: "Plain JavaScript", description: "Use NativeScript without any framework" }
Expand Down Expand Up @@ -126,6 +127,16 @@ describe("Project commands tests", () => {
assert.isTrue(createProjectCalledWithForce);
});

it("should not fail when using only --react.", async () => {
options.react = true;

await createProjectCommand.execute(dummyArgs);

assert.isTrue(isProjectCreated);
assert.equal(validateProjectCallsCount, 1);
assert.isTrue(createProjectCalledWithForce);
});

it("should not fail when using only --tsc.", async () => {
options.tsc = true;

Expand Down Expand Up @@ -156,6 +167,16 @@ describe("Project commands tests", () => {
assert.isTrue(createProjectCalledWithForce);
});

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

await createProjectCommand.execute(dummyArgs);

assert.deepEqual(selectedTemplateName, constants.REACT_NAME);
assert.equal(validateProjectCallsCount, 1);
assert.isTrue(createProjectCalledWithForce);
});

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

Expand Down Expand Up @@ -219,5 +240,15 @@ describe("Project commands tests", () => {
assert.equal(validateProjectCallsCount, 1);
assert.isTrue(createProjectCalledWithForce);
});

it("should ask for a template when react flavor is selected.", async () => {
setupAnswers({ flavorAnswer: constants.ReactFlavorName, templateAnswer: "Hello World" });

await createProjectCommand.execute(dummyArgs);

assert.deepEqual(selectedTemplateName, "tns-template-blank-react");
assert.equal(validateProjectCallsCount, 1);
assert.isTrue(createProjectCalledWithForce);
});
});
});
2 changes: 1 addition & 1 deletion test/project-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe("projectData", () => {
assertProjectType({ "react-nativescript": "*" }, null, "React");
});

it("detects project as Svelte when react-nativescript exists as dependency and typescript is devDependency", () => {
it("detects project as Svelte when svelte-native exists as dependency and typescript is devDependency", () => {
assertProjectType({ "svelte-native": "*" }, null, "Svelte");
});

Expand Down