Skip to content

Commit

Permalink
feat(builders): introduce node build and execute builders
Browse files Browse the repository at this point in the history
These builders handle building and executing node applications
  • Loading branch information
FrozenPandaz authored and vsavkin committed Oct 1, 2018
1 parent 039c151 commit 469af6e
Show file tree
Hide file tree
Showing 16 changed files with 1,416 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ node_modules
.idea
.vscode
dist
build
/build
test
.DS_Store
tmp
Expand Down
4 changes: 2 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tmp
build
/build
node_modules
/package.json
packages/schematics/src/collection/**/files/*.json
packages/schematics/src/collection/**/files/*.json
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"checkformat": "prettier \"./**/*.{ts,js,json,css,md}\" \"!./**/{__name__,__directory__}/**\" --list-different"
},
"devDependencies": {
"@angular-devkit/architect": "0.8.3",
"@angular-devkit/build-angular": "0.8.3",
"@angular-devkit/build-webpack": "0.8.3",
"@angular-devkit/core": "0.8.3",
"@angular-devkit/schematics": "0.8.3",
"@angular/cli": "6.2.3",
Expand All @@ -39,15 +41,19 @@
"@schematics/angular": "0.8.3",
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/jest": "^23.3.2",
"@types/node": "~8.9.4",
"@types/prettier": "^1.10.0",
"@types/webpack": "^4.4.11",
"@types/yargs": "^11.0.0",
"angular": "1.6.6",
"app-root-path": "^2.0.1",
"circular-dependency-plugin": "^5.0.2",
"commitizen": "^2.10.1",
"conventional-changelog-cli": "^1.3.21",
"cosmiconfig": "^4.0.0",
"cz-conventional-changelog": "^2.1.0",
"fork-ts-checker-webpack-plugin": "^0.4.9",
"fs-extra": "5.0.0",
"graphviz": "^0.0.8",
"husky": "^1.0.0-rc.13",
Expand All @@ -60,6 +66,7 @@
"karma-chrome-launcher": "~2.2.0",
"karma-jasmine": "~1.1.1",
"karma-webpack": "2.0.4",
"license-webpack-plugin": "^1.4.0",
"lint-staged": "^7.2.2",
"ng-packagr": "3.0.6",
"npm-run-all": "4.1.2",
Expand All @@ -74,6 +81,8 @@
"tslint": "5.11.0",
"typescript": "~2.9.2",
"viz.js": "^1.8.1",
"webpack": "4.9.2",
"webpack-node-externals": "^1.7.2",
"yargs": "^11.0.0",
"yargs-parser": "10.0.0",
"zone.js": "^0.8.26"
Expand Down
8 changes: 7 additions & 1 deletion packages/builders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
"builders": "./src/builders.json",
"dependencies": {
"@angular-devkit/architect": "~0.8.0",
"rxjs": "6.2.2"
"@angular-devkit/build-webpack": "~0.8.0",
"fork-ts-checker-webpack-plugin": "0.4.9",
"license-webpack-plugin": "^1.4.0",
"rxjs": "6.2.2",
"ts-loader": "4.5.0",
"webpack": "4.9.2",
"webpack-node-externals": "1.7.2"
}
}
12 changes: 11 additions & 1 deletion packages/builders/src/builders.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
{
"$schema": "../architect/src/builders-schema.json",
"$schema": "@angular-devkit/architect/src/builders-schema.json",
"builders": {
"node-build": {
"class": "./node/build/node-build.builder",
"schema": "./node/build/schema.json",
"description": "Build a Node application"
},
"node-execute": {
"class": "./node/execute/node-execute.builder",
"schema": "./node/execute/schema.json",
"description": "Build a Node application"
},
"jest": {
"class": "./jest/jest.builder",
"schema": "./jest/schema.json",
Expand Down
36 changes: 8 additions & 28 deletions packages/builders/src/jest/jest.builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import JestBuilder from './jest.builder';
import { normalize } from '@angular-devkit/core';
import * as jestCLI from 'jest';
jest.mock('jest');
const { runCLI } = require('jest');
import * as path from 'path';

describe('Jest Builder', () => {
let builder: JestBuilder;

beforeEach(() => {
builder = new JestBuilder();
});

it('should send appropriate options to jestCLI', () => {
const runCLI = spyOn(jestCLI, 'runCLI').and.returnValue(
runCLI.mockReturnValue(
Promise.resolve({
results: {
success: true
}
})
);
});

it('should send appropriate options to jestCLI', () => {
const root = normalize('/root');
builder
.run({
Expand Down Expand Up @@ -46,13 +47,6 @@ describe('Jest Builder', () => {
});

it('should send other options to jestCLI', () => {
const runCLI = spyOn(jestCLI, 'runCLI').and.returnValue(
Promise.resolve({
results: {
success: true
}
})
);
const root = normalize('/root');
builder
.run({
Expand Down Expand Up @@ -98,19 +92,12 @@ describe('Jest Builder', () => {
);
});

it('should send the main to jestCLI', () => {
const runCLI = spyOn(jestCLI, 'runCLI').and.returnValue(
Promise.resolve({
results: {
success: true
}
})
);
it('should send the main to runCLI', () => {
const root = normalize('/root');
builder
.run({
root,
builder: '',
builder: '@nrwl/builders:jest',
projectType: 'application',
options: {
jestConfig: './jest.config.js',
Expand Down Expand Up @@ -139,13 +126,6 @@ describe('Jest Builder', () => {
});

it('should return the proper result', async done => {
spyOn(jestCLI, 'runCLI').and.returnValue(
Promise.resolve({
results: {
success: true
}
})
);
const root = normalize('/root');
const result = await builder
.run({
Expand Down
4 changes: 2 additions & 2 deletions packages/builders/src/jest/jest.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { map } from 'rxjs/operators';

import * as path from 'path';

import { runCLI as runJest } from 'jest';
const { runCLI } = require('jest');

export interface JestBuilderOptions {
jestConfig: string;
Expand Down Expand Up @@ -61,7 +61,7 @@ export default class JestBuilder implements Builder<JestBuilderOptions> {
);
}

return from(runJest(config, [options.jestConfig])).pipe(
return from(runCLI(config, [options.jestConfig])).pipe(
map((results: any) => {
return {
success: results.results.success
Expand Down
162 changes: 162 additions & 0 deletions packages/builders/src/node/build/node-build.builder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { normalize } from '@angular-devkit/core';
import { TestLogger } from '@angular-devkit/architect/testing';
import BuildNodeBuilder from './node-build.builder';
import { BuildNodeBuilderOptions } from './node-build.builder';
import { of } from 'rxjs';
import * as fs from 'fs';

describe('NodeBuildBuilder', () => {
let builder: BuildNodeBuilder;
let testOptions: BuildNodeBuilderOptions;

beforeEach(() => {
builder = new BuildNodeBuilder({
host: <any>{},
logger: new TestLogger('test'),
workspace: <any>{
root: '/root'
},
architect: <any>{}
});
testOptions = {
main: 'apps/nodeapp/src/main.ts',
tsConfig: 'apps/nodeapp/tsconfig.app.json',
outputPath: 'dist/apps/nodeapp',
externalDependencies: 'all',
fileReplacements: [
{
replace: 'apps/environment/environment.ts',
with: 'apps/environment/environment.prod.ts'
},
{
replace: 'module1.ts',
with: 'module2.ts'
}
]
};
});

describe('run', () => {
it('should call runWebpack', () => {
const runWebpack = spyOn(
builder.webpackBuilder,
'runWebpack'
).and.returnValue(
of({
success: true
})
);

builder.run({
root: normalize('/root'),
projectType: 'application',
builder: '@nrwl/builders:node-build',
options: testOptions
});

expect(runWebpack).toHaveBeenCalled();
});

it('should emit the outfile along with success', async () => {
const runWebpack = spyOn(
builder.webpackBuilder,
'runWebpack'
).and.returnValue(
of({
success: true
})
);

const buildEvent = await builder
.run({
root: normalize('/root'),
projectType: 'application',
builder: '@nrwl/builders:node-build',
options: testOptions
})
.toPromise();

expect(buildEvent.success).toEqual(true);
expect(buildEvent.outfile).toEqual('/root/dist/apps/nodeapp/main.js');
});

describe('when stats json option is passed', () => {
beforeEach(() => {
const stats = {
stats: 'stats'
};
spyOn(builder.webpackBuilder, 'runWebpack').and.callFake((opts, cb) => {
cb({
toJson: () => stats,
toString: () => JSON.stringify(stats)
});
return of({
success: true
});
});
spyOn(fs, 'writeFileSync');
});

it('should generate a stats json', async () => {
await builder
.run({
root: normalize('/root'),
projectType: 'application',
builder: '@nrwl/builders:node-build',
options: {
...testOptions,
statsJson: true
}
})
.toPromise();

expect(fs.writeFileSync).toHaveBeenCalledWith(
'/root/dist/apps/nodeapp/stats.json',
JSON.stringify(
{
stats: 'stats'
},
null,
2
)
);
});
});
});

describe('options normalization', () => {
it('should add the root', () => {
const result = (<any>builder).normalizeOptions(testOptions);
expect(result.root).toEqual('/root');
});

it('should resolve main from root', () => {
const result = (<any>builder).normalizeOptions(testOptions);
expect(result.main).toEqual('/root/apps/nodeapp/src/main.ts');
});

it('should resolve the output path', () => {
const result = (<any>builder).normalizeOptions(testOptions);
expect(result.outputPath).toEqual('/root/dist/apps/nodeapp');
});

it('should resolve the tsConfig path', () => {
const result = (<any>builder).normalizeOptions(testOptions);
expect(result.tsConfig).toEqual('/root/apps/nodeapp/tsconfig.app.json');
});

it('should resolve the file replacement paths', () => {
const result = (<any>builder).normalizeOptions(testOptions);
expect(result.fileReplacements).toEqual([
{
replace: '/root/apps/environment/environment.ts',
with: '/root/apps/environment/environment.prod.ts'
},
{
replace: '/root/module1.ts',
with: '/root/module2.ts'
}
]);
});
});
});
Loading

0 comments on commit 469af6e

Please sign in to comment.