fix(node): pass projectNameAndRootFormat to js lib generator from nest lib generator (#18891)

This commit is contained in:
Jack Hsu 2023-08-29 14:35:24 -04:00 committed by GitHub
parent 759c5e1a4e
commit 74e5879e8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 352 additions and 327 deletions

View File

@ -7,24 +7,25 @@ describe('app', () => {
let appTree: Tree; let appTree: Tree;
beforeEach(() => { beforeEach(() => {
appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); appTree = createTreeWithEmptyWorkspace();
}); });
it('should generate files', async () => { it('should generate files', async () => {
await applicationGenerator(appTree, { await applicationGenerator(appTree, {
name: 'myNodeApp', name: 'myNodeApp',
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
const mainFile = appTree.read('apps/my-node-app/src/main.ts').toString(); const mainFile = appTree.read('my-node-app/src/main.ts').toString();
expect(mainFile).toContain(`import express from 'express';`); expect(mainFile).toContain(`import express from 'express';`);
const tsconfig = readJson(appTree, 'apps/my-node-app/tsconfig.json'); const tsconfig = readJson(appTree, 'my-node-app/tsconfig.json');
expect(tsconfig).toMatchInlineSnapshot(` expect(tsconfig).toMatchInlineSnapshot(`
{ {
"compilerOptions": { "compilerOptions": {
"esModuleInterop": true, "esModuleInterop": true,
}, },
"extends": "../../tsconfig.base.json", "extends": "../tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"references": [ "references": [
@ -38,11 +39,11 @@ describe('app', () => {
} }
`); `);
const eslintrcJson = readJson(appTree, 'apps/my-node-app/.eslintrc.json'); const eslintrcJson = readJson(appTree, 'my-node-app/.eslintrc.json');
expect(eslintrcJson).toMatchInlineSnapshot(` expect(eslintrcJson).toMatchInlineSnapshot(`
{ {
"extends": [ "extends": [
"../../.eslintrc.json", "../.eslintrc.json",
], ],
"ignorePatterns": [ "ignorePatterns": [
"!**/*", "!**/*",
@ -79,14 +80,15 @@ describe('app', () => {
it('should add types to the tsconfig.app.json', async () => { it('should add types to the tsconfig.app.json', async () => {
await applicationGenerator(appTree, { await applicationGenerator(appTree, {
name: 'myNodeApp', name: 'myNodeApp',
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
const tsconfig = readJson(appTree, 'apps/my-node-app/tsconfig.app.json'); const tsconfig = readJson(appTree, 'my-node-app/tsconfig.app.json');
expect(tsconfig.compilerOptions.types).toContain('express'); expect(tsconfig.compilerOptions.types).toContain('express');
expect(tsconfig).toMatchInlineSnapshot(` expect(tsconfig).toMatchInlineSnapshot(`
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs", "module": "commonjs",
"outDir": "../../dist/out-tsc", "outDir": "../dist/out-tsc",
"types": [ "types": [
"node", "node",
"express", "express",
@ -110,23 +112,21 @@ describe('app', () => {
await applicationGenerator(appTree, { await applicationGenerator(appTree, {
name: 'myNodeApp', name: 'myNodeApp',
js: true, js: true,
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
expect(appTree.exists('apps/my-node-app/src/main.js')).toBeTruthy(); expect(appTree.exists('my-node-app/src/main.js')).toBeTruthy();
expect(appTree.read('apps/my-node-app/src/main.js').toString()).toContain( expect(appTree.read('my-node-app/src/main.js').toString()).toContain(
`import express from 'express';` `import express from 'express';`
); );
const tsConfig = readJson(appTree, 'apps/my-node-app/tsconfig.json'); const tsConfig = readJson(appTree, 'my-node-app/tsconfig.json');
expect(tsConfig.compilerOptions).toEqual({ expect(tsConfig.compilerOptions).toEqual({
allowJs: true, allowJs: true,
esModuleInterop: true, esModuleInterop: true,
}); });
const tsConfigApp = readJson( const tsConfigApp = readJson(appTree, 'my-node-app/tsconfig.app.json');
appTree,
'apps/my-node-app/tsconfig.app.json'
);
expect(tsConfigApp.include).toEqual(['src/**/*.ts', 'src/**/*.js']); expect(tsConfigApp.include).toEqual(['src/**/*.ts', 'src/**/*.js']);
expect(tsConfigApp.exclude).toEqual([ expect(tsConfigApp.exclude).toEqual([
'jest.config.ts', 'jest.config.ts',

View File

@ -1,9 +1,4 @@
import { import { addDependenciesToPackageJson, readJson, Tree } from '@nx/devkit';
addDependenciesToPackageJson,
readJson,
NxJsonConfiguration,
Tree,
} from '@nx/devkit';
import { expressVersion } from '../../utils/versions'; import { expressVersion } from '../../utils/versions';
import initGenerator from './init'; import initGenerator from './init';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
@ -12,7 +7,7 @@ describe('init', () => {
let tree: Tree; let tree: Tree;
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
}); });
it('should add dependencies', async () => { it('should add dependencies', async () => {

View File

@ -9,12 +9,15 @@ describe('application generator', () => {
const appDirectory = 'my-node-app'; const appDirectory = 'my-node-app';
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
jest.clearAllMocks(); jest.clearAllMocks();
}); });
it('should generate project configurations', async () => { it('should generate project configurations', async () => {
await applicationGenerator(tree, { name: appName }); await applicationGenerator(tree, {
name: appName,
projectNameAndRootFormat: 'as-provided',
});
const projectConfigurations = devkit.getProjects(tree); const projectConfigurations = devkit.getProjects(tree);
@ -23,33 +26,32 @@ describe('application generator', () => {
}); });
it('should generate files', async () => { it('should generate files', async () => {
await applicationGenerator(tree, { name: appName }); await applicationGenerator(tree, {
name: appName,
projectNameAndRootFormat: 'as-provided',
});
expect(tree.exists(`apps/${appDirectory}/src/main.ts`)).toBeTruthy(); expect(tree.exists(`${appDirectory}/src/main.ts`)).toBeTruthy();
expect( expect(
tree.exists(`apps/${appDirectory}/src/app/app.controller.spec.ts`) tree.exists(`${appDirectory}/src/app/app.controller.spec.ts`)
).toBeTruthy(); ).toBeTruthy();
expect( expect(
tree.exists(`apps/${appDirectory}/src/app/app.controller.ts`) tree.exists(`${appDirectory}/src/app/app.controller.ts`)
).toBeTruthy(); ).toBeTruthy();
expect(tree.exists(`${appDirectory}/src/app/app.module.ts`)).toBeTruthy();
expect( expect(
tree.exists(`apps/${appDirectory}/src/app/app.module.ts`) tree.exists(`${appDirectory}/src/app/app.service.spec.ts`)
).toBeTruthy();
expect(
tree.exists(`apps/${appDirectory}/src/app/app.service.spec.ts`)
).toBeTruthy();
expect(
tree.exists(`apps/${appDirectory}/src/app/app.service.ts`)
).toBeTruthy(); ).toBeTruthy();
expect(tree.exists(`${appDirectory}/src/app/app.service.ts`)).toBeTruthy();
}); });
it('should configure tsconfig correctly', async () => { it('should configure tsconfig correctly', async () => {
await applicationGenerator(tree, { name: appName }); await applicationGenerator(tree, {
name: appName,
projectNameAndRootFormat: 'as-provided',
});
const tsConfig = devkit.readJson( const tsConfig = devkit.readJson(tree, `${appDirectory}/tsconfig.app.json`);
tree,
`apps/${appDirectory}/tsconfig.app.json`
);
expect(tsConfig.compilerOptions.emitDecoratorMetadata).toBe(true); expect(tsConfig.compilerOptions.emitDecoratorMetadata).toBe(true);
expect(tsConfig.compilerOptions.target).toBe('es2021'); expect(tsConfig.compilerOptions.target).toBe('es2021');
expect(tsConfig.exclude).toEqual([ expect(tsConfig.exclude).toEqual([
@ -60,11 +62,12 @@ describe('application generator', () => {
}); });
it('should add strict checks with --strict', async () => { it('should add strict checks with --strict', async () => {
await applicationGenerator(tree, { name: appName, strict: true }); await applicationGenerator(tree, {
const tsConfig = devkit.readJson( name: appName,
tree, strict: true,
`apps/${appDirectory}/tsconfig.app.json` projectNameAndRootFormat: 'as-provided',
); });
const tsConfig = devkit.readJson(tree, `${appDirectory}/tsconfig.app.json`);
expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy(); expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy();
expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy(); expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy();
@ -79,7 +82,10 @@ describe('application generator', () => {
it('should format files', async () => { it('should format files', async () => {
jest.spyOn(devkit, 'formatFiles'); jest.spyOn(devkit, 'formatFiles');
await applicationGenerator(tree, { name: appName }); await applicationGenerator(tree, {
name: appName,
projectNameAndRootFormat: 'as-provided',
});
expect(devkit.formatFiles).toHaveBeenCalled(); expect(devkit.formatFiles).toHaveBeenCalled();
}); });
@ -87,7 +93,11 @@ describe('application generator', () => {
it('should not format files when --skipFormat=true', async () => { it('should not format files when --skipFormat=true', async () => {
jest.spyOn(devkit, 'formatFiles'); jest.spyOn(devkit, 'formatFiles');
await applicationGenerator(tree, { name: appName, skipFormat: true }); await applicationGenerator(tree, {
name: appName,
skipFormat: true,
projectNameAndRootFormat: 'as-provided',
});
expect(devkit.formatFiles).not.toHaveBeenCalled(); expect(devkit.formatFiles).not.toHaveBeenCalled();
}); });
@ -98,6 +108,7 @@ describe('application generator', () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: appName, name: appName,
e2eTestRunner: 'none', e2eTestRunner: 'none',
projectNameAndRootFormat: 'as-provided',
}); });
const projectConfigurations = devkit.getProjects(tree); const projectConfigurations = devkit.getProjects(tree);

View File

@ -18,16 +18,16 @@ exports[`convert-tslint-to-eslint should work for NestJS applications 1`] = `
exports[`convert-tslint-to-eslint should work for NestJS applications 2`] = ` exports[`convert-tslint-to-eslint should work for NestJS applications 2`] = `
{ {
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../node_modules/nx/schemas/project-schema.json",
"name": "nest-app-1", "name": "nest-app-1",
"projectType": "application", "projectType": "application",
"root": "apps/nest-app-1", "root": "nest-app-1",
"targets": { "targets": {
"lint": { "lint": {
"executor": "@nx/linter:eslint", "executor": "@nx/linter:eslint",
"options": { "options": {
"lintFilePatterns": [ "lintFilePatterns": [
"apps/nest-app-1/**/*.ts", "nest-app-1/**/*.ts",
], ],
}, },
"outputs": [ "outputs": [
@ -246,7 +246,7 @@ exports[`convert-tslint-to-eslint should work for NestJS applications 3`] = `
exports[`convert-tslint-to-eslint should work for NestJS applications 4`] = ` exports[`convert-tslint-to-eslint should work for NestJS applications 4`] = `
{ {
"extends": [ "extends": [
"../../.eslintrc.json", "../.eslintrc.json",
], ],
"ignorePatterns": [ "ignorePatterns": [
"!**/*", "!**/*",

View File

@ -12,7 +12,7 @@ import { exampleRootTslintJson } from '@nx/linter';
import { conversionGenerator } from './convert-tslint-to-eslint'; import { conversionGenerator } from './convert-tslint-to-eslint';
const appProjectName = 'nest-app-1'; const appProjectName = 'nest-app-1';
const appProjectRoot = `apps/${appProjectName}`; const appProjectRoot = `${appProjectName}`;
const appProjectTSLintJsonPath = joinPathFragments( const appProjectTSLintJsonPath = joinPathFragments(
appProjectRoot, appProjectRoot,
'tslint.json' 'tslint.json'
@ -98,7 +98,7 @@ describe('convert-tslint-to-eslint', () => {
beforeEach(async () => { beforeEach(async () => {
jest.spyOn(devkit, 'installPackagesTask'); jest.spyOn(devkit, 'installPackagesTask');
host = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); host = createTreeWithEmptyWorkspace();
writeJson(host, 'tslint.json', exampleRootTslintJson.raw); writeJson(host, 'tslint.json', exampleRootTslintJson.raw);
@ -114,8 +114,8 @@ describe('convert-tslint-to-eslint', () => {
lint: { lint: {
executor: '@angular-devkit/build-angular:tslint', executor: '@angular-devkit/build-angular:tslint',
options: { options: {
exclude: ['**/node_modules/**', '!apps/nest-app-1/**/*'], exclude: ['**/node_modules/**', '!nest-app-1/**/*'],
tsConfig: ['apps/nest-app-1/tsconfig.app.json'], tsConfig: ['nest-app-1/tsconfig.app.json'],
}, },
}, },
}, },
@ -143,7 +143,7 @@ describe('convert-tslint-to-eslint', () => {
/** /**
* Existing tslint.json file for the app project * Existing tslint.json file for the app project
*/ */
writeJson(host, 'apps/nest-app-1/tslint.json', projectTslintJsonData.raw); writeJson(host, 'nest-app-1/tslint.json', projectTslintJsonData.raw);
/** /**
* Existing tslint.json file for the lib project * Existing tslint.json file for the lib project
*/ */

View File

@ -12,7 +12,7 @@ describe('init generator', () => {
let tree: Tree; let tree: Tree;
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
jest.clearAllMocks(); jest.clearAllMocks();
}); });

View File

@ -4,12 +4,12 @@ exports[`lib --testEnvironment should set target jest testEnvironment to jsdom 1
"/* eslint-disable */ "/* eslint-disable */
export default { export default {
displayName: 'my-lib', displayName: 'my-lib',
preset: '../../jest.preset.js', preset: '../jest.preset.js',
transform: { transform: {
'^.+\\\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }], '^.+\\\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
}, },
moduleFileExtensions: ['ts', 'js', 'html'], moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/my-lib', coverageDirectory: '../coverage/my-lib',
}; };
" "
`; `;
@ -18,13 +18,13 @@ exports[`lib --testEnvironment should set target jest testEnvironment to node by
"/* eslint-disable */ "/* eslint-disable */
export default { export default {
displayName: 'my-lib', displayName: 'my-lib',
preset: '../../jest.preset.js', preset: '../jest.preset.js',
testEnvironment: 'node', testEnvironment: 'node',
transform: { transform: {
'^.+\\\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }], '^.+\\\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
}, },
moduleFileExtensions: ['ts', 'js', 'html'], moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/my-lib', coverageDirectory: '../coverage/my-lib',
}; };
" "
`; `;
@ -40,7 +40,7 @@ exports[`lib --unit-test-runner none should not generate test configuration 1`]
"noPropertyAccessFromIndexSignature": true, "noPropertyAccessFromIndexSignature": true,
"strict": true, "strict": true,
}, },
"extends": "../../tsconfig.base.json", "extends": "../tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"references": [ "references": [
@ -56,7 +56,7 @@ exports[`lib --unit-test-runner none should not generate test configuration 2`]
"executor": "@nx/linter:eslint", "executor": "@nx/linter:eslint",
"options": { "options": {
"lintFilePatterns": [ "lintFilePatterns": [
"libs/my-lib/**/*.ts", "my-lib/**/*.ts",
], ],
}, },
"outputs": [ "outputs": [
@ -76,7 +76,7 @@ exports[`lib nested should create a local tsconfig.json 1`] = `
"noPropertyAccessFromIndexSignature": true, "noPropertyAccessFromIndexSignature": true,
"strict": true, "strict": true,
}, },
"extends": "../../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"references": [ "references": [
@ -114,7 +114,7 @@ exports[`lib not nested should create a local tsconfig.json 1`] = `
"noPropertyAccessFromIndexSignature": true, "noPropertyAccessFromIndexSignature": true,
"strict": true, "strict": true,
}, },
"extends": "../../tsconfig.base.json", "extends": "../tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"references": [ "references": [
@ -131,7 +131,7 @@ exports[`lib not nested should create a local tsconfig.json 1`] = `
exports[`lib not nested should generate files 1`] = ` exports[`lib not nested should generate files 1`] = `
{ {
"extends": [ "extends": [
"../../.eslintrc.json", "../.eslintrc.json",
], ],
"ignorePatterns": [ "ignorePatterns": [
"!**/*", "!**/*",

View File

@ -69,5 +69,6 @@ export function toJsLibraryGeneratorOptions(
unitTestRunner: options.unitTestRunner, unitTestRunner: options.unitTestRunner,
config: options.standaloneConfig ? 'project' : 'workspace', config: options.standaloneConfig ? 'project' : 'workspace',
setParserOptionsProject: options.setParserOptionsProject, setParserOptionsProject: options.setParserOptionsProject,
projectNameAndRootFormat: options.projectNameAndRootFormat,
}; };
} }

View File

@ -6,33 +6,34 @@ import { libraryGenerator } from './library';
describe('lib', () => { describe('lib', () => {
let tree: Tree; let tree: Tree;
const libFileName = 'my-lib';
const libName = 'myLib';
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
jest.clearAllMocks(); jest.clearAllMocks();
}); });
describe('not nested', () => { describe('not nested', () => {
it('should update project configuration', async () => { it('should update project configuration', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const config = readProjectConfiguration(tree, libFileName); const config = readProjectConfiguration(tree, 'my-lib');
expect(config.root).toEqual(`libs/${libFileName}`); expect(config.root).toEqual(`my-lib`);
expect(config.targets.build).toBeUndefined(); expect(config.targets.build).toBeUndefined();
expect(config.targets.lint).toEqual({ expect(config.targets.lint).toEqual({
executor: '@nx/linter:eslint', executor: '@nx/linter:eslint',
outputs: ['{options.outputFile}'], outputs: ['{options.outputFile}'],
options: { options: {
lintFilePatterns: [`libs/${libFileName}/**/*.ts`], lintFilePatterns: [`my-lib/**/*.ts`],
}, },
}); });
expect(config.targets.test).toEqual({ expect(config.targets.test).toEqual({
executor: '@nx/jest:jest', executor: '@nx/jest:jest',
outputs: [`{workspaceRoot}/coverage/{projectRoot}`], outputs: [`{workspaceRoot}/coverage/{projectRoot}`],
options: { options: {
jestConfig: `libs/${libFileName}/jest.config.ts`, jestConfig: `my-lib/jest.config.ts`,
passWithNoTests: true, passWithNoTests: true,
}, },
configurations: { configurations: {
@ -45,111 +46,119 @@ describe('lib', () => {
}); });
it('should include a controller', async () => { it('should include a controller', async () => {
await libraryGenerator(tree, { name: libName, controller: true }); await libraryGenerator(tree, {
name: 'myLib',
controller: true,
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.exists(`my-lib/src/lib/my-lib.controller.ts`)).toBeTruthy();
tree.exists(`libs/${libFileName}/src/lib/${libFileName}.controller.ts`)
).toBeTruthy();
}); });
it('should include a service', async () => { it('should include a service', async () => {
await libraryGenerator(tree, { name: libName, service: true }); await libraryGenerator(tree, {
name: 'myLib',
service: true,
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.exists(`my-lib/src/lib/my-lib.service.ts`)).toBeTruthy();
tree.exists(`libs/${libFileName}/src/lib/${libFileName}.service.ts`)
).toBeTruthy();
}); });
it('should add the @Global decorator', async () => { it('should add the @Global decorator', async () => {
await libraryGenerator(tree, { name: libName, global: true }); await libraryGenerator(tree, {
name: 'myLib',
global: true,
projectNameAndRootFormat: 'as-provided',
});
expect( expect(
tree.read( tree.read(`my-lib/src/lib/my-lib.module.ts`, 'utf-8')
`libs/${libFileName}/src/lib/${libFileName}.module.ts`,
'utf-8'
)
).toMatchSnapshot(); ).toMatchSnapshot();
}); });
it('should remove the default file from @nx/node:lib', async () => { it('should remove the default file from @nx/node:lib', async () => {
await libraryGenerator(tree, { name: libName, global: true }); await libraryGenerator(tree, {
name: 'myLib',
global: true,
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.exists(`my-lib/src/lib/my-lib.spec.ts`)).toBeFalsy();
tree.exists(`libs/${libFileName}/src/lib/${libFileName}.spec.ts`) expect(tree.exists(`my-lib/src/lib/my-lib.ts`)).toBeFalsy();
).toBeFalsy();
expect(
tree.exists(`libs/${libFileName}/src/lib/${libFileName}.ts`)
).toBeFalsy();
}); });
it('should provide the controller and service', async () => { it('should provide the controller and service', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: libName, name: 'myLib',
controller: true, controller: true,
service: true, service: true,
projectNameAndRootFormat: 'as-provided',
}); });
expect( expect(
tree.read( tree.read(`my-lib/src/lib/my-lib.module.ts`, 'utf-8')
`libs/${libFileName}/src/lib/${libFileName}.module.ts`,
'utf-8'
)
).toMatchSnapshot(); ).toMatchSnapshot();
expect( expect(
tree.read( tree.read(`my-lib/src/lib/my-lib.controller.ts`, 'utf-8')
`libs/${libFileName}/src/lib/${libFileName}.controller.ts`,
'utf-8'
)
).toMatchSnapshot();
expect(
tree.read(`libs/${libFileName}/src/index.ts`, 'utf-8')
).toMatchSnapshot(); ).toMatchSnapshot();
expect(tree.read(`my-lib/src/index.ts`, 'utf-8')).toMatchSnapshot();
}); });
it('should update tags', async () => { it('should update tags', async () => {
await libraryGenerator(tree, { name: libName, tags: 'one,two' }); await libraryGenerator(tree, {
name: 'myLib',
tags: 'one,two',
projectNameAndRootFormat: 'as-provided',
});
const projects = Object.fromEntries(devkit.getProjects(tree)); const projects = Object.fromEntries(devkit.getProjects(tree));
expect(projects).toEqual({ expect(projects).toEqual({
[libFileName]: expect.objectContaining({ ['my-lib']: expect.objectContaining({
tags: ['one', 'two'], tags: ['one', 'two'],
}), }),
}); });
}); });
it('should update root tsconfig.json', async () => { it('should update root tsconfig.json', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect( expect(tsconfigJson.compilerOptions.paths[`@proj/my-lib`]).toEqual([
tsconfigJson.compilerOptions.paths[`@proj/${libFileName}`] `my-lib/src/index.ts`,
).toEqual([`libs/${libFileName}/src/index.ts`]); ]);
}); });
it('should create a local tsconfig.json', async () => { it('should create a local tsconfig.json', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson(tree, `libs/${libFileName}/tsconfig.json`); const tsconfigJson = readJson(tree, `my-lib/tsconfig.json`);
expect(tsconfigJson).toMatchSnapshot(); expect(tsconfigJson).toMatchSnapshot();
}); });
it('should extend the local tsconfig.json with tsconfig.spec.json', async () => { it('should extend the local tsconfig.json with tsconfig.spec.json', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson( const tsconfigJson = readJson(tree, `my-lib/tsconfig.spec.json`);
tree,
`libs/${libFileName}/tsconfig.spec.json`
);
expect(tsconfigJson.extends).toEqual('./tsconfig.json'); expect(tsconfigJson.extends).toEqual('./tsconfig.json');
}); });
it('should extend the local tsconfig.json with tsconfig.lib.json', async () => { it('should extend the local tsconfig.json with tsconfig.lib.json', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson( const tsconfigJson = readJson(tree, `my-lib/tsconfig.lib.json`);
tree,
`libs/${libFileName}/tsconfig.lib.json`
);
expect(tsconfigJson.extends).toEqual('./tsconfig.json'); expect(tsconfigJson.extends).toEqual('./tsconfig.json');
expect(tsconfigJson.exclude).toEqual([ expect(tsconfigJson.exclude).toEqual([
'jest.config.ts', 'jest.config.ts',
@ -159,95 +168,99 @@ describe('lib', () => {
}); });
it('should generate files', async () => { it('should generate files', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
expect(tree.exists(`libs/${libFileName}/jest.config.ts`)).toBeTruthy(); expect(tree.exists(`my-lib/jest.config.ts`)).toBeTruthy();
expect(tree.exists(`libs/${libFileName}/src/index.ts`)).toBeTruthy(); expect(tree.exists(`my-lib/src/index.ts`)).toBeTruthy();
expect( expect(tree.exists(`my-lib/src/lib/my-lib.spec.ts`)).toBeFalsy();
tree.exists(`libs/${libFileName}/src/lib/${libFileName}.spec.ts`) expect(readJson(tree, `my-lib/.eslintrc.json`)).toMatchSnapshot();
).toBeFalsy();
expect(
readJson(tree, `libs/${libFileName}/.eslintrc.json`)
).toMatchSnapshot();
}); });
}); });
describe('nested', () => { describe('nested', () => {
const dirName = 'myDir';
const dirFileName = 'my-dir';
const nestedLibFileName = `${dirFileName}-${libFileName}`;
it('should update tags', async () => { it('should update tags', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: libName, name: 'myLib',
directory: dirName, directory: 'my-dir/my-lib',
tags: 'one,two', tags: 'one,two',
projectNameAndRootFormat: 'as-provided',
}); });
const projects = Object.fromEntries(devkit.getProjects(tree)); const projects = Object.fromEntries(devkit.getProjects(tree));
expect(projects).toEqual({ expect(projects).toEqual({
[nestedLibFileName]: expect.objectContaining({ tags: ['one', 'two'] }), [`my-lib`]: expect.objectContaining({
tags: ['one', 'two'],
}),
}); });
}); });
it('should generate files', async () => { it('should generate files', async () => {
await libraryGenerator(tree, { name: libName, directory: dirName }); await libraryGenerator(tree, {
name: 'myLib',
directory: 'my-dir/my-lib',
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.exists(`my-dir/my-lib/jest.config.ts`)).toBeTruthy();
tree.exists(`libs/${dirFileName}/${libFileName}/jest.config.ts`) expect(tree.exists(`my-dir/my-lib/src/index.ts`)).toBeTruthy();
).toBeTruthy(); expect(tree.exists(`my-dir/my-lib/src/lib/my-lib.spec.ts`)).toBeFalsy();
expect(
tree.exists(`libs/${dirFileName}/${libFileName}/src/index.ts`)
).toBeTruthy();
expect(
tree.exists(
`libs/${dirFileName}/${libFileName}/src/lib/${libFileName}.spec.ts`
)
).toBeFalsy();
}); });
it('should update workspace.json', async () => { it('should update workspace.json', async () => {
await libraryGenerator(tree, { name: libName, directory: dirName }); await libraryGenerator(tree, {
name: 'myLib',
directory: 'my-dir/my-lib',
projectNameAndRootFormat: 'as-provided',
});
const project = readProjectConfiguration(tree, nestedLibFileName); const project = readProjectConfiguration(tree, `my-lib`);
expect(project.root).toEqual(`libs/${dirFileName}/${libFileName}`); expect(project.root).toEqual(`my-dir/my-lib`);
expect(project.targets.lint).toEqual({ expect(project.targets.lint).toEqual({
executor: '@nx/linter:eslint', executor: '@nx/linter:eslint',
outputs: ['{options.outputFile}'], outputs: ['{options.outputFile}'],
options: { options: {
lintFilePatterns: [`libs/${dirFileName}/${libFileName}/**/*.ts`], lintFilePatterns: [`my-dir/my-lib/**/*.ts`],
}, },
}); });
}); });
it('should update tsconfig.json', async () => { it('should update tsconfig.json', async () => {
await libraryGenerator(tree, { name: libName, directory: dirName }); await libraryGenerator(tree, {
name: 'myLib',
directory: 'my-dir/my-lib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect( expect(tsconfigJson.compilerOptions.paths[`@proj/my-lib`]).toEqual([
tsconfigJson.compilerOptions.paths[ `my-dir/my-lib/src/index.ts`,
`@proj/${dirFileName}/${libFileName}` ]);
] expect(tsconfigJson.compilerOptions.paths[`my-lib/*`]).toBeUndefined();
).toEqual([`libs/${dirFileName}/${libFileName}/src/index.ts`]);
expect(
tsconfigJson.compilerOptions.paths[`${nestedLibFileName}/*`]
).toBeUndefined();
}); });
it('should create a local tsconfig.json', async () => { it('should create a local tsconfig.json', async () => {
await libraryGenerator(tree, { name: libName, directory: dirName }); await libraryGenerator(tree, {
name: 'myLib',
directory: 'my-dir/my-lib',
projectNameAndRootFormat: 'as-provided',
});
expect( expect(readJson(tree, `my-dir/my-lib/tsconfig.json`)).toMatchSnapshot();
readJson(tree, `libs/${dirFileName}/${libFileName}/tsconfig.json`)
).toMatchSnapshot();
}); });
}); });
describe('--strict', () => { describe('--strict', () => {
it('should update the projects tsconfig with strict true', async () => { it('should update the projects tsconfig with strict true', async () => {
await libraryGenerator(tree, { name: libName, strict: true }); await libraryGenerator(tree, {
name: 'myLib',
strict: true,
projectNameAndRootFormat: 'as-provided',
});
const tsConfig = readJson(tree, `/libs/${libFileName}/tsconfig.lib.json`); const tsConfig = readJson(tree, `/my-lib/tsconfig.lib.json`);
expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy(); expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy();
expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy(); expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy();
expect(tsConfig.compilerOptions.strictBindCallApply).toBeTruthy(); expect(tsConfig.compilerOptions.strictBindCallApply).toBeTruthy();
@ -260,17 +273,17 @@ describe('lib', () => {
describe('--unit-test-runner none', () => { describe('--unit-test-runner none', () => {
it('should not generate test configuration', async () => { it('should not generate test configuration', async () => {
await libraryGenerator(tree, { name: libName, unitTestRunner: 'none' }); await libraryGenerator(tree, {
name: 'myLib',
unitTestRunner: 'none',
projectNameAndRootFormat: 'as-provided',
});
expect(tree.exists(`libs/${libFileName}/tsconfig.spec.json`)).toBeFalsy(); expect(tree.exists(`my-lib/tsconfig.spec.json`)).toBeFalsy();
expect(tree.exists(`libs/${libFileName}/jest.config.ts`)).toBeFalsy(); expect(tree.exists(`my-lib/jest.config.ts`)).toBeFalsy();
expect( expect(tree.exists(`my-lib/lib/my-lib.spec.ts`)).toBeFalsy();
tree.exists(`libs/${libFileName}/lib/${libFileName}.spec.ts`) expect(readJson(tree, `my-lib/tsconfig.json`)).toMatchSnapshot();
).toBeFalsy(); const project = readProjectConfiguration(tree, 'my-lib');
expect(
readJson(tree, `libs/${libFileName}/tsconfig.json`)
).toMatchSnapshot();
const project = readProjectConfiguration(tree, libFileName);
expect(project.targets.test).toBeUndefined(); expect(project.targets.test).toBeUndefined();
expect(project.targets.lint).toMatchSnapshot(); expect(project.targets.lint).toMatchSnapshot();
}); });
@ -278,37 +291,39 @@ describe('lib', () => {
describe('publishable package', () => { describe('publishable package', () => {
it('should update package.json', async () => { it('should update package.json', async () => {
const importPath = `@proj/${libName}`; const importPath = `@proj/myLib`;
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: libName, name: 'myLib',
publishable: true, publishable: true,
importPath, importPath,
projectNameAndRootFormat: 'as-provided',
}); });
const packageJson = readJson(tree, `libs/${libFileName}/package.json`); const packageJson = readJson(tree, `my-lib/package.json`);
expect(packageJson.name).toEqual(importPath); expect(packageJson.name).toEqual(importPath);
}); });
}); });
describe('compiler options target', () => { describe('compiler options target', () => {
it('should set target to es6 in tsconfig.lib.json by default', async () => { it('should set target to es6 in tsconfig.lib.json by default', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson( const tsconfigJson = readJson(tree, `my-lib/tsconfig.lib.json`);
tree,
`libs/${libFileName}/tsconfig.lib.json`
);
expect(tsconfigJson.compilerOptions.target).toEqual('es6'); expect(tsconfigJson.compilerOptions.target).toEqual('es6');
}); });
it('should set target to es2021 in tsconfig.lib.json', async () => { it('should set target to es2021 in tsconfig.lib.json', async () => {
await libraryGenerator(tree, { name: libName, target: 'es2021' }); await libraryGenerator(tree, {
name: 'myLib',
target: 'es2021',
projectNameAndRootFormat: 'as-provided',
});
const tsconfigJson = readJson( const tsconfigJson = readJson(tree, `my-lib/tsconfig.lib.json`);
tree,
`libs/${libFileName}/tsconfig.lib.json`
);
expect(tsconfigJson.compilerOptions.target).toEqual('es2021'); expect(tsconfigJson.compilerOptions.target).toEqual('es2021');
}); });
}); });
@ -317,7 +332,10 @@ describe('lib', () => {
it('should format files by default', async () => { it('should format files by default', async () => {
jest.spyOn(devkit, 'formatFiles'); jest.spyOn(devkit, 'formatFiles');
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
expect(devkit.formatFiles).toHaveBeenCalled(); expect(devkit.formatFiles).toHaveBeenCalled();
}); });
@ -325,7 +343,11 @@ describe('lib', () => {
it('should not format files when --skipFormat=true', async () => { it('should not format files when --skipFormat=true', async () => {
jest.spyOn(devkit, 'formatFiles'); jest.spyOn(devkit, 'formatFiles');
await libraryGenerator(tree, { name: libName, skipFormat: true }); await libraryGenerator(tree, {
name: 'myLib',
skipFormat: true,
projectNameAndRootFormat: 'as-provided',
});
expect(devkit.formatFiles).not.toHaveBeenCalled(); expect(devkit.formatFiles).not.toHaveBeenCalled();
}); });
@ -333,56 +355,56 @@ describe('lib', () => {
describe('--testEnvironment', () => { describe('--testEnvironment', () => {
it('should set target jest testEnvironment to node by default', async () => { it('should set target jest testEnvironment to node by default', async () => {
await libraryGenerator(tree, { name: libName }); await libraryGenerator(tree, {
name: 'myLib',
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.read(`my-lib/jest.config.ts`, 'utf-8')).toMatchSnapshot();
tree.read(`libs/${libFileName}/jest.config.ts`, 'utf-8')
).toMatchSnapshot();
}); });
it('should set target jest testEnvironment to jsdom', async () => { it('should set target jest testEnvironment to jsdom', async () => {
await libraryGenerator(tree, { name: libName, testEnvironment: 'jsdom' }); await libraryGenerator(tree, {
name: 'myLib',
testEnvironment: 'jsdom',
projectNameAndRootFormat: 'as-provided',
});
expect( expect(tree.read(`my-lib/jest.config.ts`, 'utf-8')).toMatchSnapshot();
tree.read(`libs/${libFileName}/jest.config.ts`, 'utf-8')
).toMatchSnapshot();
}); });
}); });
describe('--simpleName', () => { describe('--simpleName', () => {
it('should generate a library with a simple name', async () => { it('should generate a library with a simple name', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: libName, name: 'myLib',
simpleName: true, simpleName: true,
directory: 'api', directory: 'api/my-lib',
service: true, service: true,
controller: true, controller: true,
projectNameAndRootFormat: 'as-provided',
}); });
const indexFile = tree.read('libs/api/my-lib/src/index.ts', 'utf-8'); const indexFile = tree.read('api/my-lib/src/index.ts', 'utf-8');
expect(indexFile).toContain(`export * from './lib/my-lib.module';`); expect(indexFile).toContain(`export * from './lib/my-lib.module';`);
expect(indexFile).toContain(`export * from './lib/my-lib.service';`); expect(indexFile).toContain(`export * from './lib/my-lib.service';`);
expect(indexFile).toContain(`export * from './lib/my-lib.controller';`); expect(indexFile).toContain(`export * from './lib/my-lib.controller';`);
expect(tree.exists('api/my-lib/src/lib/my-lib.module.ts')).toBeTruthy();
expect(tree.exists('api/my-lib/src/lib/my-lib.service.ts')).toBeTruthy();
expect( expect(
tree.exists('libs/api/my-lib/src/lib/my-lib.module.ts') tree.exists('api/my-lib/src/lib/my-lib.service.spec.ts')
).toBeTruthy(); ).toBeTruthy();
expect( expect(
tree.exists('libs/api/my-lib/src/lib/my-lib.service.ts') tree.exists('api/my-lib/src/lib/my-lib.controller.ts')
).toBeTruthy(); ).toBeTruthy();
expect( expect(
tree.exists('libs/api/my-lib/src/lib/my-lib.service.spec.ts') tree.exists('api/my-lib/src/lib/my-lib.controller.spec.ts')
).toBeTruthy();
expect(
tree.exists('libs/api/my-lib/src/lib/my-lib.controller.ts')
).toBeTruthy();
expect(
tree.exists('libs/api/my-lib/src/lib/my-lib.controller.spec.ts')
).toBeTruthy(); ).toBeTruthy();
}); });
}); });

View File

@ -2,10 +2,10 @@ import { addProjectConfiguration, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
export function createTreeWithNestApplication(appName: string): Tree { export function createTreeWithNestApplication(appName: string): Tree {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); const tree = createTreeWithEmptyWorkspace();
addProjectConfiguration(tree, appName, { addProjectConfiguration(tree, appName, {
root: `apps/${appName}`, root: `${appName}`,
sourceRoot: `apps/${appName}/src`, sourceRoot: `${appName}/src`,
projectType: 'application', projectType: 'application',
targets: {}, targets: {},
}); });

View File

@ -26,6 +26,7 @@ describe('app', () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'myNodeApp', name: 'myNodeApp',
bundler: 'webpack', bundler: 'webpack',
projectNameAndRootFormat: 'as-provided',
}); });
const project = readProjectConfiguration(tree, 'my-node-app'); const project = readProjectConfiguration(tree, 'my-node-app');
expect(project.root).toEqual('my-node-app'); expect(project.root).toEqual('my-node-app');
@ -83,6 +84,7 @@ describe('app', () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'myNodeApp', name: 'myNodeApp',
tags: 'one,two', tags: 'one,two',
projectNameAndRootFormat: 'as-provided',
}); });
const projects = Object.fromEntries(getProjects(tree)); const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({ expect(projects).toMatchObject({
@ -95,6 +97,7 @@ describe('app', () => {
it('should generate files', async () => { it('should generate files', async () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'myNodeApp', name: 'myNodeApp',
projectNameAndRootFormat: 'as-provided',
}); });
expect(tree.exists(`my-node-app/jest.config.ts`)).toBeTruthy(); expect(tree.exists(`my-node-app/jest.config.ts`)).toBeTruthy();
expect(tree.exists('my-node-app/src/main.ts')).toBeTruthy(); expect(tree.exists('my-node-app/src/main.ts')).toBeTruthy();
@ -170,6 +173,7 @@ describe('app', () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'myNodeApp', name: 'myNodeApp',
projectNameAndRootFormat: 'as-provided',
}); });
const tsconfig = readJson(tree, 'my-node-app/tsconfig.json'); const tsconfig = readJson(tree, 'my-node-app/tsconfig.json');
@ -181,9 +185,10 @@ describe('app', () => {
it('should update project config', async () => { it('should update project config', async () => {
await applicationGenerator(tree, { await applicationGenerator(tree, {
name: 'myNodeApp', name: 'myNodeApp',
directory: 'myDir', directory: 'my-dir/my-node-app',
projectNameAndRootFormat: 'as-provided',
}); });
const project = readProjectConfiguration(tree, 'my-dir-my-node-app'); const project = readProjectConfiguration(tree, 'my-node-app');
expect(project.root).toEqual('my-dir/my-node-app'); expect(project.root).toEqual('my-dir/my-node-app');
@ -196,7 +201,7 @@ describe('app', () => {
}); });
expect(() => expect(() =>
readProjectConfiguration(tree, 'my-dir-my-node-app-e2e') readProjectConfiguration(tree, 'my-node-app-e2e')
).not.toThrow(); ).not.toThrow();
}); });

View File

@ -14,6 +14,7 @@ describe('e2eProjectGenerator', () => {
name: 'api', name: 'api',
framework: 'express', framework: 'express',
e2eTestRunner: 'none', e2eTestRunner: 'none',
projectNameAndRootFormat: 'as-provided',
}); });
await e2eProjectGenerator(tree, { await e2eProjectGenerator(tree, {
projectType: 'server', projectType: 'server',
@ -29,6 +30,7 @@ describe('e2eProjectGenerator', () => {
framework: 'express', framework: 'express',
e2eTestRunner: 'none', e2eTestRunner: 'none',
rootProject: true, rootProject: true,
projectNameAndRootFormat: 'as-provided',
}); });
await e2eProjectGenerator(tree, { await e2eProjectGenerator(tree, {
projectType: 'server', projectType: 'server',
@ -44,6 +46,7 @@ describe('e2eProjectGenerator', () => {
name: 'api', name: 'api',
framework: 'none', framework: 'none',
e2eTestRunner: 'none', e2eTestRunner: 'none',
projectNameAndRootFormat: 'as-provided',
}); });
await e2eProjectGenerator(tree, { await e2eProjectGenerator(tree, {
projectType: 'cli', projectType: 'cli',

View File

@ -13,7 +13,7 @@ describe('init', () => {
let tree: Tree; let tree: Tree;
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
}); });
it('should add dependencies', async () => { it('should add dependencies', async () => {

View File

@ -12,33 +12,34 @@ import { libraryGenerator } from './library';
const baseLibraryConfig = { const baseLibraryConfig = {
name: 'myLib', name: 'myLib',
compiler: 'tsc' as const, compiler: 'tsc' as const,
projectNameAndRootFormat: 'as-provided' as const,
}; };
describe('lib', () => { describe('lib', () => {
let tree: Tree; let tree: Tree;
beforeEach(() => { beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace();
}); });
describe('not nested', () => { describe('not nested', () => {
it('should update configuration', async () => { it('should update configuration', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const configuration = readProjectConfiguration(tree, 'my-lib'); const configuration = readProjectConfiguration(tree, 'my-lib');
expect(configuration.root).toEqual('libs/my-lib'); expect(configuration.root).toEqual('my-lib');
expect(configuration.targets.build).toBeUndefined(); expect(configuration.targets.build).toBeUndefined();
expect(configuration.targets.lint).toEqual({ expect(configuration.targets.lint).toEqual({
executor: '@nx/linter:eslint', executor: '@nx/linter:eslint',
outputs: ['{options.outputFile}'], outputs: ['{options.outputFile}'],
options: { options: {
lintFilePatterns: ['libs/my-lib/**/*.ts'], lintFilePatterns: ['my-lib/**/*.ts'],
}, },
}); });
expect(configuration.targets.test).toEqual({ expect(configuration.targets.test).toEqual({
executor: '@nx/jest:jest', executor: '@nx/jest:jest',
outputs: ['{workspaceRoot}/coverage/{projectRoot}'], outputs: ['{workspaceRoot}/coverage/{projectRoot}'],
options: { options: {
jestConfig: 'libs/my-lib/jest.config.ts', jestConfig: 'my-lib/jest.config.ts',
passWithNoTests: true, passWithNoTests: true,
}, },
configurations: { configurations: {
@ -85,19 +86,19 @@ describe('lib', () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([
'libs/my-lib/src/index.ts', 'my-lib/src/index.ts',
]); ]);
}); });
it('should create a local tsconfig.json', async () => { it('should create a local tsconfig.json', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json'); const tsconfigJson = readJson(tree, 'my-lib/tsconfig.json');
expect(tsconfigJson).toMatchInlineSnapshot(` expect(tsconfigJson).toMatchInlineSnapshot(`
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs", "module": "commonjs",
}, },
"extends": "../../tsconfig.base.json", "extends": "../tsconfig.base.json",
"files": [], "files": [],
"include": [], "include": [],
"references": [ "references": [
@ -114,20 +115,20 @@ describe('lib', () => {
it('should extend the local tsconfig.json with tsconfig.spec.json', async () => { it('should extend the local tsconfig.json with tsconfig.spec.json', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.spec.json'); const tsconfigJson = readJson(tree, 'my-lib/tsconfig.spec.json');
expect(tsconfigJson.extends).toEqual('./tsconfig.json'); expect(tsconfigJson.extends).toEqual('./tsconfig.json');
}); });
it('should extend the local tsconfig.json with tsconfig.lib.json', async () => { it('should extend the local tsconfig.json with tsconfig.lib.json', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); const tsconfigJson = readJson(tree, 'my-lib/tsconfig.lib.json');
expect(tsconfigJson.compilerOptions.types).toContain('node'); expect(tsconfigJson.compilerOptions.types).toContain('node');
expect(tsconfigJson.extends).toEqual('./tsconfig.json'); expect(tsconfigJson.extends).toEqual('./tsconfig.json');
}); });
it('should exclude test files from tsconfig.lib.json', async () => { it('should exclude test files from tsconfig.lib.json', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.lib.json'); const tsconfigJson = readJson(tree, 'my-lib/tsconfig.lib.json');
expect(tsconfigJson.exclude).toEqual([ expect(tsconfigJson.exclude).toEqual([
'jest.config.ts', 'jest.config.ts',
'src/**/*.spec.ts', 'src/**/*.spec.ts',
@ -137,14 +138,14 @@ describe('lib', () => {
it('should generate files', async () => { it('should generate files', async () => {
await libraryGenerator(tree, baseLibraryConfig); await libraryGenerator(tree, baseLibraryConfig);
expect(tree.exists(`libs/my-lib/jest.config.ts`)).toBeTruthy(); expect(tree.exists(`my-lib/jest.config.ts`)).toBeTruthy();
expect(tree.exists('libs/my-lib/src/index.ts')).toBeTruthy(); expect(tree.exists('my-lib/src/index.ts')).toBeTruthy();
const eslintrc = readJson(tree, 'libs/my-lib/.eslintrc.json'); const eslintrc = readJson(tree, 'my-lib/.eslintrc.json');
expect(eslintrc).toMatchInlineSnapshot(` expect(eslintrc).toMatchInlineSnapshot(`
{ {
"extends": [ "extends": [
"../../.eslintrc.json", "../.eslintrc.json",
], ],
"ignorePatterns": [ "ignorePatterns": [
"!**/*", "!**/*",
@ -183,12 +184,12 @@ describe('lib', () => {
it('should update tags', async () => { it('should update tags', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
tags: 'one', tags: 'one',
}); });
let projects = Object.fromEntries(getProjects(tree)); let projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({ expect(projects).toMatchObject({
'my-dir-my-lib': { 'my-lib': {
tags: ['one'], tags: ['one'],
}, },
}); });
@ -196,15 +197,15 @@ describe('lib', () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
name: 'myLib2', name: 'myLib2',
directory: 'myDir', directory: 'my-dir/my-lib-2',
tags: 'one,two', tags: 'one,two',
}); });
projects = Object.fromEntries(getProjects(tree)); projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({ expect(projects).toMatchObject({
'my-dir-my-lib': { 'my-lib': {
tags: ['one'], tags: ['one'],
}, },
'my-dir-my-lib2': { 'my-lib2': {
tags: ['one', 'two'], tags: ['one', 'two'],
}, },
}); });
@ -213,25 +214,25 @@ describe('lib', () => {
it('should generate files', async () => { it('should generate files', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
}); });
expect(tree.exists(`libs/my-dir/my-lib/jest.config.ts`)).toBeTruthy(); expect(tree.exists(`my-dir/my-lib/jest.config.ts`)).toBeTruthy();
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy(); expect(tree.exists('my-dir/my-lib/src/index.ts')).toBeTruthy();
}); });
it('should update workspace.json', async () => { it('should update workspace.json', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
}); });
const project = readProjectConfiguration(tree, 'my-dir-my-lib'); const project = readProjectConfiguration(tree, 'my-lib');
expect(project.root).toEqual('libs/my-dir/my-lib'); expect(project.root).toEqual('my-dir/my-lib');
expect(project.targets.lint).toEqual({ expect(project.targets.lint).toEqual({
executor: '@nx/linter:eslint', executor: '@nx/linter:eslint',
outputs: ['{options.outputFile}'], outputs: ['{options.outputFile}'],
options: { options: {
lintFilePatterns: ['libs/my-dir/my-lib/**/*.ts'], lintFilePatterns: ['my-dir/my-lib/**/*.ts'],
}, },
}); });
}); });
@ -239,15 +240,13 @@ describe('lib', () => {
it('should update tsconfig.json', async () => { it('should update tsconfig.json', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
}); });
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect(tsconfigJson.compilerOptions.paths['@proj/my-dir/my-lib']).toEqual( expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([
['libs/my-dir/my-lib/src/index.ts'] 'my-dir/my-lib/src/index.ts',
); ]);
expect( expect(tsconfigJson.compilerOptions.paths['my-lib/*']).toBeUndefined();
tsconfigJson.compilerOptions.paths['my-dir-my-lib/*']
).toBeUndefined();
}); });
it('should throw an exception when not passing importPath when using --publishable', async () => { it('should throw an exception when not passing importPath when using --publishable', async () => {
@ -256,7 +255,7 @@ describe('lib', () => {
try { try {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
publishable: true, publishable: true,
}); });
} catch (e) { } catch (e) {
@ -269,11 +268,11 @@ describe('lib', () => {
it('should create a local tsconfig.json', async () => { it('should create a local tsconfig.json', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
}); });
const tsconfigJson = readJson(tree, 'libs/my-dir/my-lib/tsconfig.json'); const tsconfigJson = readJson(tree, 'my-dir/my-lib/tsconfig.json');
expect(tsconfigJson.extends).toEqual('../../../tsconfig.base.json'); expect(tsconfigJson.extends).toEqual('../../tsconfig.base.json');
expect(tsconfigJson.references).toEqual([ expect(tsconfigJson.references).toEqual([
{ {
path: './tsconfig.lib.json', path: './tsconfig.lib.json',
@ -287,17 +286,15 @@ describe('lib', () => {
it('should generate filenames that do not contain directory with --simpleModuleName', async () => { it('should generate filenames that do not contain directory with --simpleModuleName', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
directory: 'myDir', directory: 'my-dir/my-lib',
simpleModuleName: true, simpleModuleName: true,
}); });
expect(tree.exists(`libs/my-dir/my-lib/jest.config.ts`)).toBeTruthy(); expect(tree.exists(`my-dir/my-lib/jest.config.ts`)).toBeTruthy();
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy(); expect(tree.exists('my-dir/my-lib/src/index.ts')).toBeTruthy();
expect(tree.exists('libs/my-dir/my-lib/src/lib/my-lib.ts')).toBeTruthy(); expect(tree.exists('my-dir/my-lib/src/lib/my-lib.ts')).toBeTruthy();
expect( expect(tree.exists('my-dir/my-lib/src/lib/my-lib.spec.ts')).toBeTruthy();
tree.exists('libs/my-dir/my-lib/src/lib/my-lib.spec.ts') expect(tree.exists('my-dir/my-lib/src/index.ts')).toBeTruthy();
).toBeTruthy(); expect(tree.exists(`my-dir/my-lib/.eslintrc.json`)).toBeTruthy();
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy();
expect(tree.exists(`libs/my-dir/my-lib/.eslintrc.json`)).toBeTruthy();
}); });
}); });
@ -333,14 +330,14 @@ describe('lib', () => {
...baseLibraryConfig, ...baseLibraryConfig,
unitTestRunner: 'none', unitTestRunner: 'none',
}); });
expect(tree.exists('libs/my-lib/tsconfig.spec.json')).toBeFalsy(); expect(tree.exists('my-lib/tsconfig.spec.json')).toBeFalsy();
expect(tree.exists('libs/my-lib/jest.config.ts')).toBeFalsy(); expect(tree.exists('my-lib/jest.config.ts')).toBeFalsy();
expect(tree.exists('libs/my-lib/lib/my-lib.spec.ts')).toBeFalsy(); expect(tree.exists('my-lib/lib/my-lib.spec.ts')).toBeFalsy();
expect( expect(
readProjectConfiguration(tree, 'my-lib').targets.test readProjectConfiguration(tree, 'my-lib').targets.test
).toBeUndefined(); ).toBeUndefined();
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json'); const tsconfigJson = readJson(tree, 'my-lib/tsconfig.json');
expect(tsconfigJson.extends).toEqual('../../tsconfig.base.json'); expect(tsconfigJson.extends).toEqual('../tsconfig.base.json');
expect(tsconfigJson.references).toEqual([ expect(tsconfigJson.references).toEqual([
{ {
path: './tsconfig.lib.json', path: './tsconfig.lib.json',
@ -357,19 +354,19 @@ describe('lib', () => {
}); });
const projectConfiguration = readProjectConfiguration(tree, 'my-lib'); const projectConfiguration = readProjectConfiguration(tree, 'my-lib');
expect(projectConfiguration.root).toEqual('libs/my-lib'); expect(projectConfiguration.root).toEqual('my-lib');
expect(projectConfiguration.targets.build).toMatchInlineSnapshot(` expect(projectConfiguration.targets.build).toMatchInlineSnapshot(`
{ {
"executor": "@nx/js:tsc", "executor": "@nx/js:tsc",
"options": { "options": {
"assets": [ "assets": [
"libs/my-lib/*.md", "my-lib/*.md",
], ],
"main": "libs/my-lib/src/index.ts", "main": "my-lib/src/index.ts",
"outputPath": "dist/libs/my-lib", "outputPath": "dist/my-lib",
"packageJson": "libs/my-lib/package.json", "packageJson": "my-lib/package.json",
"tsConfig": "libs/my-lib/tsconfig.lib.json", "tsConfig": "my-lib/tsconfig.lib.json",
}, },
"outputs": [ "outputs": [
"{options.outputPath}", "{options.outputPath}",
@ -388,7 +385,7 @@ describe('lib', () => {
}); });
const projectConfiguration = readProjectConfiguration(tree, 'my-lib'); const projectConfiguration = readProjectConfiguration(tree, 'my-lib');
expect(projectConfiguration.root).toEqual('libs/my-lib'); expect(projectConfiguration.root).toEqual('my-lib');
expect(projectConfiguration.targets.build).toBeDefined(); expect(projectConfiguration.targets.build).toBeDefined();
}); });
@ -400,7 +397,7 @@ describe('lib', () => {
importPath: '@proj/mylib', importPath: '@proj/mylib',
}); });
let packageJsonContent = readJson(tree, 'libs/mylib/package.json'); let packageJsonContent = readJson(tree, 'mylib/package.json');
expect(packageJsonContent.name).toEqual('@proj/mylib'); expect(packageJsonContent.name).toEqual('@proj/mylib');
}); });
@ -411,10 +408,10 @@ describe('lib', () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
...baseLibraryConfig, ...baseLibraryConfig,
publishable: true, publishable: true,
directory: 'myDir', directory: 'my-dir/my-lib',
importPath: '@myorg/lib', importPath: '@myorg/lib',
}); });
const packageJson = readJson(tree, 'libs/my-dir/my-lib/package.json'); const packageJson = readJson(tree, 'my-dir/my-lib/package.json');
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect(packageJson.name).toBe('@myorg/lib'); expect(packageJson.name).toBe('@myorg/lib');
@ -455,18 +452,18 @@ describe('lib', () => {
babelJest: true, babelJest: true,
} as Schema); } as Schema);
expect(tree.read(`libs/my-lib/jest.config.ts`, 'utf-8')) expect(tree.read(`my-lib/jest.config.ts`, 'utf-8'))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
"/* eslint-disable */ "/* eslint-disable */
export default { export default {
displayName: 'my-lib', displayName: 'my-lib',
preset: '../../jest.preset.js', preset: '../jest.preset.js',
testEnvironment: 'node', testEnvironment: 'node',
transform: { transform: {
'^.+\\\\.[tj]s$': 'babel-jest', '^.+\\\\.[tj]s$': 'babel-jest',
}, },
moduleFileExtensions: ['ts', 'js', 'html'], moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/my-lib', coverageDirectory: '../coverage/my-lib',
}; };
" "
`); `);
@ -479,22 +476,20 @@ describe('lib', () => {
js: true, js: true,
} as Schema); } as Schema);
expect(tree.exists(`libs/my-lib/jest.config.js`)).toBeTruthy(); expect(tree.exists(`my-lib/jest.config.js`)).toBeTruthy();
expect(tree.exists('libs/my-lib/src/index.js')).toBeTruthy(); expect(tree.exists('my-lib/src/index.js')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/my-lib.js')).toBeTruthy(); expect(tree.exists('my-lib/src/lib/my-lib.js')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/my-lib.spec.js')).toBeTruthy(); expect(tree.exists('my-lib/src/lib/my-lib.spec.js')).toBeTruthy();
expect( expect(readJson(tree, 'my-lib/tsconfig.json').compilerOptions).toEqual({
readJson(tree, 'libs/my-lib/tsconfig.json').compilerOptions
).toEqual({
allowJs: true, allowJs: true,
module: 'commonjs', module: 'commonjs',
}); });
expect(readJson(tree, 'libs/my-lib/tsconfig.lib.json').include).toEqual([ expect(readJson(tree, 'my-lib/tsconfig.lib.json').include).toEqual([
'src/**/*.ts', 'src/**/*.ts',
'src/**/*.js', 'src/**/*.js',
]); ]);
expect(readJson(tree, 'libs/my-lib/tsconfig.lib.json').exclude).toEqual([ expect(readJson(tree, 'my-lib/tsconfig.lib.json').exclude).toEqual([
'jest.config.ts', 'jest.config.ts',
'src/**/*.spec.ts', 'src/**/*.spec.ts',
'src/**/*.test.ts', 'src/**/*.test.ts',
@ -507,7 +502,7 @@ describe('lib', () => {
await libraryGenerator(tree, { name: 'myLib', js: true } as Schema); await libraryGenerator(tree, { name: 'myLib', js: true } as Schema);
const tsconfigJson = readJson(tree, '/tsconfig.base.json'); const tsconfigJson = readJson(tree, '/tsconfig.base.json');
expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([ expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([
'libs/my-lib/src/index.js', 'my-lib/src/index.js',
]); ]);
}); });
@ -519,27 +514,24 @@ describe('lib', () => {
} as Schema); } as Schema);
const projectConfiguration = readProjectConfiguration(tree, 'my-lib'); const projectConfiguration = readProjectConfiguration(tree, 'my-lib');
expect(projectConfiguration.root).toEqual('libs/my-lib'); expect(projectConfiguration.root).toEqual('my-lib');
expect(projectConfiguration.targets.build.options.main).toEqual( expect(projectConfiguration.targets.build.options.main).toEqual(
'libs/my-lib/src/index.js' 'my-lib/src/index.js'
); );
}); });
it('should generate js files for nested libs as well', async () => { it('should generate js files for nested libs as well', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: 'myLib', name: 'myLib',
directory: 'myDir', directory: 'my-dir/my-lib',
js: true, js: true,
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
expect(tree.exists(`libs/my-dir/my-lib/jest.config.js`)).toBeTruthy(); expect(tree.exists(`my-dir/my-lib/jest.config.js`)).toBeTruthy();
expect(tree.exists('libs/my-dir/my-lib/src/index.js')).toBeTruthy(); expect(tree.exists('my-dir/my-lib/src/index.js')).toBeTruthy();
expect( expect(tree.exists('my-dir/my-lib/src/lib/my-lib.js')).toBeTruthy();
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.js') expect(tree.exists('my-dir/my-lib/src/lib/my-lib.spec.js')).toBeTruthy();
).toBeTruthy();
expect(
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.spec.js')
).toBeTruthy();
}); });
}); });
@ -548,31 +540,25 @@ describe('lib', () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: 'myLib', name: 'myLib',
pascalCaseFiles: true, pascalCaseFiles: true,
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
expect(tree.exists('libs/my-lib/src/lib/MyLib.ts')).toBeTruthy(); expect(tree.exists('my-lib/src/lib/MyLib.ts')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/MyLib.spec.ts')).toBeTruthy(); expect(tree.exists('my-lib/src/lib/MyLib.spec.ts')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/my-lib.spec.ts')).toBeFalsy(); expect(tree.exists('my-lib/src/lib/my-lib.spec.ts')).toBeFalsy();
expect(tree.exists('libs/my-lib/src/lib/my-lib.ts')).toBeFalsy(); expect(tree.exists('my-lib/src/lib/my-lib.ts')).toBeFalsy();
}); });
it('should generate files with upper case names for nested libs as well', async () => { it('should generate files with upper case names for nested libs as well', async () => {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name: 'myLib', name: 'myLib',
directory: 'myDir', directory: 'my-dir/my-lib',
pascalCaseFiles: true, pascalCaseFiles: true,
projectNameAndRootFormat: 'as-provided',
} as Schema); } as Schema);
expect( expect(tree.exists('my-dir/my-lib/src/lib/MyLib.ts')).toBeTruthy();
tree.exists('libs/my-dir/my-lib/src/lib/MyDirMyLib.ts') expect(tree.exists('my-dir/my-lib/src/lib/MyLib.spec.ts')).toBeTruthy();
).toBeTruthy(); expect(tree.exists('my-dir/my-lib/src/lib/my-lib.ts')).toBeFalsy();
expect( expect(tree.exists('my-lib/src/lib/my-lib.spec.ts')).toBeFalsy();
tree.exists('libs/my-dir/my-lib/src/lib/MyDirMyLib.spec.ts')
).toBeTruthy();
expect(
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.ts')
).toBeFalsy();
expect(
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.spec.ts')
).toBeFalsy();
}); });
}); });
}); });

View File

@ -14,6 +14,7 @@ describe('setupDockerGenerator', () => {
framework: 'express', framework: 'express',
e2eTestRunner: 'none', e2eTestRunner: 'none',
docker: true, docker: true,
projectNameAndRootFormat: 'as-provided',
}); });
const project = readProjectConfiguration(tree, 'api'); const project = readProjectConfiguration(tree, 'api');
@ -37,6 +38,7 @@ describe('setupDockerGenerator', () => {
framework: 'fastify', framework: 'fastify',
rootProject: true, rootProject: true,
docker: true, docker: true,
projectNameAndRootFormat: 'as-provided',
}); });
const project = readProjectConfiguration(tree, 'api'); const project = readProjectConfiguration(tree, 'api');