feat(schematics): add schematics for jest
This commit is contained in:
parent
e608211f46
commit
5a547ccadd
@ -1,3 +1,4 @@
|
||||
tmp
|
||||
build
|
||||
node_modules
|
||||
node_modules
|
||||
packages/schematics/src/collection/**/files/*.json
|
||||
41
e2e/schematics/jest.test.ts
Normal file
41
e2e/schematics/jest.test.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import {
|
||||
newProject,
|
||||
runCLI,
|
||||
newLib,
|
||||
copyMissingPackages,
|
||||
updateFile,
|
||||
readJson,
|
||||
runCommand,
|
||||
runCLIAsync
|
||||
} from '../utils';
|
||||
|
||||
describe('Jest', () => {
|
||||
beforeAll(() => {
|
||||
newProject();
|
||||
runCLI('generate jest', {
|
||||
silenceError: true
|
||||
});
|
||||
// TODO: remove this hack after there's a version of @nrwl/builders published
|
||||
const packageJson = readJson('package.json');
|
||||
packageJson.devDependencies['@nrwl/builders'] =
|
||||
'../../build/packages/builders';
|
||||
updateFile('package.json', JSON.stringify(packageJson));
|
||||
runCommand('npm install');
|
||||
copyMissingPackages();
|
||||
});
|
||||
|
||||
it(
|
||||
'should be able to generate a testable library using jest',
|
||||
async done => {
|
||||
newLib('jestlib --unit-test-runner jest');
|
||||
await Promise.all([
|
||||
runCLIAsync('generate service test --project jestlib'),
|
||||
runCLIAsync('generate component test --project jestlib')
|
||||
]);
|
||||
const jestResult = await runCLIAsync('test jestlib');
|
||||
expect(jestResult.stderr).toContain('Test Suites: 3 passed, 3 total');
|
||||
done();
|
||||
},
|
||||
10000
|
||||
);
|
||||
});
|
||||
33
e2e/utils.ts
33
e2e/utils.ts
@ -1,4 +1,4 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { execSync, exec } from 'child_process';
|
||||
import { readFileSync, statSync, writeFileSync } from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
@ -84,6 +84,37 @@ function copyNodeModule(path: string, name: string) {
|
||||
execSync(`cp -a node_modules/${name} tmp/${path}/node_modules/${name}`);
|
||||
}
|
||||
|
||||
export function runCommandAsync(
|
||||
command: string,
|
||||
opts = {
|
||||
silenceError: false
|
||||
}
|
||||
): Promise<{ stdout: string; stderr: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(
|
||||
command,
|
||||
{
|
||||
cwd: `./tmp/proj`
|
||||
},
|
||||
(err, stdout, stderr) => {
|
||||
if (!opts.silenceError && err) {
|
||||
reject(err);
|
||||
}
|
||||
resolve({ stdout, stderr });
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function runCLIAsync(
|
||||
command: string,
|
||||
opts = {
|
||||
silenceError: false
|
||||
}
|
||||
): Promise<{ stdout: string; stderr: string }> {
|
||||
return runCommandAsync(`./node_modules/.bin/ng ${command}`, opts);
|
||||
}
|
||||
|
||||
export function runCLI(
|
||||
command?: string,
|
||||
opts = {
|
||||
|
||||
@ -36,6 +36,19 @@
|
||||
"description": "Add NgRx support to a module"
|
||||
},
|
||||
|
||||
"jest": {
|
||||
"factory": "./collection/jest",
|
||||
"schema": "./collection/jest/schema.json",
|
||||
"description": "Add Jest configuration to the workspace"
|
||||
},
|
||||
|
||||
"jest-project": {
|
||||
"factory": "./collection/jest-project",
|
||||
"schema": "./collection/jest-project/schema.json",
|
||||
"description": "Add Jest configuration to a project",
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"upgrade-module": {
|
||||
"factory": "./collection/upgrade-module",
|
||||
"schema": "./collection/upgrade-module/schema.json",
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
name: '<%= project %>',
|
||||
preset: '<%= offsetFromRoot %>jest.config.js',
|
||||
coverageDirectory: '<%= offsetFromRoot %>coverage/<%= projectRoot %>'
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
import 'jest-preset-angular';
|
||||
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "<%= offsetFromRoot %>dist/out-tsc/<%= projectRoot %>",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"files": [<% if(!skipSetupFile) { %>"src/test-setup.ts", <% } %>"src/polyfills.ts"],
|
||||
"include": ["**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
||||
96
packages/schematics/src/collection/jest-project/index.ts
Normal file
96
packages/schematics/src/collection/jest-project/index.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import {
|
||||
Rule,
|
||||
Tree,
|
||||
mergeWith,
|
||||
chain,
|
||||
url,
|
||||
apply,
|
||||
SchematicContext,
|
||||
move,
|
||||
template,
|
||||
noop,
|
||||
filter
|
||||
} from '@angular-devkit/schematics';
|
||||
import {
|
||||
getProjectConfig,
|
||||
readJsonInTree,
|
||||
updateJsonInTree
|
||||
} from '../../utils/ast-utils';
|
||||
import { offsetFromRoot } from '../../utils/common';
|
||||
import { join, normalize } from '@angular-devkit/core';
|
||||
|
||||
export interface JestProjectSchema {
|
||||
project: string;
|
||||
skipSetupFile: boolean;
|
||||
}
|
||||
|
||||
function generateFiles(options: JestProjectSchema): Rule {
|
||||
return (host, context) => {
|
||||
const projectConfig = getProjectConfig(host, options.project);
|
||||
return mergeWith(
|
||||
apply(url('./files'), [
|
||||
template({
|
||||
tmpl: '',
|
||||
...options,
|
||||
projectRoot: projectConfig.root,
|
||||
offsetFromRoot: offsetFromRoot(projectConfig.root)
|
||||
}),
|
||||
options.skipSetupFile
|
||||
? filter(file => file !== '/src/test-setup.ts')
|
||||
: noop(),
|
||||
move(projectConfig.root)
|
||||
])
|
||||
)(host, context);
|
||||
};
|
||||
}
|
||||
|
||||
function updateAngularJson(options: JestProjectSchema): Rule {
|
||||
return updateJsonInTree('angular.json', json => {
|
||||
const projectConfig = json.projects[options.project];
|
||||
projectConfig.architect.test = {
|
||||
builder: '@nrwl/builders:jest',
|
||||
options: {
|
||||
jestConfig: join(normalize(projectConfig.root), 'jest.config.js'),
|
||||
tsConfig: join(normalize(projectConfig.root), 'tsconfig.spec.json')
|
||||
}
|
||||
};
|
||||
if (!options.skipSetupFile) {
|
||||
projectConfig.architect.test.options.setupFile = join(
|
||||
normalize(projectConfig.root),
|
||||
'src/test-setup.ts'
|
||||
);
|
||||
}
|
||||
if (projectConfig.architect.lint) {
|
||||
projectConfig.architect.lint.options.tsConfig = [
|
||||
...projectConfig.architect.lint.options.tsConfig,
|
||||
join(normalize(projectConfig.root), 'tsconfig.spec.json')
|
||||
];
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function check(options: JestProjectSchema) {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const projectConfig = getProjectConfig(host, options.project);
|
||||
if (projectConfig.architect.test) {
|
||||
throw new Error(
|
||||
`${options.project} already has a test architect option.`
|
||||
);
|
||||
}
|
||||
const packageJson = readJsonInTree(host, 'package.json');
|
||||
if (!packageJson.devDependencies.jest) {
|
||||
throw new Error(
|
||||
`Your workspace does not have jest installed. Please run "ng generate jest" to setup your workspace to run tests with jest.`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function(options: JestProjectSchema): Rule {
|
||||
return chain([
|
||||
check(options),
|
||||
generateFiles(options),
|
||||
updateAngularJson(options)
|
||||
]);
|
||||
}
|
||||
@ -0,0 +1,169 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { Tree, VirtualTree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace } from '../../utils/testing-utils';
|
||||
import { readJsonInTree } from '@nrwl/schematics/src/utils/ast-utils';
|
||||
|
||||
describe('lib', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/schematics',
|
||||
path.join(__dirname, '../../collection.json')
|
||||
);
|
||||
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
appTree = new VirtualTree();
|
||||
appTree = createEmptyWorkspace(appTree);
|
||||
appTree = schematicRunner.runSchematic('jest', {}, appTree);
|
||||
});
|
||||
|
||||
it('should generate files', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(resultTree.exists('/libs/lib1/src/test-setup.ts')).toBeTruthy();
|
||||
expect(resultTree.exists('/libs/lib1/jest.config.js')).toBeTruthy();
|
||||
expect(resultTree.exists('/libs/lib1/tsconfig.spec.json')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should alter angular.json', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const angularJson = readJsonInTree(resultTree, 'angular.json');
|
||||
expect(angularJson.projects.lib1.architect.test).toEqual({
|
||||
builder: '@nrwl/builders:jest',
|
||||
options: {
|
||||
jestConfig: 'libs/lib1/jest.config.js',
|
||||
setupFile: 'libs/lib1/src/test-setup.ts',
|
||||
tsConfig: 'libs/lib1/tsconfig.spec.json'
|
||||
}
|
||||
});
|
||||
expect(angularJson.projects.lib1.architect.lint.options.tsConfig).toContain(
|
||||
'libs/lib1/tsconfig.spec.json'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a tsconfig.spec.json', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tsConfig = readJsonInTree(resultTree, 'libs/lib1/tsconfig.spec.json');
|
||||
expect(tsConfig).toEqual({
|
||||
extends: '../../tsconfig.json',
|
||||
compilerOptions: {
|
||||
module: 'commonjs',
|
||||
outDir: '../../dist/out-tsc/libs/lib1',
|
||||
types: ['jest', 'node']
|
||||
},
|
||||
files: ['src/test-setup.ts', 'src/polyfills.ts'],
|
||||
include: ['**/*.spec.ts', '**/*.d.ts']
|
||||
});
|
||||
});
|
||||
|
||||
describe('--skip-setup-file', () => {
|
||||
it('should generate src/test-setup.ts', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1',
|
||||
skipSetupFile: true
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(resultTree.exists('src/test-setup.ts')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not list the setup file in angular.json', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1',
|
||||
skipSetupFile: true
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const angularJson = readJsonInTree(resultTree, 'angular.json');
|
||||
expect(
|
||||
angularJson.projects.lib1.architect.test.options.setupFile
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not list the setup file in tsconfig.spec.json', () => {
|
||||
appTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{
|
||||
name: 'lib1',
|
||||
unitTestRunner: 'none'
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'jest-project',
|
||||
{
|
||||
project: 'lib1',
|
||||
skipSetupFile: true
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tsConfig = readJsonInTree(
|
||||
resultTree,
|
||||
'libs/lib1/tsconfig.spec.json'
|
||||
);
|
||||
expect(tsConfig.files).not.toContain('src/test-setup.ts');
|
||||
});
|
||||
});
|
||||
});
|
||||
21
packages/schematics/src/collection/jest-project/schema.json
Normal file
21
packages/schematics/src/collection/jest-project/schema.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "Nx Jest Project Schematics Schema",
|
||||
"title": "Create Jest Configuration for the workspace",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project": {
|
||||
"type": "string",
|
||||
"description": "The name of the project.",
|
||||
"$default": {
|
||||
"$source": "projectName"
|
||||
}
|
||||
},
|
||||
"skipSetupFile": {
|
||||
"type": "boolean",
|
||||
"description": "Skips the setup file required for angular",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
10
packages/schematics/src/collection/jest/files/jest.config.js
Normal file
10
packages/schematics/src/collection/jest/files/jest.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
|
||||
transform: {
|
||||
'^.+\\.(ts|js|html)$': 'jest-preset-angular/preprocessor.js'
|
||||
},
|
||||
resolver: '@nrwl/builders/plugins/jest/resolver',
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ['html']
|
||||
};
|
||||
29
packages/schematics/src/collection/jest/index.ts
Normal file
29
packages/schematics/src/collection/jest/index.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import {
|
||||
mergeWith,
|
||||
SchematicContext,
|
||||
chain,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||
import { updateJsonInTree } from '../../utils/ast-utils';
|
||||
import { jestVersion, nxVersion } from '../../lib-versions';
|
||||
import { Rule } from '@angular-devkit/schematics';
|
||||
|
||||
const updatePackageJson = updateJsonInTree('package.json', json => {
|
||||
json.devDependencies = {
|
||||
...json.devDependencies,
|
||||
'@nrwl/builders': nxVersion,
|
||||
jest: jestVersion,
|
||||
'@types/jest': jestVersion,
|
||||
'jest-preset-angular': '6.0.0'
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
function addInstall(_, context: SchematicContext) {
|
||||
context.addTask(new NodePackageInstallTask());
|
||||
}
|
||||
|
||||
export default function(): Rule {
|
||||
return chain([mergeWith(url('./files')), updatePackageJson, addInstall]);
|
||||
}
|
||||
33
packages/schematics/src/collection/jest/jest.spec.ts
Normal file
33
packages/schematics/src/collection/jest/jest.spec.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { Tree, VirtualTree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace, createLib } from '../../utils/testing-utils';
|
||||
import { readJsonInTree } from '@nrwl/schematics/src/utils/ast-utils';
|
||||
|
||||
describe('lib', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/schematics',
|
||||
path.join(__dirname, '../../collection.json')
|
||||
);
|
||||
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
appTree = new VirtualTree();
|
||||
appTree = createEmptyWorkspace(appTree);
|
||||
});
|
||||
|
||||
it('should generate files', () => {
|
||||
const resultTree = schematicRunner.runSchematic('jest', {}, appTree);
|
||||
expect(resultTree.exists('jest.config.js')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should add dependencies', () => {
|
||||
const resultTree = schematicRunner.runSchematic('jest', {}, appTree);
|
||||
const packageJson = readJsonInTree(resultTree, 'package.json');
|
||||
expect(packageJson.devDependencies.jest).toBeDefined();
|
||||
expect(packageJson.devDependencies['@nrwl/builders']).toBeDefined();
|
||||
expect(packageJson.devDependencies['@types/jest']).toBeDefined();
|
||||
expect(packageJson.devDependencies['jest-preset-angular']).toBeDefined();
|
||||
});
|
||||
});
|
||||
8
packages/schematics/src/collection/jest/schema.json
Normal file
8
packages/schematics/src/collection/jest/schema.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "Nx Jest Schematics Schema",
|
||||
"title": "Create Jest Configuration for the workspace",
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
@ -5,7 +5,8 @@ import {
|
||||
noop,
|
||||
Rule,
|
||||
Tree,
|
||||
SchematicContext
|
||||
SchematicContext,
|
||||
schematic
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import * as path from 'path';
|
||||
@ -33,6 +34,7 @@ import {
|
||||
import { formatFiles } from '../../utils/rules/format-files';
|
||||
import { updateKarmaConf } from '../../utils/rules/update-karma-conf';
|
||||
import { excludeUnnecessaryFiles } from '@nrwl/schematics/src/utils/rules/filter-tree';
|
||||
import { join, normalize } from '@angular-devkit/core';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
name: string;
|
||||
@ -240,6 +242,12 @@ function updateProject(options: NormalizedSchema): Rule {
|
||||
host.delete(path.join(options.projectRoot, 'package.json'));
|
||||
}
|
||||
|
||||
if (options.unitTestRunner !== 'karma') {
|
||||
host.delete(path.join(options.projectRoot, 'karma.conf.js'));
|
||||
host.delete(path.join(options.projectRoot, 'src/test.ts'));
|
||||
host.delete(path.join(options.projectRoot, 'tsconfig.spec.json'));
|
||||
}
|
||||
|
||||
host.overwrite(
|
||||
path.join(libRoot, `${options.name}.module.ts`),
|
||||
`
|
||||
@ -253,26 +261,29 @@ function updateProject(options: NormalizedSchema): Rule {
|
||||
export class ${options.moduleName} { }
|
||||
`
|
||||
);
|
||||
host.create(
|
||||
path.join(libRoot, `${options.name}.module.spec.ts`),
|
||||
`
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { ${options.moduleName} } from './${options.name}.module';
|
||||
|
||||
describe('${options.moduleName}', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ ${options.moduleName} ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(${options.moduleName}).toBeDefined();
|
||||
if (options.unitTestRunner !== 'none') {
|
||||
host.create(
|
||||
path.join(libRoot, `${options.name}.module.spec.ts`),
|
||||
`
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { ${options.moduleName} } from './${options.name}.module';
|
||||
|
||||
describe('${options.moduleName}', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ ${options.moduleName} ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(${options.moduleName}).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
`
|
||||
);
|
||||
`
|
||||
);
|
||||
}
|
||||
host.overwrite(
|
||||
`${options.projectRoot}/src/index.ts`,
|
||||
`
|
||||
@ -293,6 +304,16 @@ describe('${options.moduleName}', () => {
|
||||
delete fixedProject.architect.build;
|
||||
}
|
||||
|
||||
if (options.unitTestRunner !== 'karma') {
|
||||
delete fixedProject.architect.test;
|
||||
|
||||
fixedProject.architect.lint.options.tsConfig = fixedProject.architect.lint.options.tsConfig.filter(
|
||||
path =>
|
||||
path !==
|
||||
join(normalize(options.projectRoot), 'tsconfig.spec.json')
|
||||
);
|
||||
}
|
||||
|
||||
json.projects[options.name] = fixedProject;
|
||||
return json;
|
||||
}),
|
||||
@ -309,18 +330,6 @@ describe('${options.moduleName}', () => {
|
||||
}
|
||||
};
|
||||
}),
|
||||
updateJsonInTree(`${options.projectRoot}/tsconfig.spec.json`, json => {
|
||||
return {
|
||||
...json,
|
||||
extends: `${offsetFromRoot(options.projectRoot)}tsconfig.json`,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
outDir: `${offsetFromRoot(options.projectRoot)}dist/out-tsc/${
|
||||
options.projectRoot
|
||||
}`
|
||||
}
|
||||
};
|
||||
}),
|
||||
updateJsonInTree(`${options.projectRoot}/tslint.json`, json => {
|
||||
return {
|
||||
...json,
|
||||
@ -337,22 +346,43 @@ describe('${options.moduleName}', () => {
|
||||
};
|
||||
}),
|
||||
updateNgPackage(options),
|
||||
host => {
|
||||
const karma = host
|
||||
.read(`${options.projectRoot}/karma.conf.js`)
|
||||
.toString();
|
||||
host.overwrite(
|
||||
`${options.projectRoot}/karma.conf.js`,
|
||||
karma.replace(
|
||||
`'../../coverage${options.projectRoot}'`,
|
||||
`'${offsetFromRoot(options.projectRoot)}coverage'`
|
||||
)
|
||||
);
|
||||
}
|
||||
options.unitTestRunner === 'karma' ? updateKarmaConfig(options) : noop()
|
||||
])(host, null);
|
||||
};
|
||||
}
|
||||
|
||||
function updateKarmaConfig(options: NormalizedSchema) {
|
||||
return chain([
|
||||
host => {
|
||||
const karma = host
|
||||
.read(`${options.projectRoot}/karma.conf.js`)
|
||||
.toString();
|
||||
host.overwrite(
|
||||
`${options.projectRoot}/karma.conf.js`,
|
||||
karma.replace(
|
||||
`'../../coverage${options.projectRoot}'`,
|
||||
`'${offsetFromRoot(options.projectRoot)}coverage'`
|
||||
)
|
||||
);
|
||||
},
|
||||
updateJsonInTree(`${options.projectRoot}/tsconfig.spec.json`, json => {
|
||||
return {
|
||||
...json,
|
||||
extends: `${offsetFromRoot(options.projectRoot)}tsconfig.json`,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
outDir: `${offsetFromRoot(options.projectRoot)}dist/out-tsc/${
|
||||
options.projectRoot
|
||||
}`
|
||||
}
|
||||
};
|
||||
}),
|
||||
updateKarmaConf({
|
||||
projectName: options.name
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
function updateTsConfig(options: NormalizedSchema): Rule {
|
||||
return chain([
|
||||
(host: Tree, context: SchematicContext) => {
|
||||
@ -396,10 +426,12 @@ export default function(schema: Schema): Rule {
|
||||
|
||||
move(options.name, options.projectRoot),
|
||||
updateProject(options),
|
||||
updateKarmaConf({
|
||||
projectName: options.name
|
||||
}),
|
||||
updateTsConfig(options),
|
||||
options.unitTestRunner === 'jest'
|
||||
? schematic('jest-project', {
|
||||
project: options.name
|
||||
})
|
||||
: noop(),
|
||||
|
||||
options.publishable ? updateLibPackageNpmScope(options) : noop(),
|
||||
options.routing && options.lazy
|
||||
|
||||
@ -47,7 +47,7 @@ describe('lib', () => {
|
||||
appTree
|
||||
);
|
||||
const packageJson = readJsonInTree(tree, '/package.json');
|
||||
expect(packageJson.devDependencies).toBeUndefined();
|
||||
expect(packageJson.devDependencies['ng-packagr']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should update package.json when publishable', () => {
|
||||
@ -392,4 +392,42 @@ describe('lib', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('--unit-test-runner jest', () => {
|
||||
beforeEach(() => {
|
||||
appTree = schematicRunner.runSchematic('jest', {}, appTree);
|
||||
});
|
||||
|
||||
it('should generate jest configuration', () => {
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{ name: 'myLib', unitTestRunner: 'jest' },
|
||||
appTree
|
||||
);
|
||||
expect(resultTree.exists('libs/my-lib/src/test-setup.ts')).toBeTruthy();
|
||||
expect(resultTree.exists('libs/my-lib/jest.config.js')).toBeTruthy();
|
||||
const angularJson = readJsonInTree(resultTree, 'angular.json');
|
||||
expect(angularJson.projects['my-lib'].architect.test.builder).toEqual(
|
||||
'@nrwl/builders:jest'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--unit-test-runner none', () => {
|
||||
it('should not generate test configuration', () => {
|
||||
const resultTree = schematicRunner.runSchematic(
|
||||
'lib',
|
||||
{ name: 'myLib', unitTestRunner: 'none' },
|
||||
appTree
|
||||
);
|
||||
expect(
|
||||
resultTree.exists('libs/my-lib/src/lib/my-lib.module.spec.ts')
|
||||
).toBeFalsy();
|
||||
expect(resultTree.exists('libs/my-lib/tsconfig.spec.json')).toBeFalsy();
|
||||
expect(resultTree.exists('libs/my-lib/jest.config.js')).toBeFalsy();
|
||||
expect(resultTree.exists('libs/my-lib/karma.config.js')).toBeFalsy();
|
||||
const angularJson = readJsonInTree(resultTree, 'angular.json');
|
||||
expect(angularJson.projects['my-lib'].architect.test).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { UnitTestRunner } from '../../utils/test-runners';
|
||||
|
||||
export interface Schema {
|
||||
name: string;
|
||||
skipFormat: boolean;
|
||||
@ -14,4 +16,6 @@ export interface Schema {
|
||||
lazy?: boolean;
|
||||
parentModule?: string;
|
||||
tags?: string;
|
||||
|
||||
unitTestRunner: UnitTestRunner;
|
||||
}
|
||||
|
||||
@ -61,6 +61,12 @@
|
||||
"tags": {
|
||||
"type": "string",
|
||||
"description": "Add tags to the library (used for linting)"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["karma", "jest", "none"],
|
||||
"description": "Test runner to use for unit tests",
|
||||
"default": "karma"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { UnitTestRunner } from '../../utils/test-runners';
|
||||
|
||||
export interface Schema {
|
||||
directory: string;
|
||||
name: string;
|
||||
|
||||
@ -12,6 +12,7 @@ export const latestMigration = '20180507-create-nx-json';
|
||||
export const prettierVersion = '1.13.7';
|
||||
export const typescriptVersion = '~2.7.2';
|
||||
export const rxjsVersion = '^6.0.0';
|
||||
export const jestVersion = '^23.0.0';
|
||||
export const jasmineMarblesVersion = '0.3.1';
|
||||
|
||||
export const libVersions = {
|
||||
|
||||
1
packages/schematics/src/utils/test-runners.ts
Normal file
1
packages/schematics/src/utils/test-runners.ts
Normal file
@ -0,0 +1 @@
|
||||
export type UnitTestRunner = 'karma' | 'jest' | 'none';
|
||||
@ -26,7 +26,13 @@ export function createEmptyWorkspace(tree: Tree): Tree {
|
||||
'/angular.json',
|
||||
JSON.stringify({ projects: {}, newProjectRoot: '' })
|
||||
);
|
||||
tree.create('/package.json', JSON.stringify({}));
|
||||
tree.create(
|
||||
'/package.json',
|
||||
JSON.stringify({
|
||||
dependencies: {},
|
||||
devDependencies: {}
|
||||
})
|
||||
);
|
||||
tree.create('/nx.json', JSON.stringify({ npmScope: 'proj', projects: {} }));
|
||||
tree.create(
|
||||
'/tsconfig.json',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user