Skip to content

Commit

Permalink
feat(testing): Using getJestProjects() out of the box (nrwl#5900)
Browse files Browse the repository at this point in the history
* feat(testing): updating nx to use getJestProjects() itself

* feat(testing): using getJestProjects() for new workspaces

* feat(testing): accomodating for getJestConfig() when adding new project

* feat(testing): migration for updating the base jest.config.js

* testing...

* fix(testing): fixing formatting in tests and bumping to next version

* fix(testing): fixing broken tests

* fix(testing): fixing test for jest init

* fix(testing): removing unnecessary test in jest project

* fix(testing): updating remove generator to work with jest utility fn

* fix(testing): fixing line break on package.json

* fix(testing): fixing import statement

* fix(testing): using AST to update the jest config contents

* fix(testing): fixing snapshot tests

* fix(testing): fixing describe to 12.6

* fix(testing): adding back in import statement to jest.config.js

* fix(testing): updating generated docs
  • Loading branch information
ZackDeRose authored Jul 9, 2021
1 parent 0335797 commit 2524fdb
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 57 deletions.
33 changes: 3 additions & 30 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,5 @@
const { getJestProjects } = require('@nrwl/jest');

module.exports = {
projects: [
'<rootDir>/packages/tao',
'<rootDir>/packages/workspace',
'<rootDir>/packages/web',
'<rootDir>/packages/cypress',
'<rootDir>/packages/jest',
'<rootDir>/packages/storybook',
'<rootDir>/packages/react',
'<rootDir>/packages/nx-plugin',
'<rootDir>/packages/node',
'<rootDir>/packages/next',
'<rootDir>/packages/nest',
'<rootDir>/packages/linter',
'<rootDir>/packages/express',
'<rootDir>/packages/eslint-plugin-nx',
'<rootDir>/packages/create-nx-workspace',
'<rootDir>/packages/create-nx-plugin',
'<rootDir>/packages/cli',
'<rootDir>/packages/angular',
'<rootDir>/packages/gatsby',
'<rootDir>/dep-graph/dep-graph',
'<rootDir>/nx-dev/nx-dev',
'<rootDir>/nx-dev/ui/common',
'<rootDir>/nx-dev/feature-doc-viewer',
'<rootDir>/nx-dev/data-access-documents',
'<rootDir>/nx-dev/data-access-menu',
'<rootDir>/nx-dev/feature-search',
'<rootDir>/nx-dev/feature-analytics',
'<rootDir>/typedoc-theme',
],
projects: getJestProjects(),
};
6 changes: 6 additions & 0 deletions packages/jest/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@
"cli": "nx",
"description": "Support for Jest 27 via updating ts-jest + jest-preset-angular",
"factory": "./src/migrations/update-12-4-0/update-jest-preset-angular"
},
"update-jest-config-to-use-util": {
"version": "12.6.0-beta.0",
"cli": "nx",
"description": "Uses `getJestProjects()` to populate projects array in root level `jest.config.js` file.",
"factory": "./src/migrations/update-12-6-0/update-base-jest-config"
}
},
"packageJsonUpdates": {
Expand Down
6 changes: 4 additions & 2 deletions packages/jest/src/generators/init/init.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ describe('jest', () => {

expect(tree.exists('jest.config.js')).toBeTruthy();
expect(tree.read('jest.config.js', 'utf-8')).toMatchInlineSnapshot(`
"module.exports = {
projects: []
"const { getJestProjects } = require('@nrwl/jest');
module.exports = {
projects: getJestProjects()
};"
`);
});
Expand Down
4 changes: 3 additions & 1 deletion packages/jest/src/generators/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ function createJestConfig(host: Tree) {
host.write(
'jest.config.js',
stripIndents`
const { getJestProjects } = require('@nrwl/jest');
module.exports = {
projects: []
projects: getJestProjects()
};`
);
}
Expand Down
10 changes: 0 additions & 10 deletions packages/jest/src/generators/jest-project/jest-project.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,6 @@ describe('jestProject', () => {
expect(tree.read('libs/lib1/jest.config.js', 'utf-8')).toMatchSnapshot();
});

it('should add a project reference in the root jest.config.js', async () => {
await jestProjectGenerator(tree, {
...defaultOptions,
project: 'lib1',
} as JestProjectSchema);
const jestConfig = jestConfigObject(tree, 'jest.config.js');

expect(jestConfig.projects).toEqual(['<rootDir>/libs/lib1']);
});

it('should add a reference to solution tsconfig.json', async () => {
await jestProjectGenerator(tree, {
...defaultOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { JestProjectSchema } from '../schema';
import { addPropertyToJestConfig } from '../../../utils/config/update-config';
import { readProjectConfiguration, Tree } from '@nrwl/devkit';

function isUsingUtilityFunction(host: Tree) {
return host.read('jest.config.js').toString().includes('getJestProjects()');
}

export function updateJestConfig(host: Tree, options: JestProjectSchema) {
if (isUsingUtilityFunction(host)) {
return;
}
const project = readProjectConfiguration(host, options.project);
addPropertyToJestConfig(
host,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const mockGetJestProjects = jest.fn(() => []);
jest.mock('../../utils/config/get-jest-projects', () => ({
getJestProjects: mockGetJestProjects,
}));
const mockResolveConfig = jest.fn(() =>
Promise.resolve({ singleQuote: true, endOfLine: 'lf' })
);

import { Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from 'packages/devkit/src/tests/create-tree-with-empty-workspace';
import update from './update-base-jest-config';

describe('update 12.6.0', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
tree.write(
'jest.config.js',
`module.exports = {
projects: ['<rootDir>/test-1']
}`
);
});

beforeEach(async () => {
const prettier = await import('prettier');
prettier.resolveConfig = mockResolveConfig as any;
});

test('all jest projects covered', async () => {
mockGetJestProjects.mockImplementation(() => ['<rootDir>/test-1']);
await update(tree);
const result = tree.read('jest.config.js').toString();
expect(result).toMatchInlineSnapshot(`
"const { getJestProjects } = require('@nrwl/jest');
module.exports = { projects: getJestProjects() };
"
`);
});

test('some jest projects uncovered', async () => {
mockGetJestProjects.mockImplementation(() => ['<rootDir>/test-2']);
await update(tree);
const result = tree.read('jest.config.js').toString();
expect(result).toMatchInlineSnapshot(`
"const { getJestProjects } = require('@nrwl/jest');
module.exports = { projects: [...getJestProjects(), '<rootDir>/test-1'] };
"
`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { formatFiles, Tree } from '@nrwl/devkit';
import { jestConfigObject } from '../../utils/config/functions';
import { getJestProjects } from '../../utils/config/get-jest-projects';
import {
addImportStatementToJestConfig,
addPropertyToJestConfig,
removePropertyFromJestConfig,
} from '../../utils/config/update-config';

function determineUncoveredJestProjects(existingProjects: string[]) {
const coveredJestProjects = (getJestProjects() as string[]).reduce(
(acc, key) => {
acc[key] = true;
return acc;
},
{}
);
return existingProjects.filter((project) => !coveredJestProjects[project]);
}

function determineProjectsValue(uncoveredJestProjects: string[]): string {
if (!uncoveredJestProjects.length) {
return `getJestProjects()`;
}
return `[...getJestProjects(), ${uncoveredJestProjects.map(
(projectName) => `'${projectName}', `
)}]`;
}

function updateBaseJestConfig(
tree: Tree,
baseJestConfigPath = 'jest.config.js'
) {
const currentConfig = jestConfigObject(tree, baseJestConfigPath);
const uncoveredJestProjects = determineUncoveredJestProjects(
currentConfig.projects as string[]
);
removePropertyFromJestConfig(tree, baseJestConfigPath, 'projects');
addPropertyToJestConfig(
tree,
baseJestConfigPath,
'projects',
determineProjectsValue(uncoveredJestProjects),
{ valueAsString: true }
);
addImportStatementToJestConfig(
tree,
baseJestConfigPath,
`const { getJestProjects } = require('@nrwl/jest');`
);
return;
}

export default async function update(tree: Tree) {
updateBaseJestConfig(tree);
await formatFiles(tree);
}
18 changes: 16 additions & 2 deletions packages/jest/src/utils/config/update-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import {
* @param path - path to the jest config file
* @param propertyName - Property to update. Can be dot delimited to access deeply nested properties
* @param value
* @param options - set `valueAsString` option to true if the `value` being passed represents a string of the code that should be associated with the `propertyName`
*/
export function addPropertyToJestConfig(
host: Tree,
path: string,
propertyName: string,
value: unknown
value: unknown,
options: { valueAsString: boolean } = { valueAsString: false }
) {
if (!host.exists(path)) {
throw new Error(`Cannot find '${path}' in your workspace.`);
Expand All @@ -28,7 +30,7 @@ export function addPropertyToJestConfig(
host,
configObject,
properties,
JSON.stringify(value),
options.valueAsString ? value : JSON.stringify(value),
path
);
} catch (e) {
Expand Down Expand Up @@ -83,3 +85,15 @@ export function removePropertyFromJestConfig(
console.log(`Please manually update ${path}`);
}
}

export function addImportStatementToJestConfig(
host: Tree,
path: string,
importStatement: string
) {
const currentContents = host.read(path, 'utf-8');
const newContents = `${importStatement}
${currentContents}`;
host.write(path, newContents);
}
21 changes: 12 additions & 9 deletions packages/workspace/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,25 @@ describe('lib', () => {
...defaultOptions,
name: 'myLib',
});
const expectedRootJestConfig = `
"const { getJestProjects } = require('@nrwl/jest');
expect(tree.read('jest.config.js', 'utf-8')).toMatchInlineSnapshot(`
"module.exports = {
projects: [\\"<rootDir>/libs/my-lib\\"]
module.exports = {
projects: getJestProjects()
};"
`);
`;

expect(tree.read('jest.config.js', 'utf-8')).toMatchInlineSnapshot(
expectedRootJestConfig
);
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib2',
});

expect(tree.read('jest.config.js', 'utf-8')).toMatchInlineSnapshot(`
"module.exports = {
projects: [\\"<rootDir>/libs/my-lib\\",\\"<rootDir>/libs/my-lib2\\"]
};"
`);
expect(tree.read('jest.config.js', 'utf-8')).toMatchInlineSnapshot(
expectedRootJestConfig
);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ describe('updateJestConfig', () => {
`coverageDirectory: '../../coverage/libs/my-destination'`
);

expect(rootJestConfigAfter).not.toContain('<rootDir>/libs/my-source');
expect(rootJestConfigAfter).toContain('<rootDir>/libs/my-destination');
expect(rootJestConfigAfter).toContain('getJestProjects()');
});

it('should update jest configs properly even if project is in many layers of subfolders', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import {
} from 'typescript';
import { join } from 'path';

function isUsingUtilityFunction(host: Tree) {
return host.read('jest.config.js').toString().includes('getJestProjects()');
}

/**
* Updates the root jest config projects array and removes the project.
*/
Expand All @@ -31,7 +35,8 @@ export function updateJestConfig(

if (
!tree.exists('jest.config.js') ||
!tree.exists(join(projectConfig.root, 'jest.config.js'))
!tree.exists(join(projectConfig.root, 'jest.config.js')) ||
isUsingUtilityFunction(tree)
) {
return;
}
Expand Down

0 comments on commit 2524fdb

Please sign in to comment.