Skip to content

Commit

Permalink
feat(testing): add projects into jest config (nrwl#3766)
Browse files Browse the repository at this point in the history
* feat(testing): add projects into jest config

* chore(testing): update unit tests and fix presets with spreading a default

* chore(testing): fix node e2e

* chore(testing): review comment changes
  • Loading branch information
Cammisuli authored and Doginal committed Nov 25, 2020
1 parent 93d66f5 commit d98c3a6
Show file tree
Hide file tree
Showing 21 changed files with 378 additions and 52 deletions.
4 changes: 2 additions & 2 deletions e2e/node/src/node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ forEachCli((currentCLIName) => {

expect(stripIndents`${jestConfigContent}`).toEqual(
stripIndents`module.exports = {
name: '${nestlib}',
preset: '../../jest.config.js',
displayName: '${nestlib}',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Array [
"/tsconfig.base.json",
"/tslint.json",
"/jest.config.js",
"/jest.preset.js",
"/libs/test-ui-lib/README.md",
"/libs/test-ui-lib/tsconfig.lib.json",
"/libs/test-ui-lib/tslint.json",
Expand Down
5 changes: 5 additions & 0 deletions packages/jest/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
"version": "10.2.0",
"description": "Remove deprecated jest builder options",
"factory": "./src/migrations/update-10-2-0/update-10-2-0"
},
"update-projects-property": {
"version": "10.3.0-beta.1",
"description": "Adds all jest projects into the root jest config",
"factory": "./src/migrations/update-10-3-0/update-projects-property"
}
},
"packageJsonUpdates": {
Expand Down
1 change: 1 addition & 0 deletions packages/jest/preset/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export = require('./jest-preset');
9 changes: 9 additions & 0 deletions packages/jest/preset/jest-preset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export = {
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
resolver: '@nrwl/jest/plugins/resolver',
moduleFileExtensions: ['ts', 'js', 'html'],
coverageReporters: ['html'],
transform: {
'^.+\\.(ts|js|html)$': 'ts-jest',
},
};
15 changes: 10 additions & 5 deletions packages/jest/src/builders/jest/jest.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import * as path from 'path';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { JestBuilderOptions } from './schema';
import { Config } from '@jest/types';

try {
require('dotenv').config();
} catch (e) {
// noop
}

if (process.env.NODE_ENV == null || process.env.NODE_ENV == undefined) {
if (process.env.NODE_ENV === null || process.env.NODE_ENV === undefined) {
(process.env as any).NODE_ENV = 'test';
}

Expand All @@ -40,7 +41,8 @@ function run(
);
}

const config: any = {
const config: Config.Argv = {
$0: undefined,
_: [],
config: options.config,
coverage: options.codeCoverage,
Expand Down Expand Up @@ -98,14 +100,17 @@ function run(
config.reporters = options.reporters;
}

if (options.coverageReporters && options.coverageReporters.length > 0) {
if (
Array.isArray(options.coverageReporters) &&
options.coverageReporters.length > 0
) {
config.coverageReporters = options.coverageReporters;
}

return from(runCLI(config, [options.jestConfig])).pipe(
map((results) => {
map(({ results }) => {
return {
success: results.results.success,
success: results.success,
};
})
);
Expand Down
2 changes: 1 addition & 1 deletion packages/jest/src/builders/jest/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface JestBuilderOptions extends JsonObject {
colors?: boolean;
reporters?: string[];
verbose?: boolean;
coverageReporters?: string;
coverageReporters?: string[];
coverageDirectory?: string;
testResultsProcessor?: string;
updateSnapshot?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { tags } from '@angular-devkit/core';
import { Tree } from '@angular-devkit/schematics';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { serializeJson } from '@nrwl/workspace';
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
import * as path from 'path';

describe('update projects property', () => {
let initialTree: Tree;
let schematicRunner: SchematicTestRunner;

beforeEach(() => {
initialTree = createEmptyWorkspace(Tree.empty());

initialTree.create(
'jest.config.js',
tags.stripIndents`
module.exports = {
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
transform: {
'^.+\\\\.(ts|js|html)$': 'ts-jest',
},
maxWorkers: 2,
};
`
);

initialTree.create(
'apps/products/jest.config.js',
tags.stripIndents`
module.exports = {
name: 'products',
preset: '../../jest.config.js',
coverageDirectory: '../../coverage/apps/products',
snapshotSerializers: [
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js'
],
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
astTransformers: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer'
]
}
}
};
`
);

initialTree.overwrite(
'workspace.json',
serializeJson({
version: 1,
projects: {
products: {
root: 'apps/products',
sourceRoot: 'apps/products/src',
architect: {
build: {
builder: '@angular-devkit/build-angular:browser',
},
test: {
builder: '@nrwl/jest:jest',
options: {
jestConfig: 'apps/products/jest.config.js',
tsConfig: 'apps/products/tsconfig.spec.json',
setupFile: 'apps/products/src/test-setup.ts',
passWithNoTests: true,
},
},
},
},
cart: {
root: 'apps/cart',
sourceRoot: 'apps/cart/src',
architect: {
build: {
builder: '@nrwl/web:build',
},
test: {
builder: '@nrwl/jest:jest',
options: {
jestConfig: 'apps/cart/jest.config.js',
passWithNoTests: true,
},
},
},
},
basket: {
root: 'apps/basket',
sourceRoot: 'apps/basket/src',
architect: {
build: {
builder: '@nrwl/web:build',
},
},
},
},
})
);
schematicRunner = new SchematicTestRunner(
'@nrwl/jest',
path.join(__dirname, '../../../migrations.json')
);
});

it('should remove setupFile and tsconfig in test architect from workspace.json', async (done) => {
const result = await schematicRunner
.runSchematicAsync('update-projects-property', {}, initialTree)
.toPromise();

const updatedJestConfig = result.readContent('jest.config.js');
expect(tags.stripIndents`${updatedJestConfig}`).toEqual(tags.stripIndents`
module.exports = {
projects: ['<rootDir>/apps/products', '<rootDir>/apps/cart'],
};
`);

const jestPreset = result.readContent('jest.preset.js');
expect(tags.stripIndents`${jestPreset}`).toEqual(tags.stripIndents`
const nxPreset = require('@nrwl/jest/preset');
module.exports = {
...nxPreset,
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
transform: {
'^.+\\\\.(ts|js|html)$': 'ts-jest',
},
maxWorkers: 2,
};
`);

const projectConfig = result.readContent('apps/products/jest.config.js');
expect(tags.stripIndents`${projectConfig}`).toEqual(tags.stripIndents`
module.exports = {
preset: '../../jest.preset.js',
coverageDirectory: '../../coverage/apps/products',
snapshotSerializers: [
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
],
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
astTransformers: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer',
],
},
},
displayName: 'products',
};
`);

done();
});
});
107 changes: 107 additions & 0 deletions packages/jest/src/migrations/update-10-3-0/update-projects-property.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {
chain,
Rule,
SchematicContext,
Tree,
} from '@angular-devkit/schematics';
import {
formatFiles,
getWorkspace,
insert,
InsertChange,
offsetFromRoot,
serializeJson,
} from '@nrwl/workspace';
import {
addPropertyToJestConfig,
removePropertyFromJestConfig,
} from '../../utils/config/update-config';
import { jestConfigObjectAst } from '../../utils/config/functions';

function updateRootJestConfig(): Rule {
return async (host: Tree, context: SchematicContext) => {
const workspace = await getWorkspace(host);

const rootDirs = [];
for (const [projectName, project] of workspace.projects) {
for (const [, target] of project.targets) {
if (target.builder !== '@nrwl/jest:jest') {
continue;
}

rootDirs.push(`<rootDir>/${project.root}`);

try {
addPropertyToJestConfig(
host,
target.options.jestConfig as string,
'preset',
`${offsetFromRoot(project.root)}jest.preset.js`
);
addPropertyToJestConfig(
host,
target.options.jestConfig as string,
'displayName',
projectName
);
removePropertyFromJestConfig(
host,
target.options.jestConfig as string,
'name'
);
} catch {
context.logger.error(
`Unable to update the jest preset for project ${projectName}. Please manually add "@nrwl/jest/preset" as the preset.`
);
}
}
}

if (rootDirs.length == 0) {
return;
} else {
try {
context.logger.info(`
The root jest.config.js file will be updated to include all references to each individual project's jest config.
A new jest.preset.js file will be created that would have your existing configuration. All projects will now have this preset.
`);

let existingRootConfig = host.read('jest.config.js').toString('utf-8');

existingRootConfig =
"const nxPreset = require('@nrwl/jest/preset'); \n" +
existingRootConfig;

const presetPath = 'jest.preset.js';

host.create(presetPath, existingRootConfig);
const configObject = jestConfigObjectAst(host, presetPath);
insert(host, presetPath, [
new InsertChange(
presetPath,
configObject.getStart() + 1,
'\n...nxPreset,'
),
]);

host.overwrite(
'jest.config.js',
`
module.exports = {
projects: ${serializeJson(rootDirs)}
}
`
);
} catch {
context.logger.error(`
Unable to update the root jest.config.js with projects. Please add the "projects" property to the exported jest config with the following:
${serializeJson(rootDirs)}
`);
}
}
};
}

export default function update(): Rule {
return chain([updateRootJestConfig(), formatFiles()]);
}
8 changes: 1 addition & 7 deletions packages/jest/src/schematics/init/init.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ describe('jest', () => {
expect(resultTree.exists('jest.config.js')).toBeTruthy();
expect(resultTree.readContent('jest.config.js')).toMatchInlineSnapshot(`
"module.exports = {
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
transform: {
'^.+\\\\\\\\.(ts|js|html)$': 'ts-jest'
},
resolver: '@nrwl/jest/plugins/resolver',
moduleFileExtensions: ['ts', 'js', 'html'],
coverageReporters: ['html']
projects: []
};"
`);
});
Expand Down
Loading

0 comments on commit d98c3a6

Please sign in to comment.