From fd28b8ce00c2c769e308a06a5b1db0d1a467b6e8 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Thu, 8 Dec 2016 11:11:52 -0800 Subject: [PATCH] fix(new): Make sure the project name is valid. --- packages/angular-cli/commands/new.ts | 7 ++ tests/acceptance/{new.spec.js => new.spec.ts} | 69 ++++++++++++------- 2 files changed, 52 insertions(+), 24 deletions(-) rename tests/acceptance/{new.spec.js => new.spec.ts} (66%) diff --git a/packages/angular-cli/commands/new.ts b/packages/angular-cli/commands/new.ts index 81ee12b2cdca..4a9dcdf9b9af 100644 --- a/packages/angular-cli/commands/new.ts +++ b/packages/angular-cli/commands/new.ts @@ -1,5 +1,6 @@ import * as chalk from 'chalk'; import InitCommand from './init'; +import {oneLine} from 'common-tags'; const Command = require('../ember-cli/lib/models/command'); const Project = require('../ember-cli/lib/models/project'); @@ -37,6 +38,12 @@ const NewCommand = Command.extend({ `The "ng ${this.name}" command requires a name argument to be specified. ` + `For more details, use "ng help".`)); } + if (!packageName.match(/^[a-zA-Z][.0-9a-zA-Z]*(-[a-zA-Z][.0-9a-zA-Z]*)*$/)) { + return Promise.reject(new SilentError(oneLine` + Project name "${packageName}" is not valid. New project names must + start with a letter, and must contain only alphanumeric characters or dashes. + `)); + } commandOptions.name = packageName; if (commandOptions.dryRun) { diff --git a/tests/acceptance/new.spec.js b/tests/acceptance/new.spec.ts similarity index 66% rename from tests/acceptance/new.spec.js rename to tests/acceptance/new.spec.ts index 02f60bb66f96..22f938f11775 100644 --- a/tests/acceptance/new.spec.js +++ b/tests/acceptance/new.spec.ts @@ -1,18 +1,17 @@ -'use strict'; - -var fs = require('fs-extra'); -var ng = require('../helpers/ng'); -var existsSync = require('exists-sync'); -var expect = require('chai').expect; -var forEach = require('lodash/forEach'); -var walkSync = require('walk-sync'); -var Blueprint = require('angular-cli/ember-cli/lib/models/blueprint'); -var path = require('path'); -var tmp = require('../helpers/tmp'); -var root = process.cwd(); -var util = require('util'); -var EOL = require('os').EOL; -var SilentError = require('silent-error'); +const fs = require('fs-extra'); +const ng = require('../helpers/ng'); +const existsSync = require('exists-sync'); +const expect = require('chai').expect; +const forEach = require('lodash/forEach'); +const walkSync = require('walk-sync'); +const Blueprint = require('angular-cli/ember-cli/lib/models/blueprint'); +const path = require('path'); +const tmp = require('../helpers/tmp'); +const root = process.cwd(); +const util = require('util'); +const EOL = require('os').EOL; +const SilentError = require('silent-error'); + describe('Acceptance: ng new', function () { beforeEach(function () { @@ -29,10 +28,10 @@ describe('Acceptance: ng new', function () { function confirmBlueprintedForDir(dir) { return function () { - var blueprintPath = path.join(root, dir, 'files'); - var expected = walkSync(blueprintPath); - var actual = walkSync('.').sort(); - var directory = path.basename(process.cwd()); + let blueprintPath = path.join(root, dir, 'files'); + let expected = walkSync(blueprintPath); + let actual = walkSync('.').sort(); + let directory = path.basename(process.cwd()); forEach(Blueprint.renamedFiles, function (destFile, srcFile) { expected[expected.indexOf(srcFile)] = destFile; @@ -56,6 +55,28 @@ describe('Acceptance: ng new', function () { return confirmBlueprintedForDir('blueprints/ng2'); } + it('requires a valid name (!)', () => { + return ng(['new', '!', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {}); + }); + it('requires a valid name (abc-.)', () => { + return ng(['new', 'abc-.', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {}); + }); + it('requires a valid name (abc-)', () => { + return ng(['new', 'abc-', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {}); + }); + it('requires a valid name (abc-def-)', () => { + return ng(['new', 'abc-def-', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {}); + }); + it('requires a valid name (abc-123)', () => { + return ng(['new', 'abc-123', '--skip-npm', '--skip-git', '--inline-template']).then(() => { throw new Error(); }, () => {}); + }); + it('requires a valid name (abc)', () => { + return ng(['new', 'abc', '--skip-npm', '--skip-git', '--inline-template']); + }); + it('requires a valid name (abc-def)', () => { + return ng(['new', 'abc-def', '--skip-npm', '--skip-git', '--inline-template']); + }); + it('ng new foo, where foo does not yet exist, works', function () { return ng(['new', 'foo', '--skip-npm', '--skip-bower']).then(confirmBlueprinted); }); @@ -72,7 +93,7 @@ describe('Acceptance: ng new', function () { return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () { expect(!existsSync('FooApp')); - var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); + const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); expect(pkgJson.name).to.equal('foo-app'); }); }); @@ -81,7 +102,7 @@ describe('Acceptance: ng new', function () { return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () { expect(!existsSync('FooApp')); - var editorConfig = fs.readFileSync('.editorconfig', 'utf8'); + const editorConfig = fs.readFileSync('.editorconfig', 'utf8'); expect(editorConfig).to.exist; }); }); @@ -106,7 +127,7 @@ describe('Acceptance: ng new', function () { it('ng new with --dry-run does not create new directory', function () { return ng(['new', 'foo', '--dry-run']).then(function () { - var cwd = process.cwd(); + const cwd = process.cwd(); expect(cwd).to.not.match(/foo/, 'does not change cwd to foo in a dry run'); expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory'); expect(!existsSync(path.join(cwd, '.git')), 'does not create git in current directory'); @@ -116,14 +137,14 @@ describe('Acceptance: ng new', function () { it('ng new with --directory uses given directory name and has correct package name', function () { return ng(['new', 'foo', '--skip-npm', '--skip-bower', '--skip-git', '--directory=bar']) .then(function () { - var cwd = process.cwd(); + const cwd = process.cwd(); expect(cwd).to.not.match(/foo/, 'does not use app name for directory name'); expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory with app name'); expect(cwd).to.match(/bar/, 'uses given directory name'); expect(existsSync(path.join(cwd, 'bar')), 'creates new directory with specified name'); - var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); + const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); expect(pkgJson.name).to.equal('foo', 'uses app name for package name'); }); });