818 lines
28 KiB
TypeScript
818 lines
28 KiB
TypeScript
import {
|
|
checkFilesExist,
|
|
newProject,
|
|
readJson,
|
|
cleanupProject,
|
|
runCLI,
|
|
uniq,
|
|
updateFile,
|
|
readFile,
|
|
exists,
|
|
tmpProjPath,
|
|
getPackageManagerCommand,
|
|
getSelectedPackageManager,
|
|
runCommand,
|
|
runE2ETests,
|
|
} from '@nx/e2e/utils';
|
|
import { join } from 'path';
|
|
|
|
let proj: string;
|
|
|
|
describe('@nx/workspace:convert-to-monorepo', () => {
|
|
beforeEach(() => {
|
|
proj = newProject({ packages: ['@nx/react', '@nx/js'] });
|
|
});
|
|
|
|
afterEach(() => cleanupProject());
|
|
|
|
it('should convert a standalone webpack and jest react project to a monorepo', async () => {
|
|
const reactApp = uniq('reactapp');
|
|
runCLI(
|
|
`generate @nx/react:app ${reactApp} --rootProject=true --bundler=webpack --unitTestRunner=jest --e2eTestRunner=cypress --no-interactive`
|
|
);
|
|
|
|
runCLI('generate @nx/workspace:convert-to-monorepo --no-interactive');
|
|
|
|
checkFilesExist(
|
|
`apps/${reactApp}/src/main.tsx`,
|
|
`apps/e2e/cypress.config.ts`
|
|
);
|
|
|
|
expect(() => runCLI(`build ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`test ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`lint ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`lint e2e`)).not.toThrow();
|
|
if (runE2ETests()) {
|
|
expect(() => runCLI(`e2e e2e`)).not.toThrow();
|
|
}
|
|
});
|
|
|
|
it('should be convert a standalone vite and playwright react project to a monorepo', async () => {
|
|
const reactApp = uniq('reactapp');
|
|
runCLI(
|
|
`generate @nx/react:app ${reactApp} --rootProject=true --bundler=vite --unitTestRunner vitest --e2eTestRunner=playwright --no-interactive`
|
|
);
|
|
|
|
runCLI('generate @nx/workspace:convert-to-monorepo --no-interactive');
|
|
|
|
checkFilesExist(
|
|
`apps/${reactApp}/src/main.tsx`,
|
|
`apps/e2e/playwright.config.ts`
|
|
);
|
|
|
|
expect(() => runCLI(`build ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`test ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`lint ${reactApp}`)).not.toThrow();
|
|
expect(() => runCLI(`lint e2e`)).not.toThrow();
|
|
if (runE2ETests()) {
|
|
expect(() => runCLI(`e2e e2e`)).not.toThrow();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Workspace Tests', () => {
|
|
beforeAll(() => {
|
|
proj = newProject();
|
|
});
|
|
|
|
afterAll(() => cleanupProject());
|
|
|
|
describe('@nx/workspace:npm-package', () => {
|
|
it('should create a minimal npm package', () => {
|
|
const npmPackage = uniq('npm-package');
|
|
|
|
runCLI(`generate @nx/workspace:npm-package ${npmPackage}`);
|
|
|
|
updateFile('package.json', (content) => {
|
|
const json = JSON.parse(content);
|
|
json.workspaces = ['libs/*'];
|
|
return JSON.stringify(json);
|
|
});
|
|
|
|
const pmc = getPackageManagerCommand({
|
|
packageManager: getSelectedPackageManager(),
|
|
});
|
|
|
|
runCommand(pmc.install);
|
|
|
|
const result = runCLI(`test ${npmPackage}`);
|
|
expect(result).toContain('Hello World');
|
|
});
|
|
});
|
|
|
|
describe('move project', () => {
|
|
/**
|
|
* Tries moving a library from ${lib}/data-access -> shared/${lib}/data-access
|
|
*/
|
|
it('should work for libraries', async () => {
|
|
const lib1 = uniq('mylib');
|
|
const lib2 = uniq('mylib');
|
|
const lib3 = uniq('mylib');
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib1}-data-access --directory=${lib1}/data-access --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/lib/${lib1}-data-access.ts`,
|
|
`export function fromLibOne() { console.log('This is completely pointless'); }`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/index.ts`,
|
|
`export * from './lib/${lib1}-data-access.ts'`
|
|
);
|
|
|
|
/**
|
|
* Create a library which imports a class from lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib2}-ui --directory=${lib2}/ui --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib2}/ui/src/lib/${lib2}-ui.ts`,
|
|
`import { fromLibOne } from '@${proj}/${lib1}-data-access';
|
|
|
|
export const fromLibTwo = () => fromLibOne();`
|
|
);
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib3} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
updateFile(join(lib3, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [`${lib1}-data-access`];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Now try to move lib1
|
|
*/
|
|
|
|
const moveOutput = runCLI(
|
|
`generate @nx/workspace:move --project ${lib1}-data-access shared/${lib1}/data-access --newProjectName=shared-${lib1}-data-access --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
expect(moveOutput).toContain(`DELETE ${lib1}/data-access`);
|
|
expect(exists(`${lib1}/data-access`)).toBeFalsy();
|
|
|
|
const newPath = `shared/${lib1}/data-access`;
|
|
const newName = `shared-${lib1}-data-access`;
|
|
|
|
const readmePath = `${newPath}/README.md`;
|
|
expect(moveOutput).toContain(`CREATE ${readmePath}`);
|
|
checkFilesExist(readmePath);
|
|
|
|
const jestConfigPath = `${newPath}/jest.config.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${jestConfigPath}`);
|
|
checkFilesExist(jestConfigPath);
|
|
const jestConfig = readFile(jestConfigPath);
|
|
expect(jestConfig).toContain(`displayName: 'shared-${lib1}-data-access'`);
|
|
expect(jestConfig).toContain(`preset: '../../../jest.preset.js'`);
|
|
expect(jestConfig).toContain(`'../../../coverage/${newPath}'`);
|
|
|
|
const tsConfigPath = `${newPath}/tsconfig.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigPath}`);
|
|
checkFilesExist(tsConfigPath);
|
|
|
|
const tsConfigLibPath = `${newPath}/tsconfig.lib.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigLibPath}`);
|
|
checkFilesExist(tsConfigLibPath);
|
|
const tsConfigLib = readJson(tsConfigLibPath);
|
|
expect(tsConfigLib.compilerOptions.outDir).toEqual(
|
|
'../../../dist/out-tsc'
|
|
);
|
|
|
|
const tsConfigSpecPath = `${newPath}/tsconfig.spec.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigSpecPath}`);
|
|
checkFilesExist(tsConfigSpecPath);
|
|
const tsConfigSpec = readJson(tsConfigSpecPath);
|
|
expect(tsConfigSpec.compilerOptions.outDir).toEqual(
|
|
'../../../dist/out-tsc'
|
|
);
|
|
|
|
const indexPath = `${newPath}/src/index.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
checkFilesExist(indexPath);
|
|
|
|
const rootClassPath = `${newPath}/src/lib/${lib1}-data-access.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
|
|
checkFilesExist(rootClassPath);
|
|
|
|
let projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(`${lib1}-data-access`);
|
|
const newConfig = readJson(join(newPath, 'project.json'));
|
|
expect(newConfig).toMatchObject({
|
|
tags: [],
|
|
});
|
|
const lib3Config = readJson(join(lib3, 'project.json'));
|
|
expect(lib3Config.implicitDependencies).toEqual([
|
|
`shared-${lib1}-data-access`,
|
|
]);
|
|
|
|
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
|
|
const rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}-data-access`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[
|
|
`@${proj}/shared-${lib1}-data-access`
|
|
]
|
|
).toEqual([`shared/${lib1}/data-access/src/index.ts`]);
|
|
|
|
projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(`${lib1}-data-access`);
|
|
const project = readJson(join(newPath, 'project.json'));
|
|
expect(project).toBeTruthy();
|
|
expect(project.sourceRoot).toBe(`${newPath}/src`);
|
|
|
|
/**
|
|
* Check that the import in lib2 has been updated
|
|
*/
|
|
const lib2FilePath = `${lib2}/ui/src/lib/${lib2}-ui.ts`;
|
|
const lib2File = readFile(lib2FilePath);
|
|
expect(lib2File).toContain(
|
|
`import { fromLibOne } from '@${proj}/shared-${lib1}-data-access';`
|
|
);
|
|
});
|
|
|
|
it('should work for libs created with --importPath', async () => {
|
|
const importPath = '@wibble/fish';
|
|
const lib1 = uniq('mylib');
|
|
const lib2 = uniq('mylib');
|
|
const lib3 = uniq('mylib');
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib1}-data-access --directory=${lib1}/data-access --importPath=${importPath} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/lib/${lib1}-data-access.ts`,
|
|
`export function fromLibOne() { console.log('This is completely pointless'); }`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/index.ts`,
|
|
`export * from './lib/${lib1}-data-access.ts'`
|
|
);
|
|
|
|
/**
|
|
* Create a library which imports a class from lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib2}-ui --directory=${lib2}/ui --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib2}/ui/src/lib/${lib2}-ui.ts`,
|
|
`import { fromLibOne } from '${importPath}';
|
|
|
|
export const fromLibTwo = () => fromLibOne();`
|
|
);
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib3} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
updateFile(join(lib3, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [`${lib1}-data-access`];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Now try to move lib1
|
|
*/
|
|
|
|
const moveOutput = runCLI(
|
|
`generate @nx/workspace:move --project ${lib1}-data-access shared/${lib1}/data-access --newProjectName=shared-${lib1}-data-access --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
expect(moveOutput).toContain(`DELETE ${lib1}/data-access`);
|
|
expect(exists(`${lib1}/data-access`)).toBeFalsy();
|
|
|
|
const newPath = `shared/${lib1}/data-access`;
|
|
const newName = `shared-${lib1}-data-access`;
|
|
|
|
const readmePath = `${newPath}/README.md`;
|
|
expect(moveOutput).toContain(`CREATE ${readmePath}`);
|
|
checkFilesExist(readmePath);
|
|
|
|
const jestConfigPath = `${newPath}/jest.config.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${jestConfigPath}`);
|
|
checkFilesExist(jestConfigPath);
|
|
const jestConfig = readFile(jestConfigPath);
|
|
expect(jestConfig).toContain(`displayName: 'shared-${lib1}-data-access'`);
|
|
expect(jestConfig).toContain(`preset: '../../../jest.preset.js'`);
|
|
expect(jestConfig).toContain(`'../../../coverage/${newPath}'`);
|
|
|
|
const tsConfigPath = `${newPath}/tsconfig.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigPath}`);
|
|
checkFilesExist(tsConfigPath);
|
|
|
|
const tsConfigLibPath = `${newPath}/tsconfig.lib.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigLibPath}`);
|
|
checkFilesExist(tsConfigLibPath);
|
|
const tsConfigLib = readJson(tsConfigLibPath);
|
|
expect(tsConfigLib.compilerOptions.outDir).toEqual(
|
|
'../../../dist/out-tsc'
|
|
);
|
|
|
|
const tsConfigSpecPath = `${newPath}/tsconfig.spec.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigSpecPath}`);
|
|
checkFilesExist(tsConfigSpecPath);
|
|
const tsConfigSpec = readJson(tsConfigSpecPath);
|
|
expect(tsConfigSpec.compilerOptions.outDir).toEqual(
|
|
'../../../dist/out-tsc'
|
|
);
|
|
|
|
const indexPath = `${newPath}/src/index.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
checkFilesExist(indexPath);
|
|
|
|
const rootClassPath = `${newPath}/src/lib/${lib1}-data-access.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
|
|
checkFilesExist(rootClassPath);
|
|
|
|
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
|
|
const rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}-data-access`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[
|
|
`@${proj}/shared-${lib1}-data-access`
|
|
]
|
|
).toEqual([`shared/${lib1}/data-access/src/index.ts`]);
|
|
|
|
const projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(`${lib1}-data-access`);
|
|
const project = readJson(join(newPath, 'project.json'));
|
|
expect(project).toBeTruthy();
|
|
expect(project.sourceRoot).toBe(`${newPath}/src`);
|
|
expect(project.tags).toEqual([]);
|
|
const lib3Config = readJson(join(lib3, 'project.json'));
|
|
expect(lib3Config.implicitDependencies).toEqual([newName]);
|
|
|
|
/**
|
|
* Check that the import in lib2 has been updated
|
|
*/
|
|
const lib2FilePath = `${lib2}/ui/src/lib/${lib2}-ui.ts`;
|
|
const lib2File = readFile(lib2FilePath);
|
|
expect(lib2File).toContain(
|
|
`import { fromLibOne } from '@${proj}/shared-${lib1}-data-access';`
|
|
);
|
|
});
|
|
|
|
it('should work for custom workspace layouts with --project-name-and-root-format=derived', async () => {
|
|
const lib1 = uniq('mylib');
|
|
const lib2 = uniq('mylib');
|
|
const lib3 = uniq('mylib');
|
|
|
|
let nxJson = readJson('nx.json');
|
|
nxJson.workspaceLayout = { libsDir: 'packages' };
|
|
updateFile('nx.json', JSON.stringify(nxJson));
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib1}/data-access --unitTestRunner=jest --project-name-and-root-format=derived`
|
|
);
|
|
|
|
updateFile(
|
|
`packages/${lib1}/data-access/src/lib/${lib1}-data-access.ts`,
|
|
`export function fromLibOne() { console.log('This is completely pointless'); }`
|
|
);
|
|
|
|
updateFile(
|
|
`packages/${lib1}/data-access/src/index.ts`,
|
|
`export * from './lib/${lib1}-data-access.ts'`
|
|
);
|
|
|
|
/**
|
|
* Create a library which imports a class from lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib2}/ui --unitTestRunner=jest --project-name-and-root-format=derived`
|
|
);
|
|
|
|
updateFile(
|
|
`packages/${lib2}/ui/src/lib/${lib2}-ui.ts`,
|
|
`import { fromLibOne } from '@${proj}/${lib1}/data-access';
|
|
|
|
export const fromLibTwo = () => fromLibOne();`
|
|
);
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib3} --unitTestRunner=jest --project-name-and-root-format=derived`
|
|
);
|
|
updateFile(join('packages', lib3, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [`${lib1}-data-access`];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Now try to move lib1
|
|
*/
|
|
|
|
const moveOutput = runCLI(
|
|
`generate @nx/workspace:move --project ${lib1}-data-access shared/${lib1}/data-access --project-name-and-root-format=derived`
|
|
);
|
|
|
|
expect(moveOutput).toContain(`DELETE packages/${lib1}/data-access`);
|
|
expect(exists(`packages/${lib1}/data-access`)).toBeFalsy();
|
|
|
|
const newPath = `packages/shared/${lib1}/data-access`;
|
|
const newName = `shared-${lib1}-data-access`;
|
|
|
|
const readmePath = `${newPath}/README.md`;
|
|
expect(moveOutput).toContain(`CREATE ${readmePath}`);
|
|
checkFilesExist(readmePath);
|
|
|
|
const jestConfigPath = `${newPath}/jest.config.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${jestConfigPath}`);
|
|
checkFilesExist(jestConfigPath);
|
|
const jestConfig = readFile(jestConfigPath);
|
|
expect(jestConfig).toContain(`displayName: 'shared-${lib1}-data-access'`);
|
|
expect(jestConfig).toContain(`preset: '../../../../jest.preset.js'`);
|
|
expect(jestConfig).toContain(`'../../../../coverage/${newPath}'`);
|
|
|
|
const tsConfigPath = `${newPath}/tsconfig.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigPath}`);
|
|
checkFilesExist(tsConfigPath);
|
|
|
|
const tsConfigLibPath = `${newPath}/tsconfig.lib.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigLibPath}`);
|
|
checkFilesExist(tsConfigLibPath);
|
|
const tsConfigLib = readJson(tsConfigLibPath);
|
|
expect(tsConfigLib.compilerOptions.outDir).toEqual(
|
|
'../../../../dist/out-tsc'
|
|
);
|
|
|
|
const tsConfigSpecPath = `${newPath}/tsconfig.spec.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigSpecPath}`);
|
|
checkFilesExist(tsConfigSpecPath);
|
|
const tsConfigSpec = readJson(tsConfigSpecPath);
|
|
expect(tsConfigSpec.compilerOptions.outDir).toEqual(
|
|
'../../../../dist/out-tsc'
|
|
);
|
|
|
|
const indexPath = `${newPath}/src/index.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
checkFilesExist(indexPath);
|
|
|
|
const rootClassPath = `${newPath}/src/lib/${lib1}-data-access.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
|
|
checkFilesExist(rootClassPath);
|
|
|
|
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
|
|
const rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[
|
|
`@${proj}/shared/${lib1}/data-access`
|
|
]
|
|
).toEqual([`packages/shared/${lib1}/data-access/src/index.ts`]);
|
|
|
|
const projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(`${lib1}-data-access`);
|
|
const project = readJson(join(newPath, 'project.json'));
|
|
expect(project).toBeTruthy();
|
|
expect(project.sourceRoot).toBe(`${newPath}/src`);
|
|
expect(project.tags).toEqual([]);
|
|
|
|
/**
|
|
* Check that the import in lib2 has been updated
|
|
*/
|
|
const lib2FilePath = `packages/${lib2}/ui/src/lib/${lib2}-ui.ts`;
|
|
const lib2File = readFile(lib2FilePath);
|
|
expect(lib2File).toContain(
|
|
`import { fromLibOne } from '@${proj}/shared/${lib1}/data-access';`
|
|
);
|
|
|
|
nxJson = readJson('nx.json');
|
|
delete nxJson.workspaceLayout;
|
|
updateFile('nx.json', JSON.stringify(nxJson));
|
|
});
|
|
|
|
it('should work when moving a lib to a subfolder', async () => {
|
|
const lib1 = uniq('lib1');
|
|
const lib2 = uniq('lib2');
|
|
const lib3 = uniq('lib3');
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib1} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/src/lib/${lib1}.ts`,
|
|
`export function fromLibOne() { console.log('This is completely pointless'); }`
|
|
);
|
|
|
|
updateFile(`${lib1}/src/index.ts`, `export * from './lib/${lib1}.ts'`);
|
|
|
|
/**
|
|
* Create a library which imports a class from lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib2}-ui --directory=${lib2}/ui --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib2}/ui/src/lib/${lib2}-ui.ts`,
|
|
`import { fromLibOne } from '@${proj}/${lib1}';
|
|
|
|
export const fromLibTwo = () => fromLibOne();`
|
|
);
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib3} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
updateFile(join(lib3, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [lib1];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Now try to move lib1
|
|
*/
|
|
|
|
const moveOutput = runCLI(
|
|
`generate @nx/workspace:move --project ${lib1} ${lib1}/data-access --newProjectName=${lib1}-data-access --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
expect(moveOutput).toContain(`DELETE ${lib1}/project.json`);
|
|
expect(exists(`${lib1}/project.json`)).toBeFalsy();
|
|
|
|
const newPath = `${lib1}/data-access`;
|
|
const newName = `${lib1}-data-access`;
|
|
|
|
const readmePath = `${newPath}/README.md`;
|
|
expect(moveOutput).toContain(`CREATE ${readmePath}`);
|
|
checkFilesExist(readmePath);
|
|
|
|
const jestConfigPath = `${newPath}/jest.config.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${jestConfigPath}`);
|
|
checkFilesExist(jestConfigPath);
|
|
const jestConfig = readFile(jestConfigPath);
|
|
expect(jestConfig).toContain(`displayName: '${lib1}-data-access'`);
|
|
expect(jestConfig).toContain(`preset: '../../jest.preset.js'`);
|
|
expect(jestConfig).toContain(`'../../coverage/${newPath}'`);
|
|
|
|
const tsConfigPath = `${newPath}/tsconfig.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigPath}`);
|
|
checkFilesExist(tsConfigPath);
|
|
|
|
const tsConfigLibPath = `${newPath}/tsconfig.lib.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigLibPath}`);
|
|
checkFilesExist(tsConfigLibPath);
|
|
const tsConfigLib = readJson(tsConfigLibPath);
|
|
expect(tsConfigLib.compilerOptions.outDir).toEqual('../../dist/out-tsc');
|
|
|
|
const tsConfigSpecPath = `${newPath}/tsconfig.spec.json`;
|
|
expect(moveOutput).toContain(`CREATE ${tsConfigSpecPath}`);
|
|
checkFilesExist(tsConfigSpecPath);
|
|
const tsConfigSpec = readJson(tsConfigSpecPath);
|
|
expect(tsConfigSpec.compilerOptions.outDir).toEqual('../../dist/out-tsc');
|
|
|
|
const indexPath = `${newPath}/src/index.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
checkFilesExist(indexPath);
|
|
|
|
const rootClassPath = `${newPath}/src/lib/${lib1}.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
|
|
checkFilesExist(rootClassPath);
|
|
|
|
let projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(lib1);
|
|
const newConfig = readJson(join(newPath, 'project.json'));
|
|
expect(newConfig).toMatchObject({
|
|
tags: [],
|
|
});
|
|
const lib3Config = readJson(join(lib3, 'project.json'));
|
|
expect(lib3Config.implicitDependencies).toEqual([`${lib1}-data-access`]);
|
|
|
|
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
|
|
const rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}-data-access`]
|
|
).toEqual([`${lib1}/data-access/src/index.ts`]);
|
|
|
|
projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(lib1);
|
|
const project = readJson(join(newPath, 'project.json'));
|
|
expect(project).toBeTruthy();
|
|
expect(project.sourceRoot).toBe(`${newPath}/src`);
|
|
|
|
/**
|
|
* Check that the import in lib2 has been updated
|
|
*/
|
|
const lib2FilePath = `${lib2}/ui/src/lib/${lib2}-ui.ts`;
|
|
const lib2File = readFile(lib2FilePath);
|
|
expect(lib2File).toContain(
|
|
`import { fromLibOne } from '@${proj}/${lib1}-data-access';`
|
|
);
|
|
});
|
|
|
|
it('should work for libraries when scope is unset', async () => {
|
|
const json = readJson('package.json');
|
|
json.name = proj;
|
|
updateFile('package.json', JSON.stringify(json));
|
|
|
|
const lib1 = uniq('mylib');
|
|
const lib2 = uniq('mylib');
|
|
const lib3 = uniq('mylib');
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib1}-data-access --directory=${lib1}/data-access --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
let rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}-data-access`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`${lib1}-data-access`]
|
|
).toBeDefined();
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/lib/${lib1}-data-access.ts`,
|
|
`export function fromLibOne() { console.log('This is completely pointless'); }`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib1}/data-access/src/index.ts`,
|
|
`export * from './lib/${lib1}-data-access.ts'`
|
|
);
|
|
|
|
/**
|
|
* Create a library which imports a class from lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib2}-ui --directory=${lib2}/ui --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
updateFile(
|
|
`${lib2}/ui/src/lib/${lib2}-ui.ts`,
|
|
`import { fromLibOne } from '${lib1}-data-access';
|
|
|
|
export const fromLibTwo = () => fromLibOne();`
|
|
);
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(
|
|
`generate @nx/js:lib ${lib3} --unitTestRunner=jest --project-name-and-root-format=as-provided`
|
|
);
|
|
updateFile(join(lib3, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [`${lib1}-data-access`];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Now try to move lib1
|
|
*/
|
|
|
|
const moveOutput = runCLI(
|
|
`generate @nx/workspace:move --project ${lib1}-data-access shared/${lib1}/data-access --newProjectName=shared-${lib1}-data-access --project-name-and-root-format=as-provided`
|
|
);
|
|
|
|
expect(moveOutput).toContain(`DELETE ${lib1}/data-access`);
|
|
expect(exists(`${lib1}/data-access`)).toBeFalsy();
|
|
|
|
const newPath = `shared/${lib1}/data-access`;
|
|
const newName = `shared-${lib1}-data-access`;
|
|
|
|
const readmePath = `${newPath}/README.md`;
|
|
expect(moveOutput).toContain(`CREATE ${readmePath}`);
|
|
checkFilesExist(readmePath);
|
|
|
|
const indexPath = `${newPath}/src/index.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
checkFilesExist(indexPath);
|
|
|
|
const rootClassPath = `${newPath}/src/lib/${lib1}-data-access.ts`;
|
|
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
|
|
checkFilesExist(rootClassPath);
|
|
|
|
const newConfig = readJson(join(newPath, 'project.json'));
|
|
expect(newConfig).toMatchObject({
|
|
tags: [],
|
|
});
|
|
const lib3Config = readJson(join(lib3, 'project.json'));
|
|
expect(lib3Config.implicitDependencies).toEqual([
|
|
`shared-${lib1}-data-access`,
|
|
]);
|
|
|
|
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
|
|
rootTsConfig = readJson('tsconfig.base.json');
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`${lib1}-data-access`]
|
|
).toBeUndefined();
|
|
expect(
|
|
rootTsConfig.compilerOptions.paths[`shared-${lib1}-data-access`]
|
|
).toEqual([`shared/${lib1}/data-access/src/index.ts`]);
|
|
|
|
const projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(`${lib1}-data-access`);
|
|
const project = readJson(join(newPath, 'project.json'));
|
|
expect(project).toBeTruthy();
|
|
expect(project.sourceRoot).toBe(`${newPath}/src`);
|
|
|
|
/**
|
|
* Check that the import in lib2 has been updated
|
|
*/
|
|
const lib2FilePath = `${lib2}/ui/src/lib/${lib2}-ui.ts`;
|
|
const lib2File = readFile(lib2FilePath);
|
|
expect(lib2File).toContain(
|
|
`import { fromLibOne } from 'shared-${lib1}-data-access';`
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('remove project', () => {
|
|
/**
|
|
* Tries creating then deleting a lib
|
|
*/
|
|
it('should work', async () => {
|
|
const lib1 = uniq('myliba');
|
|
const lib2 = uniq('mylibb');
|
|
|
|
runCLI(`generate @nx/js:lib ${lib1} --unitTestRunner=jest`);
|
|
expect(exists(tmpProjPath(`libs/${lib1}`))).toBeTruthy();
|
|
|
|
/**
|
|
* Create a library which has an implicit dependency on lib1
|
|
*/
|
|
|
|
runCLI(`generate @nx/js:lib ${lib2} --unitTestRunner=jest`);
|
|
updateFile(join('libs', lib2, 'project.json'), (content) => {
|
|
const data = JSON.parse(content);
|
|
data.implicitDependencies = [lib1];
|
|
return JSON.stringify(data, null, 2);
|
|
});
|
|
|
|
/**
|
|
* Try removing the project (should fail)
|
|
*/
|
|
|
|
let error;
|
|
try {
|
|
console.log(runCLI(`generate @nx/workspace:remove --project ${lib1}`));
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
|
|
expect(error).toBeDefined();
|
|
expect(error.stdout.toString()).toContain(
|
|
`${lib1} is still a dependency of the following projects`
|
|
);
|
|
expect(error.stdout.toString()).toContain(lib2);
|
|
|
|
/**
|
|
* Try force removing the project
|
|
*/
|
|
|
|
const removeOutputForced = runCLI(
|
|
`generate @nx/workspace:remove --project ${lib1} --forceRemove`
|
|
);
|
|
|
|
expect(removeOutputForced).toContain(`DELETE libs/${lib1}`);
|
|
expect(exists(tmpProjPath(`libs/${lib1}`))).toBeFalsy();
|
|
|
|
expect(removeOutputForced).not.toContain(`UPDATE nx.json`);
|
|
const projects = runCLI('show projects').split('\n');
|
|
expect(projects).not.toContain(lib1);
|
|
const lib2Config = readJson(join('libs', lib2, 'project.json'));
|
|
expect(lib2Config.implicitDependencies).toEqual([]);
|
|
|
|
expect(projects[`${lib1}`]).toBeUndefined();
|
|
});
|
|
});
|
|
});
|