Skip to content
This repository has been archived by the owner on Apr 9, 2022. It is now read-only.

Commit

Permalink
fix(@schematics/angular): Fix usage of sourceRoot configuration value
Browse files Browse the repository at this point in the history
  • Loading branch information
Brocco authored and hansl committed Jun 5, 2018
1 parent 3017ef2 commit 524c7cf
Show file tree
Hide file tree
Showing 20 changed files with 176 additions and 19 deletions.
4 changes: 2 additions & 2 deletions packages/schematics/angular/class/index.ts
Expand Up @@ -22,6 +22,7 @@ import {
} from '@angular-devkit/schematics';
import { getWorkspace } from '../utility/config';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as ClassOptions } from './schema';

export default function (options: ClassOptions): Rule {
Expand All @@ -33,8 +34,7 @@ export default function (options: ClassOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

options.type = !!options.type ? `.${options.type}` : '';
Expand Down
8 changes: 8 additions & 0 deletions packages/schematics/angular/class/index_spec.ts
Expand Up @@ -88,4 +88,12 @@ describe('Class Schematic', () => {
const tree = schematicRunner.runSchematic('class', options, appTree);
expect(tree.files.indexOf('/zzz/foo.ts')).toBeGreaterThanOrEqual(0);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('class', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.ts')).toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/component/index.ts
Expand Up @@ -31,6 +31,7 @@ import { InsertChange } from '../utility/change';
import { getWorkspace } from '../utility/config';
import { buildRelativePath, findModuleFromOptions } from '../utility/find-module';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { validateHtmlSelector, validateName } from '../utility/validation';
import { Schema as ComponentOptions } from './schema';

Expand Down Expand Up @@ -134,8 +135,7 @@ export default function(options: ComponentOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

options.module = findModuleFromOptions(host, options);
Expand Down
15 changes: 15 additions & 0 deletions packages/schematics/angular/component/index_spec.ts
Expand Up @@ -287,4 +287,19 @@ describe('Component Schematic', () => {
const content = appTree.readContent('/projects/bar/src/app/sub/test/test.component.ts');
expect(content).toMatch(/selector: 'app-test'/);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));

// should fail without a module in that dir
expect(() => schematicRunner.runSchematic('component', defaultOptions, appTree)).toThrow();

// move the module
appTree.rename('/projects/bar/src/app/app.module.ts', '/projects/bar/custom/app/app.module.ts');
appTree = schematicRunner.runSchematic('component', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo/foo.component.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/directive/index.ts
Expand Up @@ -27,6 +27,7 @@ import { InsertChange } from '../utility/change';
import { getWorkspace } from '../utility/config';
import { buildRelativePath, findModuleFromOptions } from '../utility/find-module';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { validateHtmlSelector } from '../utility/validation';
import { Schema as DirectiveOptions } from './schema';

Expand Down Expand Up @@ -110,8 +111,7 @@ export default function (options: DirectiveOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

options.module = findModuleFromOptions(host, options);
Expand Down
15 changes: 15 additions & 0 deletions packages/schematics/angular/directive/index_spec.ts
Expand Up @@ -154,4 +154,19 @@ describe('Directive Schematic', () => {
const content = tree.readContent('/projects/bar/src/app/foo.directive.ts');
expect(content).toMatch(/selector: '\[foo\]'/);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));

// should fail without a module in that dir
expect(() => schematicRunner.runSchematic('directive', defaultOptions, appTree)).toThrow();

// move the module
appTree.rename('/projects/bar/src/app/app.module.ts', '/projects/bar/custom/app/app.module.ts');
appTree = schematicRunner.runSchematic('directive', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.directive.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/enum/index.ts
Expand Up @@ -21,6 +21,7 @@ import {
} from '@angular-devkit/schematics';
import { getWorkspace } from '../utility/config';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as EnumOptions } from './schema';


Expand All @@ -33,8 +34,7 @@ export default function (options: EnumOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

const parsedPath = parseName(options.path, options.name);
Expand Down
8 changes: 7 additions & 1 deletion packages/schematics/angular/enum/index_spec.ts
Expand Up @@ -54,5 +54,11 @@ describe('Enum Schematic', () => {
expect(content).toMatch('export enum Foo {');
});


it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('enum', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.enum.ts')).toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/guard/index.ts
Expand Up @@ -23,6 +23,7 @@ import {
} from '@angular-devkit/schematics';
import { getWorkspace } from '../utility/config';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as GuardOptions } from './schema';


Expand All @@ -35,8 +36,7 @@ export default function (options: GuardOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

const parsedPath = parseName(options.path, options.name);
Expand Down
9 changes: 9 additions & 0 deletions packages/schematics/angular/guard/index_spec.ts
Expand Up @@ -59,4 +59,13 @@ describe('Guard Schematic', () => {
expect(files.indexOf('/projects/bar/src/app/foo.guard.spec.ts')).toEqual(-1);
expect(files.indexOf('/projects/bar/src/app/foo.guard.ts')).toBeGreaterThanOrEqual(0);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('guard', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.guard.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/interface/index.ts
Expand Up @@ -21,6 +21,7 @@ import {
} from '@angular-devkit/schematics';
import { getWorkspace } from '../utility/config';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as InterfaceOptions } from './schema';


Expand All @@ -33,8 +34,7 @@ export default function (options: InterfaceOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

const parsedPath = parseName(options.path, options.name);
Expand Down
8 changes: 8 additions & 0 deletions packages/schematics/angular/interface/index_spec.ts
Expand Up @@ -63,4 +63,12 @@ describe('Interface Schematic', () => {
expect(tree.files.indexOf('/projects/bar/src/app/foo.model.ts')).toBeGreaterThanOrEqual(0);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('interface', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/module/index.ts
Expand Up @@ -27,6 +27,7 @@ import { InsertChange } from '../utility/change';
import { getWorkspace } from '../utility/config';
import { findModuleFromOptions } from '../utility/find-module';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as ModuleOptions } from './schema';


Expand Down Expand Up @@ -79,8 +80,7 @@ export default function (options: ModuleOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}
if (options.module) {
options.module = findModuleFromOptions(host, options);
Expand Down
9 changes: 9 additions & 0 deletions packages/schematics/angular/module/index_spec.ts
Expand Up @@ -115,4 +115,13 @@ describe('Module Schematic', () => {
expect(files.indexOf('/projects/bar/src/app/two-word/two-word.module.spec.ts'))
.toBeGreaterThanOrEqual(0);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('module', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo/foo.module.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/pipe/index.ts
Expand Up @@ -27,6 +27,7 @@ import { InsertChange } from '../utility/change';
import { getWorkspace } from '../utility/config';
import { buildRelativePath, findModuleFromOptions } from '../utility/find-module';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as PipeOptions } from './schema';


Expand Down Expand Up @@ -94,8 +95,7 @@ export default function (options: PipeOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

const parsedPath = parseName(options.path, options.name);
Expand Down
15 changes: 15 additions & 0 deletions packages/schematics/angular/pipe/index_spec.ts
Expand Up @@ -109,4 +109,19 @@ describe('Pipe Schematic', () => {
const content = getFileContent(tree, routingModulePath);
expect(content).toMatch(/import { FooPipe } from '.\/foo.pipe/);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));

// should fail without a module in that dir
expect(() => schematicRunner.runSchematic('pipe', defaultOptions, appTree)).toThrow();

// move the module
appTree.rename('/projects/bar/src/app/app.module.ts', '/projects/bar/custom/app/app.module.ts');
appTree = schematicRunner.runSchematic('pipe', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo.pipe.ts'))
.toBeGreaterThanOrEqual(0);
});
});
4 changes: 2 additions & 2 deletions packages/schematics/angular/service/index.ts
Expand Up @@ -21,6 +21,7 @@ import {
} from '@angular-devkit/schematics';
import { getWorkspace } from '../utility/config';
import { parseName } from '../utility/parse-name';
import { buildDefaultPath } from '../utility/project';
import { Schema as ServiceOptions } from './schema';

export default function (options: ServiceOptions): Rule {
Expand All @@ -32,8 +33,7 @@ export default function (options: ServiceOptions): Rule {
const project = workspace.projects[options.project];

if (options.path === undefined) {
const projectDirName = project.projectType === 'application' ? 'app' : 'lib';
options.path = `/${project.root}/src/${projectDirName}`;
options.path = buildDefaultPath(project);
}

const parsedPath = parseName(options.path, options.name);
Expand Down
9 changes: 9 additions & 0 deletions packages/schematics/angular/service/index_spec.ts
Expand Up @@ -70,4 +70,13 @@ describe('Service Schematic', () => {
expect(files.indexOf('/projects/bar/src/app/foo/foo.service.ts')).toBeGreaterThanOrEqual(0);
expect(files.indexOf('/projects/bar/src/app/foo/foo.service.spec.ts')).toEqual(-1);
});

it('should respect the sourceRoot value', () => {
const config = JSON.parse(appTree.readContent('/angular.json'));
config.projects.bar.sourceRoot = 'projects/bar/custom';
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
appTree = schematicRunner.runSchematic('service', defaultOptions, appTree);
expect(appTree.files.indexOf('/projects/bar/custom/app/foo/foo.service.ts'))
.toBeGreaterThanOrEqual(0);
});
});
23 changes: 23 additions & 0 deletions packages/schematics/angular/utility/project.ts
@@ -0,0 +1,23 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { WorkspaceProject } from '../utility/config';


/**
* Build a default project path for generating.
* @param project The project to build the path for.
*/
export function buildDefaultPath(project: WorkspaceProject): string {
const root = project.sourceRoot
? `/${project.sourceRoot}/`
: `/${project.root}/src/`;

const projectDirName = project.projectType === 'application' ? 'app' : 'lib';

return `${root}${projectDirName}`;
}
40 changes: 40 additions & 0 deletions packages/schematics/angular/utility/project_spec.ts
@@ -0,0 +1,40 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { WorkspaceProject } from '../utility/config';
import { buildDefaultPath } from './project';


describe('project', () => {
describe('buildDefaultPath', () => {
let project: WorkspaceProject;
beforeEach(() => {
project = {
projectType: 'application',
root: 'foo',
prefix: 'app',
};
});

it('should handle projectType of application', () => {
const result = buildDefaultPath(project);
expect(result).toEqual('/foo/src/app');
});

it('should handle projectType of library', () => {
project = { ...project, projectType: 'library' };
const result = buildDefaultPath(project);
expect(result).toEqual('/foo/src/lib');
});

it('should handle sourceRoot', () => {
project = { ...project, sourceRoot: 'foo/bar/custom' };
const result = buildDefaultPath(project);
expect(result).toEqual('/foo/bar/custom/app');
});
});
});

0 comments on commit 524c7cf

Please sign in to comment.