import { checkFilesExist, newProject, readFile, readJson, runCLI, runCommand, updateFile, exists, ensureProject, uniq } from '../utils'; describe('Command line', () => { it('lint should ensure module boundaries', () => { ensureProject(); const myapp = uniq('myapp'); const myapp2 = uniq('myapp2'); const mylib = uniq('mylib'); const lazylib = uniq('lazylib'); const invalidtaglib = uniq('invalidtaglib'); const validtaglib = uniq('validtaglib'); runCLI(`generate @nrwl/angular:app ${myapp} --tags=validtag`); runCLI(`generate @nrwl/angular:app ${myapp2}`); runCLI(`generate @nrwl/angular:lib ${mylib}`); runCLI(`generate @nrwl/angular:lib ${lazylib}`); runCLI(`generate @nrwl/angular:lib ${invalidtaglib} --tags=invalidtag`); runCLI(`generate @nrwl/angular:lib ${validtaglib} --tags=validtag`); const tslint = readJson('tslint.json'); tslint.rules['nx-enforce-module-boundaries'][1].depConstraints = [ { sourceTag: 'validtag', onlyDependOnLibsWithTags: ['validtag'] }, ...tslint.rules['nx-enforce-module-boundaries'][1].depConstraints ]; updateFile('tslint.json', JSON.stringify(tslint, null, 2)); updateFile( `apps/${myapp}/src/main.ts`, ` import '../../../libs/${mylib}'; import '@proj/${lazylib}'; import '@proj/${mylib}/deep'; import '@proj/${myapp2}'; import '@proj/${invalidtaglib}'; import '@proj/${validtaglib}'; const s = {loadChildren: '@proj/${lazylib}'}; ` ); const out = runCLI(`lint ${myapp}`, { silenceError: true }); expect(out).toContain('library imports must start with @proj/'); expect(out).toContain('imports of lazy-loaded libraries are forbidden'); expect(out).toContain('deep imports into libraries are forbidden'); expect(out).toContain('imports of apps are forbidden'); expect(out).toContain( 'A project tagged with "validtag" can only depend on libs tagged with "validtag"' ); }, 1000000); describe('nx lint', () => { afterAll(() => { newProject(); }); it('should run nx lint', () => { ensureProject(); const appBefore = uniq('before'); const appAfter = uniq('after'); runCLI(`generate @nrwl/angular:app ${appBefore}`); runCommand(`mv apps/${appBefore} apps/${appAfter}`); const stdout = runCommand('./node_modules/.bin/nx lint'); expect(stdout).toContain( `Cannot find project '${appBefore}' in 'apps/${appBefore}'` ); expect(stdout).toContain( `The 'apps/${appAfter}/browserslist' file doesn't belong to any project.` ); }); }); it('format should check and reformat the code', () => { ensureProject(); const myapp = uniq('myapp'); const mylib = uniq('mylib'); runCLI(`generate @nrwl/angular:app ${myapp}`); runCLI(`generate @nrwl/angular:lib ${mylib}`); updateFile( `apps/${myapp}/src/main.ts`, ` const x = 1111; ` ); updateFile( `apps/${myapp}/src/app/app.module.ts`, ` const y = 1111; ` ); updateFile( `apps/${myapp}/src/app/app.component.ts`, ` const z = 1111; ` ); updateFile( `libs/${mylib}/index.ts`, ` const x = 1111; ` ); updateFile( `libs/${mylib}/src/${mylib}.module.ts`, ` const y = 1111; ` ); let stdout = runCommand( `npm run -s format:check -- --files="libs/${mylib}/index.ts" --libs-and-apps` ); expect(stdout).toContain(`libs/${mylib}/index.ts`); expect(stdout).toContain(`libs/${mylib}/src/${mylib}.module.ts`); stdout = runCommand(`npm run -s format:check -- --all`); expect(stdout).toContain(`apps/${myapp}/src/main.ts`); expect(stdout).toContain(`apps/${myapp}/src/app/app.module.ts`); expect(stdout).toContain(`apps/${myapp}/src/app/app.component.ts`); runCommand( `npm run format:write -- --files="apps/${myapp}/src/app/app.module.ts,apps/${myapp}/src/app/app.component.ts"` ); stdout = runCommand('npm run -s format:check -- --all'); expect(stdout).toContain(`apps/${myapp}/src/main.ts`); expect(stdout).not.toContain(`apps/${myapp}/src/app/app.module.ts`); expect(stdout).not.toContain(`apps/${myapp}/src/app/app.component.ts`); runCommand('npm run format:write -- --all'); expect(runCommand('npm run -s format:check -- --all')).toEqual(''); }); it('should support workspace-specific schematics', () => { ensureProject(); const custom = uniq('custom'); runCLI(`g workspace-schematic ${custom} --no-interactive`); checkFilesExist( `tools/schematics/${custom}/index.ts`, `tools/schematics/${custom}/schema.json` ); const json = readJson(`tools/schematics/${custom}/schema.json`); json.properties['directory'] = { type: 'string', description: 'lib directory' }; updateFile(`tools/schematics/${custom}/schema.json`, JSON.stringify(json)); const indexFile = readFile(`tools/schematics/${custom}/index.ts`); updateFile( `tools/schematics/${custom}/index.ts`, indexFile.replace( 'name: schema.name', 'name: schema.name, directory: schema.directory' ) ); const workspace = uniq('workspace'); const dryRunOutput = runCommand( `npm run workspace-schematic ${custom} ${workspace} -- --no-interactive --directory=dir -d` ); expect(exists(`libs/dir/${workspace}/src/index.ts`)).toEqual(false); expect(dryRunOutput).toContain('update angular.json'); expect(dryRunOutput).toContain('update nx.json'); const output = runCommand( `npm run workspace-schematic ${custom} ${workspace} -- --no-interactive --directory=dir` ); checkFilesExist(`libs/dir/${workspace}/src/index.ts`); expect(output).toContain('update angular.json'); expect(output).toContain('update nx.json'); const another = uniq('another'); runCLI(`g workspace-schematic ${another} --no-interactive`); const listSchematicsOutput = runCommand( 'npm run workspace-schematic -- --list-schematics' ); expect(listSchematicsOutput).toContain( 'nx workspace-schematic "--list-schematics"' ); expect(listSchematicsOutput).toContain(custom); expect(listSchematicsOutput).toContain(another); const promptOutput = runCommand( `npm run workspace-schematic ${custom} mylib2 --` ); expect(promptOutput).toContain( 'In which directory should the library be generated?' ); }, 1000000); // describe('dep-graph', () => { // beforeAll(() => { // newProject(); // runCLI('generate @nrwl/angular:app myapp'); // runCLI('generate @nrwl/angular:app myapp2'); // runCLI('generate @nrwl/angular:app myapp3'); // runCLI('generate @nrwl/angular:lib mylib'); // runCLI('generate @nrwl/angular:lib mylib2'); // // updateFile( // 'apps/myapp/src/main.ts', // ` // import '@proj/mylib'; // // const s = {loadChildren: '@proj/mylib2'}; // ` // ); // // updateFile( // 'apps/myapp2/src/app/app.component.spec.ts', // `import '@proj/mylib';` // ); // // updateFile( // 'libs/mylib/src/mylib.module.spec.ts', // `import '@proj/mylib2';` // ); // }); // // it('dep-graph should output json (without critical path) to file', () => { // const file = 'dep-graph.json'; // // runCommand(`npm run dep-graph -- --file="${file}"`); // // expect(() => checkFilesExist(file)).not.toThrow(); // // const jsonFileContents = readJson(file); // // expect(jsonFileContents).toEqual({ // deps: { // mylib2: [], // myapp3: [], // 'myapp3-e2e': [ // { // projectName: 'myapp3', // type: 'implicit' // } // ], // myapp2: [ // { // projectName: 'mylib', // type: 'es6Import' // } // ], // 'myapp2-e2e': [ // { // projectName: 'myapp2', // type: 'implicit' // } // ], // mylib: [ // { // projectName: 'mylib2', // type: 'es6Import' // } // ], // myapp: [ // { // projectName: 'mylib', // type: 'es6Import' // }, // { // projectName: 'mylib2', // type: 'loadChildren' // } // ], // 'myapp-e2e': [ // { // projectName: 'myapp', // type: 'implicit' // } // ] // }, // criticalPath: [] // }); // }, 1000000); // // it('dep-graph should output json with critical path to file', () => { // const file = 'dep-graph.json'; // // runCommand( // `npm run affected:dep-graph -- --files="libs/mylib/src/index.ts" --file="${file}"` // ); // // expect(() => checkFilesExist(file)).not.toThrow(); // // const jsonFileContents = readJson(file); // // expect(jsonFileContents.criticalPath).toContain('myapp'); // expect(jsonFileContents.criticalPath).toContain('myapp2'); // expect(jsonFileContents.criticalPath).toContain('mylib'); // expect(jsonFileContents.criticalPath).not.toContain('mylib2'); // }, 1000000); // // it('dep-graph should output dot to file', () => { // const file = 'dep-graph.dot'; // // runCommand( // `npm run dep-graph -- --files="libs/mylib/index.ts" --file="${file}"` // ); // // expect(() => checkFilesExist(file)).not.toThrow(); // // const fileContents = readFile(file); // expect(fileContents).toContain('"myapp" -> "mylib"'); // expect(fileContents).toContain('"myapp2" -> "mylib"'); // expect(fileContents).toContain('"mylib" -> "mylib2"'); // }, 1000000); // // it('dep-graph should output html to file', () => { // const file = 'dep-graph.html'; // runCommand( // `npm run dep-graph -- --files="libs/mylib/index.ts" --file="${file}"` // ); // // expect(() => checkFilesExist(file)).not.toThrow(); // // const fileContents = readFile(file); // expect(fileContents).toContain(''); // expect(fileContents).toContain('