diff --git a/packages/angular/src/generators/karma-project/__snapshots__/karma-project.spec.ts.snap b/packages/angular/src/generators/karma-project/__snapshots__/karma-project.spec.ts.snap index 9aab0ae357096..946578a2c0b52 100644 --- a/packages/angular/src/generators/karma-project/__snapshots__/karma-project.spec.ts.snap +++ b/packages/angular/src/generators/karma-project/__snapshots__/karma-project.spec.ts.snap @@ -1,8 +1,75 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`karmaProject --root-project should generate the right karma.conf.js file for a nested project in a workspace with a project at the root 1`] = ` +"// Karma configuration file, see link for more information +// https://karma-runner.github.io/6.4/config/configuration-file.html + +const { join } = require('path'); +const setBaseKarmaConfig = require('../../karma.conf'); + +module.exports = function (config) { + setBaseKarmaConfig(config); + + config.set({ + coverageReporter: { + dir: join(__dirname, '../../coverage/libs/nested-lib') + } + }); +}; +" +`; + +exports[`karmaProject --root-project should support a project located at the root 1`] = ` +"// Karma configuration file, see link for more information +// https://karma-runner.github.io/6.4/config/configuration-file.html + +const { constants } = require('karma'); +const { join } = require('path'); + +module.exports = (config) => { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma'), + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with \`random: false\` + // or set a specific seed with \`seed: 4321\` + }, + clearContext: false, // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true, // removes the duplicated traces + }, + coverageReporter: { + dir: join(__dirname, 'coverage/root-app'), + subdir: '.', + reporters: [{ type: 'html' }, { type: 'text-summary' }], + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: constants.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: true, + restartOnFileChange: true, + }); +}; +" +`; + exports[`karmaProject should create a karma.conf.js 1`] = ` "// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html +// https://karma-runner.github.io/6.4/config/configuration-file.html const { join } = require('path'); const getBaseKarmaConfig = require('../../karma.conf'); diff --git a/packages/angular/src/generators/karma-project/files/karma.conf.js__tmpl__ b/packages/angular/src/generators/karma-project/files/common/karma.conf.js__tmpl__ similarity index 87% rename from packages/angular/src/generators/karma-project/files/karma.conf.js__tmpl__ rename to packages/angular/src/generators/karma-project/files/common/karma.conf.js__tmpl__ index 4f4dc3f195375..6ed7fd01a7eb9 100644 --- a/packages/angular/src/generators/karma-project/files/karma.conf.js__tmpl__ +++ b/packages/angular/src/generators/karma-project/files/common/karma.conf.js__tmpl__ @@ -1,5 +1,5 @@ // Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html +// https://karma-runner.github.io/6.4/config/configuration-file.html const { join } = require('path'); const getBaseKarmaConfig = require('<%= offsetFromRoot %>karma.conf'); diff --git a/packages/angular/src/generators/karma-project/files/tsconfig.spec.json b/packages/angular/src/generators/karma-project/files/common/tsconfig.spec.json similarity index 100% rename from packages/angular/src/generators/karma-project/files/tsconfig.spec.json rename to packages/angular/src/generators/karma-project/files/common/tsconfig.spec.json diff --git a/packages/angular/src/generators/karma-project/files/root-project/karma.conf.js__tmpl__ b/packages/angular/src/generators/karma-project/files/root-project/karma.conf.js__tmpl__ new file mode 100644 index 0000000000000..c82ce2458b2ad --- /dev/null +++ b/packages/angular/src/generators/karma-project/files/root-project/karma.conf.js__tmpl__ @@ -0,0 +1,44 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/6.4/config/configuration-file.html + +const { constants } = require('karma'); +const { join } = require('path'); + +module.exports = (config) => { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma'), + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false, // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true, // removes the duplicated traces + }, + coverageReporter: { + dir: join(__dirname, 'coverage/<%= projectName %>'), + subdir: '.', + reporters: [{ type: 'html' }, { type: 'text-summary' }], + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: constants.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: true, + restartOnFileChange: true, + }); +}; diff --git a/packages/angular/src/generators/karma-project/files/workspace-with-root-project/karma.conf.js__tmpl__ b/packages/angular/src/generators/karma-project/files/workspace-with-root-project/karma.conf.js__tmpl__ new file mode 100644 index 0000000000000..dbbdf05ed972a --- /dev/null +++ b/packages/angular/src/generators/karma-project/files/workspace-with-root-project/karma.conf.js__tmpl__ @@ -0,0 +1,15 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/6.4/config/configuration-file.html + +const { join } = require('path'); +const setBaseKarmaConfig = require('<%= offsetFromRoot %>karma.conf'); + +module.exports = function (config) { + setBaseKarmaConfig(config); + + config.set({ + coverageReporter: { + dir: join(__dirname, '<%= offsetFromRoot %>coverage/<%= projectRoot %>') + } + }); +}; diff --git a/packages/angular/src/generators/karma-project/karma-project.spec.ts b/packages/angular/src/generators/karma-project/karma-project.spec.ts index f7f0d8c8b32b1..22432dbf05828 100644 --- a/packages/angular/src/generators/karma-project/karma-project.spec.ts +++ b/packages/angular/src/generators/karma-project/karma-project.spec.ts @@ -209,4 +209,50 @@ describe('karmaProject', () => { }); }); }); + + describe('--root-project', () => { + it('should support a project located at the root', async () => { + await applicationGenerator(tree, { + name: 'root-app', + unitTestRunner: UnitTestRunner.None, + rootProject: true, + }); + await karmaProjectGenerator(tree, { project: 'root-app' }); + + expect(tree.exists('karma.conf.js')).toBe(true); + expect(tree.read('karma.conf.js', 'utf-8')).toMatchSnapshot(); + expect(tree.exists('tsconfig.spec.json')).toBe(true); + const { references } = devkit.readJson(tree, 'tsconfig.json'); + expect(references).toContainEqual({ + path: './tsconfig.spec.json', + }); + const project = devkit.readProjectConfiguration(tree, 'root-app'); + expect(project.targets.test.options).toStrictEqual({ + polyfills: ['zone.js', 'zone.js/testing'], + tsConfig: 'tsconfig.spec.json', + karmaConfig: 'karma.conf.js', + styles: [], + scripts: [], + assets: [], + }); + }); + + it('should generate the right karma.conf.js file for a nested project in a workspace with a project at the root', async () => { + await applicationGenerator(tree, { + name: 'root-app', + unitTestRunner: UnitTestRunner.Karma, + rootProject: true, + }); + await libraryGenerator(tree, { + name: 'nested-lib', + unitTestRunner: UnitTestRunner.None, + }); + await karmaProjectGenerator(tree, { project: 'nested-lib' }); + + expect(tree.exists('libs/nested-lib/karma.conf.js')).toBe(true); + expect( + tree.read('libs/nested-lib/karma.conf.js', 'utf-8') + ).toMatchSnapshot(); + }); + }); }); diff --git a/packages/angular/src/generators/karma-project/karma-project.ts b/packages/angular/src/generators/karma-project/karma-project.ts index d8a4f1feca93b..cfb0718e4453f 100644 --- a/packages/angular/src/generators/karma-project/karma-project.ts +++ b/packages/angular/src/generators/karma-project/karma-project.ts @@ -1,4 +1,4 @@ -import type { Tree } from '@nrwl/devkit'; +import type { GeneratorCallback, Tree } from '@nrwl/devkit'; import { formatFiles } from '@nrwl/devkit'; import { checkProjectTestTarget } from './lib/check-test-target'; import { generateKarmaProjectFiles } from './lib/generate-karma-project-files'; @@ -10,15 +10,18 @@ import { karmaGenerator } from '../karma/karma'; export async function karmaProjectGenerator( tree: Tree, options: KarmaProjectOptions -) { - karmaGenerator(tree, options); +): Promise { + const installTask = karmaGenerator(tree, options); checkProjectTestTarget(tree, options.project); generateKarmaProjectFiles(tree, options.project); updateTsConfigs(tree, options.project); updateWorkspaceConfig(tree, options.project); + if (!options.skipFormat) { await formatFiles(tree); } + + return installTask; } export default karmaProjectGenerator; diff --git a/packages/angular/src/generators/karma-project/lib/generate-karma-project-files.ts b/packages/angular/src/generators/karma-project/lib/generate-karma-project-files.ts index 4ec1dac486e08..f446583bfcb40 100644 --- a/packages/angular/src/generators/karma-project/lib/generate-karma-project-files.ts +++ b/packages/angular/src/generators/karma-project/lib/generate-karma-project-files.ts @@ -1,6 +1,7 @@ import type { Tree } from '@nrwl/devkit'; import { generateFiles, + getProjects, joinPathFragments, offsetFromRoot, readProjectConfiguration, @@ -10,13 +11,51 @@ export function generateKarmaProjectFiles(tree: Tree, project: string): void { const projectConfig = readProjectConfiguration(tree, project); generateFiles( tree, - joinPathFragments(__dirname, '..', 'files'), + joinPathFragments(__dirname, '..', 'files', 'common'), projectConfig.root, { tmpl: '', projectRoot: projectConfig.root, - isLibrary: projectConfig.projectType === 'library', offsetFromRoot: offsetFromRoot(projectConfig.root), } ); + + if (projectConfig.root === '' || projectConfig.root === '.') { + generateFiles( + tree, + joinPathFragments(__dirname, '..', 'files', 'root-project'), + projectConfig.root, + { + tmpl: '', + projectName: project, + } + ); + } else if (isWorkspaceWithProjectAtRoot(tree)) { + generateFiles( + tree, + joinPathFragments( + __dirname, + '..', + 'files', + 'workspace-with-root-project' + ), + projectConfig.root, + { + tmpl: '', + projectRoot: projectConfig.root, + offsetFromRoot: offsetFromRoot(projectConfig.root), + } + ); + } +} + +function isWorkspaceWithProjectAtRoot(tree: Tree): boolean { + const projects = getProjects(tree); + for (const [, project] of projects) { + if (project.root === '.' || project.root === '') { + return true; + } + } + + return false; } diff --git a/packages/angular/src/generators/utils/path.spec.ts b/packages/angular/src/generators/utils/path.spec.ts index 1943ba56f72de..cc377bb1ea94d 100644 --- a/packages/angular/src/generators/utils/path.spec.ts +++ b/packages/angular/src/generators/utils/path.spec.ts @@ -13,5 +13,9 @@ describe('path helpers', () => { it('should return true regardless if path has relative path chars', () => { expect(pathStartsWith(`lib1/src/app`, `./lib1/src/app`)).toBeTruthy(); }); + + it('should return true for a root path', () => { + expect(pathStartsWith('lib1/src/app', '.')).toBe(true); + }); }); }); diff --git a/packages/angular/src/generators/utils/path.ts b/packages/angular/src/generators/utils/path.ts index cc3fb0bf15cd0..85559e8c831b2 100644 --- a/packages/angular/src/generators/utils/path.ts +++ b/packages/angular/src/generators/utils/path.ts @@ -1,11 +1,11 @@ -import { joinPathFragments } from '@nrwl/devkit'; -import { basename, dirname, normalize, relative } from 'path'; +import { joinPathFragments, workspaceRoot } from '@nrwl/devkit'; +import { basename, dirname, relative } from 'path'; -export function pathStartsWith(path1: string, path2: string) { - path1 = normalize(path1).replace(/\\/g, '/'); - path2 = normalize(path2).replace(/\\/g, '/'); +export function pathStartsWith(path1: string, path2: string): boolean { + const normalizedPath1 = joinPathFragments(workspaceRoot, path1); + const normalizedPath2 = joinPathFragments(workspaceRoot, path2); - return path1.startsWith(path2); + return normalizedPath1.startsWith(normalizedPath2); } export function getRelativeImportToFile(