From 6bca1db956c44358716d52f0b9f3c012ba0b482d Mon Sep 17 00:00:00 2001 From: Nikolay Vitkov <34244704+Lightning00Blade@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:41:42 +0200 Subject: [PATCH] feat: support for multi projects repos (#10665) --- packages/ng-schematics/.gitignore | 3 +- .../src/builders/puppeteer/index.ts | 19 ++++----- .../tests/app.__ext@dasherize__.ts.template | 2 +- .../files/base/e2e/tsconfig.json.template | 2 +- .../src/schematics/utils/files.ts | 39 +++++++++++++++---- .../src/schematics/utils/packages.ts | 5 ++- .../ng-schematics/test/src/ng-add.spec.ts | 37 +++++++++--------- packages/ng-schematics/test/src/test.spec.ts | 14 +++---- packages/ng-schematics/test/src/utils.ts | 24 +++--------- 9 files changed, 77 insertions(+), 68 deletions(-) diff --git a/packages/ng-schematics/.gitignore b/packages/ng-schematics/.gitignore index 93d9982369d..5c0e14548c4 100644 --- a/packages/ng-schematics/.gitignore +++ b/packages/ng-schematics/.gitignore @@ -1,3 +1,4 @@ # Sandbox -sandbox/ \ No newline at end of file +sandbox/ +multi/ diff --git a/packages/ng-schematics/src/builders/puppeteer/index.ts b/packages/ng-schematics/src/builders/puppeteer/index.ts index 2738c90f418..30cb126b277 100644 --- a/packages/ng-schematics/src/builders/puppeteer/index.ts +++ b/packages/ng-schematics/src/builders/puppeteer/index.ts @@ -32,28 +32,25 @@ function getExecutable(command: string[]) { const executable = command.shift()!; const error = getError(executable, command); - if (executable === 'node') { - return { - executable: executable, - args: command, - error, - }; - } - return { - executable: `./node_modules/.bin/${executable}`, + executable, args: command, error, }; } async function executeCommand(context: BuilderContext, command: string[]) { - await new Promise((resolve, reject) => { + await new Promise(async (resolve, reject) => { context.logger.debug(`Trying to execute command - ${command.join(' ')}.`); const {executable, args, error} = getExecutable(command); + let path = context.workspaceRoot; + if (context.target) { + const project = await context.getProjectMetadata(context.target.project); + path = `${path}/${project['root']}`; + } const child = spawn(executable, args, { - cwd: context.workspaceRoot, + cwd: path, stdio: 'inherit', }); diff --git a/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.__ext@dasherize__.ts.template b/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.__ext@dasherize__.ts.template index c9ee1b49836..eec01a61919 100644 --- a/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.__ext@dasherize__.ts.template +++ b/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.__ext@dasherize__.ts.template @@ -10,7 +10,7 @@ describe('App test', function () { setupBrowserHooks(); it('is running', async function () { const {page} = getBrowserState(); - const element = await page.waitForSelector('text/sandbox app is running!'); + const element = await page.waitForSelector('text/<%= project %> app is running!'); <% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %> expect(element).not.toBeNull(); diff --git a/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template b/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template index 55cf465ae68..583e5ed4af7 100644 --- a/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template +++ b/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.json", + "extends": "<%= tsConfigPath %>", "compilerOptions": {<% if(testingFramework == 'jest') { %> "esModuleInterop": true,<% } %><% if(testingFramework == 'node') { %> "module": "CommonJS", diff --git a/packages/ng-schematics/src/schematics/utils/files.ts b/packages/ng-schematics/src/schematics/utils/files.ts index d294ad80629..0ad8a43ba3b 100644 --- a/packages/ng-schematics/src/schematics/utils/files.ts +++ b/packages/ng-schematics/src/schematics/utils/files.ts @@ -29,7 +29,7 @@ import { url, } from '@angular-devkit/schematics'; -import {SchematicsOptions, TestingFramework} from './types.js'; +import {AngularProject, SchematicsOptions, TestingFramework} from './types.js'; export interface FilesOptions { projects: Record; @@ -62,7 +62,7 @@ export function addFiles( ): any { return chain( Object.keys(projects).map(name => { - const project = projects[name]; + const project = projects[name] as AngularProject; const projectPath = resolve(getSystemPath(normalize(project.root))); const workspacePath = resolve(getSystemPath(normalize(''))); @@ -72,6 +72,7 @@ export function addFiles( ); const baseUrl = getProjectBaseUrl(project, options.port); + const tsConfigPath = getTsConfigPath(project); return mergeWith( apply(url(applyPath), [ @@ -87,6 +88,7 @@ export function addFiles( ...strings, root: project.root ? `${project.root}/` : project.root, baseUrl, + tsConfigPath, project: name, relativeToWorkspace, }), @@ -109,6 +111,13 @@ function getProjectBaseUrl(project: any, port: number): string { return `${options.protocol}://${options.host}:${options.port}`; } +function getTsConfigPath(project: AngularProject): string { + if (!project.root) { + return '../tsconfig.json'; + } + return `../tsconfig.app.json`; +} + export function addBaseFiles( tree: Tree, context: SchematicContext, @@ -144,17 +153,33 @@ export function addFrameworkFiles( return addFiles(tree, context, options); } -export function getScriptFromOptions(options: SchematicsOptions): string[][] { +export function getScriptFromOptions( + options: SchematicsOptions, + root?: string +): string[][] { + let path = 'node_modules/.bin'; + if (root && root !== '') { + const nested = root + .split('/') + .map(() => { + return '../'; + }) + .join(''); + path = `${nested}${path}`; + } else { + path = `./${path}`; + } + switch (options.testingFramework) { case TestingFramework.Jasmine: - return [[`jasmine`, '--config=./e2e/support/jasmine.json']]; + return [[`${path}/jasmine`, '--config=./e2e/support/jasmine.json']]; case TestingFramework.Jest: - return [[`jest`, '-c', 'e2e/jest.config.js']]; + return [[`${path}/jest`, '-c', 'e2e/jest.config.js']]; case TestingFramework.Mocha: - return [[`mocha`, '--config=./e2e/.mocharc.js']]; + return [[`${path}/mocha`, '--config=./e2e/.mocharc.js']]; case TestingFramework.Node: return [ - [`tsc`, '-p', 'e2e/tsconfig.json'], + [`${path}/tsc`, '-p', 'e2e/tsconfig.json'], ['node', '--test', '--test-reporter', 'spec', 'e2e/build/'], ]; } diff --git a/packages/ng-schematics/src/schematics/utils/packages.ts b/packages/ng-schematics/src/schematics/utils/packages.ts index 40d8a4b76e6..953be74a898 100644 --- a/packages/ng-schematics/src/schematics/utils/packages.ts +++ b/packages/ng-schematics/src/schematics/utils/packages.ts @@ -168,11 +168,14 @@ export function updateAngularJsonScripts( overwrite = true ): Tree { const angularJson = getAngularConfig(tree); - const commands = getScriptFromOptions(options); const name = getNgCommandName(options); const port = options.port !== 4200 ? Number(options.port) : undefined; Object.keys(angularJson['projects']).forEach(project => { + const commands = getScriptFromOptions( + options, + angularJson['projects'][project]!.root + ); const e2eScript = [ { name, diff --git a/packages/ng-schematics/test/src/ng-add.spec.ts b/packages/ng-schematics/test/src/ng-add.spec.ts index 399df9d2762..c6f94d8790a 100644 --- a/packages/ng-schematics/test/src/ng-add.spec.ts +++ b/packages/ng-schematics/test/src/ng-add.spec.ts @@ -4,7 +4,6 @@ import { buildTestingTree, getAngularJsonScripts, getPackageJson, - getProjectFile, setupHttpHooks, } from './utils.js'; @@ -16,9 +15,9 @@ describe('@puppeteer/ng-schematics: ng-add', () => { const {devDependencies, scripts} = getPackageJson(tree); const {builder, configurations} = getAngularJsonScripts(tree); - expect(tree.files).toContain(getProjectFile('e2e/tsconfig.json')); - expect(tree.files).toContain(getProjectFile('e2e/tests/app.e2e.ts')); - expect(tree.files).toContain(getProjectFile('e2e/tests/utils.ts')); + expect(tree.files).toContain('/e2e/tsconfig.json'); + expect(tree.files).toContain('/e2e/tests/app.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/utils.ts'); expect(devDependencies).toContain('puppeteer'); expect(scripts['e2e']).toBe('ng e2e'); expect(builder).toBe('@puppeteer/ng-schematics:puppeteer'); @@ -45,7 +44,7 @@ describe('@puppeteer/ng-schematics: ng-add', () => { exportConfig: true, }); - expect(files).toContain(getProjectFile('.puppeteerrc.cjs')); + expect(files).toContain('/.puppeteerrc.cjs'); }); it('should not create Puppeteer config', async () => { @@ -53,7 +52,7 @@ describe('@puppeteer/ng-schematics: ng-add', () => { exportConfig: false, }); - expect(files).not.toContain(getProjectFile('.puppeteerrc.cjs')); + expect(files).not.toContain('/.puppeteerrc.cjs'); }); it('should create Jasmine files and update "package.json"', async () => { @@ -63,14 +62,14 @@ describe('@puppeteer/ng-schematics: ng-add', () => { const {devDependencies} = getPackageJson(tree); const {options} = getAngularJsonScripts(tree); - expect(tree.files).toContain(getProjectFile('e2e/support/jasmine.json')); - expect(tree.files).toContain(getProjectFile('e2e/helpers/babel.js')); + expect(tree.files).toContain('/e2e/support/jasmine.json'); + expect(tree.files).toContain('/e2e/helpers/babel.js'); expect(devDependencies).toContain('jasmine'); expect(devDependencies).toContain('@babel/core'); expect(devDependencies).toContain('@babel/register'); expect(devDependencies).toContain('@babel/preset-typescript'); expect(options['commands']).toEqual([ - [`jasmine`, '--config=./e2e/support/jasmine.json'], + [`./node_modules/.bin/jasmine`, '--config=./e2e/support/jasmine.json'], ]); }); @@ -81,11 +80,13 @@ describe('@puppeteer/ng-schematics: ng-add', () => { const {devDependencies} = getPackageJson(tree); const {options} = getAngularJsonScripts(tree); - expect(tree.files).toContain(getProjectFile('e2e/jest.config.js')); + expect(tree.files).toContain('/e2e/jest.config.js'); expect(devDependencies).toContain('jest'); expect(devDependencies).toContain('@types/jest'); expect(devDependencies).toContain('ts-jest'); - expect(options['commands']).toEqual([[`jest`, '-c', 'e2e/jest.config.js']]); + expect(options['commands']).toEqual([ + [`./node_modules/.bin/jest`, '-c', 'e2e/jest.config.js'], + ]); }); it('should create Mocha files and update "package.json"', async () => { @@ -95,15 +96,15 @@ describe('@puppeteer/ng-schematics: ng-add', () => { const {devDependencies} = getPackageJson(tree); const {options} = getAngularJsonScripts(tree); - expect(tree.files).toContain(getProjectFile('e2e/.mocharc.js')); - expect(tree.files).toContain(getProjectFile('e2e/babel.js')); + expect(tree.files).toContain('/e2e/.mocharc.js'); + expect(tree.files).toContain('/e2e/babel.js'); expect(devDependencies).toContain('mocha'); expect(devDependencies).toContain('@types/mocha'); expect(devDependencies).toContain('@babel/core'); expect(devDependencies).toContain('@babel/register'); expect(devDependencies).toContain('@babel/preset-typescript'); expect(options['commands']).toEqual([ - [`mocha`, '--config=./e2e/.mocharc.js'], + [`./node_modules/.bin/mocha`, '--config=./e2e/.mocharc.js'], ]); }); @@ -113,11 +114,11 @@ describe('@puppeteer/ng-schematics: ng-add', () => { }); const {options} = getAngularJsonScripts(tree); - expect(tree.files).toContain(getProjectFile('e2e/.gitignore')); - expect(tree.files).not.toContain(getProjectFile('e2e/tests/app.e2e.ts')); - expect(tree.files).toContain(getProjectFile('e2e/tests/app.test.ts')); + expect(tree.files).toContain('/e2e/.gitignore'); + expect(tree.files).not.toContain('/e2e/tests/app.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/app.test.ts'); expect(options['commands']).toEqual([ - [`tsc`, '-p', 'e2e/tsconfig.json'], + [`./node_modules/.bin/tsc`, '-p', 'e2e/tsconfig.json'], ['node', '--test', '--test-reporter', 'spec', 'e2e/build/'], ]); }); diff --git a/packages/ng-schematics/test/src/test.spec.ts b/packages/ng-schematics/test/src/test.spec.ts index f3e1a317d03..7943b2a531c 100644 --- a/packages/ng-schematics/test/src/test.spec.ts +++ b/packages/ng-schematics/test/src/test.spec.ts @@ -1,6 +1,6 @@ import expect from 'expect'; -import {buildTestingTree, getProjectFile, setupHttpHooks} from './utils.js'; +import {buildTestingTree, setupHttpHooks} from './utils.js'; describe('@puppeteer/ng-schematics: test', () => { setupHttpHooks(); @@ -9,10 +9,8 @@ describe('@puppeteer/ng-schematics: test', () => { const tree = await buildTestingTree('test', { name: 'myTest', }); - expect(tree.files).toContain(getProjectFile('e2e/tests/my-test.e2e.ts')); - expect(tree.files).not.toContain( - getProjectFile('e2e/tests/my-test.test.ts') - ); + expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.files).not.toContain('/e2e/tests/my-test.test.ts'); }); it('should create Node file', async () => { @@ -20,9 +18,7 @@ describe('@puppeteer/ng-schematics: test', () => { name: 'myTest', testingFramework: 'node', }); - expect(tree.files).not.toContain( - getProjectFile('e2e/tests/my-test.e2e.ts') - ); - expect(tree.files).toContain(getProjectFile('e2e/tests/my-test.test.ts')); + expect(tree.files).not.toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/my-test.test.ts'); }); }); diff --git a/packages/ng-schematics/test/src/utils.ts b/packages/ng-schematics/test/src/utils.ts index 03a82ab8d44..f382ac712ab 100644 --- a/packages/ng-schematics/test/src/utils.ts +++ b/packages/ng-schematics/test/src/utils.ts @@ -8,14 +8,11 @@ import { } from '@angular-devkit/schematics/testing'; import sinon from 'sinon'; -const WORKSPACE_OPTIONS = { - name: 'workspace', - newProjectRoot: 'projects', - version: '14.0.0', -}; - const APPLICATION_OPTIONS = { name: 'sandbox', + directory: '.', + createApplication: true, + version: '14.0.0', }; export function setupHttpHooks(): void { @@ -34,10 +31,6 @@ export function setupHttpHooks(): void { }); } -export function getProjectFile(file: string): string { - return `/${WORKSPACE_OPTIONS.newProjectRoot}/${APPLICATION_OPTIONS.name}/${file}`; -} - export function getAngularJsonScripts( tree: UnitTestTree, isDefault = true @@ -85,15 +78,8 @@ export async function buildTestingTree( // Build workspace workingTree = await runner.runExternalSchematic( '@schematics/angular', - 'workspace', - WORKSPACE_OPTIONS - ); - // Build dummy application - workingTree = await runner.runExternalSchematic( - '@schematics/angular', - 'application', - APPLICATION_OPTIONS, - workingTree + 'ng-new', + APPLICATION_OPTIONS ); if (command !== 'ng-add') {