feat: support for multi projects repos (#10665)

This commit is contained in:
Nikolay Vitkov 2023-08-01 13:41:42 +02:00 committed by GitHub
parent f09077d3bc
commit 6bca1db956
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 77 additions and 68 deletions

View File

@ -1,3 +1,4 @@
# Sandbox
sandbox/
multi/

View File

@ -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',
});

View File

@ -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();

View File

@ -1,5 +1,5 @@
{
"extends": "../tsconfig.json",
"extends": "<%= tsConfigPath %>",
"compilerOptions": {<% if(testingFramework == 'jest') { %>
"esModuleInterop": true,<% } %><% if(testingFramework == 'node') { %>
"module": "CommonJS",

View File

@ -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<string, any>;
@ -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/'],
];
}

View File

@ -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,

View File

@ -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/'],
]);
});

View File

@ -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');
});
});

View File

@ -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') {