Skip to content

Commit

Permalink
feat(@schematics/angular): add generation for resolvers
Browse files Browse the repository at this point in the history
closes: #17569
  • Loading branch information
Jefiozie committed Oct 14, 2020
1 parent 43e5738 commit d2d274f
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/schematics/angular/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
"description": "Create a guard.",
"schema": "./guard/schema.json"
},
"resolver": {
"aliases": [ "r" ],
"factory": "./resolver",
"description": "Create a resolver.",
"schema": "./resolver/schema.json"
},
"interceptor": {
"factory": "./interceptor",
"description": "Create an interceptor.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { <%= classify(name) %>Resolver } from './<%= dasherize(name) %>.resolver';

describe('<%= classify(name) %>Resolver', () => {
let resolver: <%= classify(name) %>Resolver;

beforeEach(() => {
TestBed.configureTestingModule({});
resolver = TestBed.inject(<%= classify(name) %>Resolver);
});

it('should be created', () => {
expect(resolver).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Injectable } from '@angular/core';
import {
Router, Resolve,
RouterStateSnapshot,
ActivatedRouteSnapshot
} from '@angular/router';
import { Observable, of } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class <%= classify(name) %>Resolver implements Resolve<boolean> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return of(true);
}
}
49 changes: 49 additions & 0 deletions packages/schematics/angular/resolver/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @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 { strings } from '@angular-devkit/core';
import {
Rule,
Tree,
apply,
applyTemplates,
chain,
filter,
mergeWith,
move,
noop,
url,
} from '@angular-devkit/schematics';
import { parseName } from '../utility/parse-name';
import { createDefaultPath } from '../utility/workspace';
import { Schema } from './schema';


export default function (options: Schema): Rule {
return async (host: Tree) => {
if (options.path === undefined) {
options.path = await createDefaultPath(host, options.project as string);
}

const parsedPath = parseName(options.path, options.name);
options.name = parsedPath.name;
options.path = parsedPath.path;

const templateSource = apply(url('./files'), [
options.skipTests ? filter(path => !path.endsWith('.spec.ts.template')) : noop(),
applyTemplates({
...strings,
...options,
}),
move(parsedPath.path + (options.flat ? '' : '/' + strings.dasherize(options.name))),
]);

return chain([
mergeWith(templateSource),
]);
};
}
80 changes: 80 additions & 0 deletions packages/schematics/angular/resolver/index_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* @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 { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { Schema as ApplicationOptions } from '../application/schema';
import { Schema as WorkspaceOptions } from '../workspace/schema';
import { Schema } from './schema';

describe('resolver Schematic', () => {
const schematicRunner = new SchematicTestRunner(
'@schematics/angular',
require.resolve('../collection.json'),
);
const defaultOptions: Schema = {
name: 'foo',
flat: true,
project: 'bar',
};
const workspaceOptions: WorkspaceOptions = {
name: 'workspace',
newProjectRoot: 'projects',
version: '6.0.0',
};

const appOptions: ApplicationOptions = {
name: 'bar',
inlineStyle: false,
inlineTemplate: false,
routing: false,
skipTests: false,
skipPackageJson: false,
};
let appTree: UnitTestTree;
beforeEach(async () => {
appTree = await schematicRunner.runSchematicAsync('workspace', workspaceOptions).toPromise();
appTree = await schematicRunner.runSchematicAsync('application', appOptions, appTree)
.toPromise();
});

it('should create a resolver', async () => {
const tree = await schematicRunner.runSchematicAsync('resolver', defaultOptions, appTree)
.toPromise();
const files = tree.files;
expect(files).toContain('/projects/bar/src/app/foo.resolver.spec.ts');
expect(files).toContain('/projects/bar/src/app/foo.resolver.ts');
});

it('should respect the skipTests flag', async () => {
const options = { ...defaultOptions, skipTests: true };

const tree = await schematicRunner.runSchematicAsync('resolver', options, appTree)
.toPromise();
const files = tree.files;
expect(files).not.toContain('/projects/bar/src/app/foo.resolver.spec.ts');
expect(files).toContain('/projects/bar/src/app/foo.resolver.ts');
});

it('should respect the flat flag', async () => {
const options = { ...defaultOptions, flat: false };

const tree = await schematicRunner.runSchematicAsync('resolver', options, appTree)
.toPromise();
const files = tree.files;
expect(files).toContain('/projects/bar/src/app/foo/foo.resolver.spec.ts');
expect(files).toContain('/projects/bar/src/app/foo/foo.resolver.ts');
});

it('should respect the sourceRoot value', async () => {
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 = await schematicRunner.runSchematicAsync('resolver', defaultOptions, appTree)
.toPromise();
expect(appTree.files).toContain('/projects/bar/custom/app/foo.resolver.ts');
});
});
45 changes: 45 additions & 0 deletions packages/schematics/angular/resolver/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "http://json-schema.org/schema",
"id": "SchematicsAngularResolver",
"title": "Angular resolver Options Schema",
"type": "object",
"description": "Generates a new, generic resolver definition in the given or default project.",
"properties": {
"name": {
"type": "string",
"description": "The name of the new resolver.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What name would you like to use for the resolver?"
},
"skipTests": {
"type": "boolean",
"description": "When true, does not create \"spec.ts\" test files for the new resolver.",
"default": false,
"x-user-analytics": 12
},
"flat": {
"type": "boolean",
"description": "When true (the default), creates the new files at the top level of the current project.",
"default": true
},
"path": {
"type": "string",
"format": "path",
"description": "The path at which to create the interface that defines the resolver, relative to the current workspace.",
"visible": false
},
"project": {
"type": "string",
"description": "The name of the project.",
"$default": {
"$source": "projectName"
}
}
},
"required": [
"name"
]
}

0 comments on commit d2d274f

Please sign in to comment.