From df3314d94882e26870b3a4689612df545ec9ff17 Mon Sep 17 00:00:00 2001 From: Mitchell Cash Date: Wed, 7 Sep 2022 11:05:23 +0100 Subject: [PATCH] feat: run all app e2e tests when configuring new sub apps When a new SubApp is added to a project the project is now configured to run all E2E tests by default. Closes #1167 --- src/lib/sub-app/sub-app.factory.test.ts | 40 ++++++++++++++ src/lib/sub-app/sub-app.factory.ts | 71 ++++++++++++++++++++----- 2 files changed, 98 insertions(+), 13 deletions(-) diff --git a/src/lib/sub-app/sub-app.factory.test.ts b/src/lib/sub-app/sub-app.factory.test.ts index f8d016e24..135dd2d1e 100644 --- a/src/lib/sub-app/sub-app.factory.test.ts +++ b/src/lib/sub-app/sub-app.factory.test.ts @@ -20,6 +20,7 @@ describe('SubApp Factory', () => { const files: string[] = tree.files; expect(files.sort()).toEqual([ '/nest-cli.json', + '/apps/jest-e2e.json', '/apps/nestjs-schematics/tsconfig.app.json', '/apps/project/tsconfig.app.json', '/apps/project/src/main.ts', @@ -30,6 +31,13 @@ describe('SubApp Factory', () => { '/apps/project/test/app.e2e-spec.ts', '/apps/project/test/jest-e2e.json', ].sort()); + + expect(JSON.parse(tree.readContent('/apps/jest-e2e.json'))).toMatchObject({ + projects: [ + 'apps/nestjs-schematics/test/jest-e2e.json', + 'apps/project/test/jest-e2e.json', + ] + }); }); it('should manage name to normalize', async () => { const options: SubAppOptions = { @@ -41,6 +49,7 @@ describe('SubApp Factory', () => { const files: string[] = tree.files; expect(files.sort()).toEqual([ '/nest-cli.json', + '/apps/jest-e2e.json', '/apps/nestjs-schematics/tsconfig.app.json', '/apps/awesome-project/tsconfig.app.json', '/apps/awesome-project/src/main.ts', @@ -51,6 +60,13 @@ describe('SubApp Factory', () => { '/apps/awesome-project/test/app.e2e-spec.ts', '/apps/awesome-project/test/jest-e2e.json', ].sort()); + + expect(JSON.parse(tree.readContent('/apps/jest-e2e.json'))).toMatchObject({ + projects: [ + 'apps/nestjs-schematics/test/jest-e2e.json', + 'apps/awesome-project/test/jest-e2e.json', + ] + }); }); it("should keep underscores in sub-app's path and file name", async () => { const options: SubAppOptions = { @@ -62,6 +78,7 @@ describe('SubApp Factory', () => { const files: string[] = tree.files; expect(files.sort()).toEqual([ '/nest-cli.json', + '/apps/jest-e2e.json', '/apps/nestjs-schematics/tsconfig.app.json', '/apps/_project/tsconfig.app.json', '/apps/_project/src/main.ts', @@ -72,6 +89,13 @@ describe('SubApp Factory', () => { '/apps/_project/test/app.e2e-spec.ts', '/apps/_project/test/jest-e2e.json', ].sort()); + + expect(JSON.parse(tree.readContent('/apps/jest-e2e.json'))).toMatchObject({ + projects: [ + 'apps/nestjs-schematics/test/jest-e2e.json', + 'apps/_project/test/jest-e2e.json', + ] + }); }); it('should manage javascript files', async () => { const options: SubAppOptions = { @@ -84,6 +108,7 @@ describe('SubApp Factory', () => { const files: string[] = tree.files; expect(files.sort()).toEqual([ '/nest-cli.json', + '/apps/jest-e2e.json', '/apps/nestjs-schematics/.babelrc', '/apps/nestjs-schematics/index.js', '/apps/nestjs-schematics/jsconfig.json', @@ -98,6 +123,13 @@ describe('SubApp Factory', () => { '/apps/project/test/app.e2e-spec.js', '/apps/project/test/jest-e2e.json', ].sort()); + + expect(JSON.parse(tree.readContent('/apps/jest-e2e.json'))).toMatchObject({ + projects: [ + 'apps/nestjs-schematics/test/jest-e2e.json', + 'apps/project/test/jest-e2e.json', + ] + }); }); it('should generate spec files with custom suffix', async () => { const options: SubAppOptions = { @@ -110,6 +142,7 @@ describe('SubApp Factory', () => { const files: string[] = tree.files; expect(files.sort()).toEqual([ '/nest-cli.json', + '/apps/jest-e2e.json', '/apps/nestjs-schematics/tsconfig.app.json', '/apps/project/tsconfig.app.json', '/apps/project/src/main.ts', @@ -120,5 +153,12 @@ describe('SubApp Factory', () => { '/apps/project/test/jest-e2e.json', '/apps/project/test/app.e2e-test.ts', ].sort()); + + expect(JSON.parse(tree.readContent('/apps/jest-e2e.json'))).toMatchObject({ + projects: [ + 'apps/nestjs-schematics/test/jest-e2e.json', + 'apps/project/test/jest-e2e.json', + ] + }); }); }); diff --git a/src/lib/sub-app/sub-app.factory.ts b/src/lib/sub-app/sub-app.factory.ts index 46bdb52c0..1c2771c59 100644 --- a/src/lib/sub-app/sub-app.factory.ts +++ b/src/lib/sub-app/sub-app.factory.ts @@ -43,7 +43,7 @@ export function main(options: SubAppOptions): Rule { options = transform(options); return chain([ updateTsConfig(), - updatePackageJson(options, appName), + updatePackageJson(options), (tree, context) => isMonorepo(tree) ? noop()(tree, context) @@ -52,6 +52,7 @@ export function main(options: SubAppOptions): Rule { moveDefaultAppToApps(options.path, appName, options.sourceRoot), ])(tree, context), addAppsToCliOptions(options.path, options.name, appName), + addAppsToE2eOptions(options.path, options.name, appName), branchAndMerge(mergeWith(generate(options))), ]); } @@ -145,7 +146,7 @@ function updateTsConfig() { }; } -function updatePackageJson(options: SubAppOptions, defaultAppName: string) { +function updatePackageJson(options: SubAppOptions) { return (host: Tree) => { if (!host.exists('package.json')) { return host; @@ -154,7 +155,7 @@ function updatePackageJson(options: SubAppOptions, defaultAppName: string) { host, 'package.json', (packageJson: Record) => { - updateNpmScripts(packageJson.scripts, options, defaultAppName); + updateNpmScripts(packageJson.scripts, options); updateJestOptions(packageJson.jest, options); }, ); @@ -164,7 +165,6 @@ function updatePackageJson(options: SubAppOptions, defaultAppName: string) { function updateNpmScripts( scripts: Record, options: SubAppOptions, - defaultAppName: string, ) { if (!scripts) { return; @@ -178,15 +178,11 @@ function updateNpmScripts( scripts[defaultTestScriptName] && scripts[defaultTestScriptName].indexOf(options.path as string) < 0 ) { - const defaultTestDir = 'test'; - const newTestDir = join( - options.path as Path, - defaultAppName, - defaultTestDir, - ); - scripts[defaultTestScriptName] = ( - scripts[defaultTestScriptName] as string - ).replace(defaultTestDir, newTestDir); + const defaultSourceRoot = + options.rootDir !== undefined ? options.rootDir : DEFAULT_APPS_PATH; + scripts[ + defaultTestScriptName + ] = `jest --config ${defaultSourceRoot}/jest-e2e.json`; } if ( scripts[defaultFormatScriptName] && @@ -299,6 +295,40 @@ function addAppsToCliOptions( }; } +function addAppsToE2eOptions( + projectRoot: string, + projectName: string, + appName: string, +): Rule { + return (host: Tree) => { + const rootE2eFileExists = host.exists('apps/jest-e2e.json'); + if (!rootE2eFileExists) { + host.create('apps/jest-e2e.json', '{}'); + } + + return updateJsonFile( + host, + 'apps/jest-e2e.json', + (optionsFile: Record) => { + updateMainAppE2eOptions(optionsFile, projectRoot, appName); + if (!optionsFile.projects) { + optionsFile.projects = [] as string[]; + } + + for (const project of optionsFile.projects as string) { + if (project.includes(`apps/${projectName}/test/jest-e2e.json`)) { + throw new SchematicsException( + `Project "${projectName}" exists in the root E2E config already.`, + ); + } + } + + optionsFile.projects.push(`apps/${projectName}/test/jest-e2e.json`); + }, + ); + } +} + function updateMainAppOptions( optionsFile: Record, projectRoot: string, @@ -337,6 +367,21 @@ function updateMainAppOptions( }; } +function updateMainAppE2eOptions( + optionsFile: Record, + projectRoot: string, + appName: string, +) { + if (optionsFile.projects) { + return; + } + const rootFilePath = join(projectRoot as Path, appName); + const e2ePath = join(rootFilePath, 'test/jest-e2e.json'); + + optionsFile.projects = [] as string[]; + optionsFile.projects.push(e2ePath); +} + function generateWorkspace(options: SubAppOptions, appName: string): Source { const path = join(options.path as Path, appName); return apply(url(join('./workspace' as Path, options.language)), [