feat: support for multi projects repos (#10665)
This commit is contained in:
parent
f09077d3bc
commit
6bca1db956
1
packages/ng-schematics/.gitignore
vendored
1
packages/ng-schematics/.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# Sandbox
|
# Sandbox
|
||||||
sandbox/
|
sandbox/
|
||||||
|
multi/
|
||||||
|
@ -32,28 +32,25 @@ function getExecutable(command: string[]) {
|
|||||||
const executable = command.shift()!;
|
const executable = command.shift()!;
|
||||||
const error = getError(executable, command);
|
const error = getError(executable, command);
|
||||||
|
|
||||||
if (executable === 'node') {
|
|
||||||
return {
|
|
||||||
executable: executable,
|
|
||||||
args: command,
|
|
||||||
error,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
executable: `./node_modules/.bin/${executable}`,
|
executable,
|
||||||
args: command,
|
args: command,
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function executeCommand(context: BuilderContext, command: string[]) {
|
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(' ')}.`);
|
context.logger.debug(`Trying to execute command - ${command.join(' ')}.`);
|
||||||
const {executable, args, error} = getExecutable(command);
|
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, {
|
const child = spawn(executable, args, {
|
||||||
cwd: context.workspaceRoot,
|
cwd: path,
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ describe('App test', function () {
|
|||||||
setupBrowserHooks();
|
setupBrowserHooks();
|
||||||
it('is running', async function () {
|
it('is running', async function () {
|
||||||
const {page} = getBrowserState();
|
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') { %>
|
<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
|
||||||
expect(element).not.toBeNull();
|
expect(element).not.toBeNull();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "<%= tsConfigPath %>",
|
||||||
"compilerOptions": {<% if(testingFramework == 'jest') { %>
|
"compilerOptions": {<% if(testingFramework == 'jest') { %>
|
||||||
"esModuleInterop": true,<% } %><% if(testingFramework == 'node') { %>
|
"esModuleInterop": true,<% } %><% if(testingFramework == 'node') { %>
|
||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
|
@ -29,7 +29,7 @@ import {
|
|||||||
url,
|
url,
|
||||||
} from '@angular-devkit/schematics';
|
} from '@angular-devkit/schematics';
|
||||||
|
|
||||||
import {SchematicsOptions, TestingFramework} from './types.js';
|
import {AngularProject, SchematicsOptions, TestingFramework} from './types.js';
|
||||||
|
|
||||||
export interface FilesOptions {
|
export interface FilesOptions {
|
||||||
projects: Record<string, any>;
|
projects: Record<string, any>;
|
||||||
@ -62,7 +62,7 @@ export function addFiles(
|
|||||||
): any {
|
): any {
|
||||||
return chain(
|
return chain(
|
||||||
Object.keys(projects).map(name => {
|
Object.keys(projects).map(name => {
|
||||||
const project = projects[name];
|
const project = projects[name] as AngularProject;
|
||||||
const projectPath = resolve(getSystemPath(normalize(project.root)));
|
const projectPath = resolve(getSystemPath(normalize(project.root)));
|
||||||
const workspacePath = resolve(getSystemPath(normalize('')));
|
const workspacePath = resolve(getSystemPath(normalize('')));
|
||||||
|
|
||||||
@ -72,6 +72,7 @@ export function addFiles(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const baseUrl = getProjectBaseUrl(project, options.port);
|
const baseUrl = getProjectBaseUrl(project, options.port);
|
||||||
|
const tsConfigPath = getTsConfigPath(project);
|
||||||
|
|
||||||
return mergeWith(
|
return mergeWith(
|
||||||
apply(url(applyPath), [
|
apply(url(applyPath), [
|
||||||
@ -87,6 +88,7 @@ export function addFiles(
|
|||||||
...strings,
|
...strings,
|
||||||
root: project.root ? `${project.root}/` : project.root,
|
root: project.root ? `${project.root}/` : project.root,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
tsConfigPath,
|
||||||
project: name,
|
project: name,
|
||||||
relativeToWorkspace,
|
relativeToWorkspace,
|
||||||
}),
|
}),
|
||||||
@ -109,6 +111,13 @@ function getProjectBaseUrl(project: any, port: number): string {
|
|||||||
return `${options.protocol}://${options.host}:${options.port}`;
|
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(
|
export function addBaseFiles(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
context: SchematicContext,
|
context: SchematicContext,
|
||||||
@ -144,17 +153,33 @@ export function addFrameworkFiles(
|
|||||||
return addFiles(tree, context, options);
|
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) {
|
switch (options.testingFramework) {
|
||||||
case TestingFramework.Jasmine:
|
case TestingFramework.Jasmine:
|
||||||
return [[`jasmine`, '--config=./e2e/support/jasmine.json']];
|
return [[`${path}/jasmine`, '--config=./e2e/support/jasmine.json']];
|
||||||
case TestingFramework.Jest:
|
case TestingFramework.Jest:
|
||||||
return [[`jest`, '-c', 'e2e/jest.config.js']];
|
return [[`${path}/jest`, '-c', 'e2e/jest.config.js']];
|
||||||
case TestingFramework.Mocha:
|
case TestingFramework.Mocha:
|
||||||
return [[`mocha`, '--config=./e2e/.mocharc.js']];
|
return [[`${path}/mocha`, '--config=./e2e/.mocharc.js']];
|
||||||
case TestingFramework.Node:
|
case TestingFramework.Node:
|
||||||
return [
|
return [
|
||||||
[`tsc`, '-p', 'e2e/tsconfig.json'],
|
[`${path}/tsc`, '-p', 'e2e/tsconfig.json'],
|
||||||
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -168,11 +168,14 @@ export function updateAngularJsonScripts(
|
|||||||
overwrite = true
|
overwrite = true
|
||||||
): Tree {
|
): Tree {
|
||||||
const angularJson = getAngularConfig(tree);
|
const angularJson = getAngularConfig(tree);
|
||||||
const commands = getScriptFromOptions(options);
|
|
||||||
const name = getNgCommandName(options);
|
const name = getNgCommandName(options);
|
||||||
const port = options.port !== 4200 ? Number(options.port) : undefined;
|
const port = options.port !== 4200 ? Number(options.port) : undefined;
|
||||||
|
|
||||||
Object.keys(angularJson['projects']).forEach(project => {
|
Object.keys(angularJson['projects']).forEach(project => {
|
||||||
|
const commands = getScriptFromOptions(
|
||||||
|
options,
|
||||||
|
angularJson['projects'][project]!.root
|
||||||
|
);
|
||||||
const e2eScript = [
|
const e2eScript = [
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
buildTestingTree,
|
buildTestingTree,
|
||||||
getAngularJsonScripts,
|
getAngularJsonScripts,
|
||||||
getPackageJson,
|
getPackageJson,
|
||||||
getProjectFile,
|
|
||||||
setupHttpHooks,
|
setupHttpHooks,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
|
|
||||||
@ -16,9 +15,9 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
const {devDependencies, scripts} = getPackageJson(tree);
|
const {devDependencies, scripts} = getPackageJson(tree);
|
||||||
const {builder, configurations} = getAngularJsonScripts(tree);
|
const {builder, configurations} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tsconfig.json'));
|
expect(tree.files).toContain('/e2e/tsconfig.json');
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tests/app.e2e.ts'));
|
expect(tree.files).toContain('/e2e/tests/app.e2e.ts');
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tests/utils.ts'));
|
expect(tree.files).toContain('/e2e/tests/utils.ts');
|
||||||
expect(devDependencies).toContain('puppeteer');
|
expect(devDependencies).toContain('puppeteer');
|
||||||
expect(scripts['e2e']).toBe('ng e2e');
|
expect(scripts['e2e']).toBe('ng e2e');
|
||||||
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
||||||
@ -45,7 +44,7 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
exportConfig: true,
|
exportConfig: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(files).toContain(getProjectFile('.puppeteerrc.cjs'));
|
expect(files).toContain('/.puppeteerrc.cjs');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not create Puppeteer config', async () => {
|
it('should not create Puppeteer config', async () => {
|
||||||
@ -53,7 +52,7 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
exportConfig: false,
|
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 () => {
|
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 {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/support/jasmine.json'));
|
expect(tree.files).toContain('/e2e/support/jasmine.json');
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/helpers/babel.js'));
|
expect(tree.files).toContain('/e2e/helpers/babel.js');
|
||||||
expect(devDependencies).toContain('jasmine');
|
expect(devDependencies).toContain('jasmine');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
expect(devDependencies).toContain('@babel/core');
|
||||||
expect(devDependencies).toContain('@babel/register');
|
expect(devDependencies).toContain('@babel/register');
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
expect(devDependencies).toContain('@babel/preset-typescript');
|
||||||
expect(options['commands']).toEqual([
|
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 {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(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('jest');
|
||||||
expect(devDependencies).toContain('@types/jest');
|
expect(devDependencies).toContain('@types/jest');
|
||||||
expect(devDependencies).toContain('ts-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 () => {
|
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 {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/.mocharc.js'));
|
expect(tree.files).toContain('/e2e/.mocharc.js');
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/babel.js'));
|
expect(tree.files).toContain('/e2e/babel.js');
|
||||||
expect(devDependencies).toContain('mocha');
|
expect(devDependencies).toContain('mocha');
|
||||||
expect(devDependencies).toContain('@types/mocha');
|
expect(devDependencies).toContain('@types/mocha');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
expect(devDependencies).toContain('@babel/core');
|
||||||
expect(devDependencies).toContain('@babel/register');
|
expect(devDependencies).toContain('@babel/register');
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
expect(devDependencies).toContain('@babel/preset-typescript');
|
||||||
expect(options['commands']).toEqual([
|
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);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/.gitignore'));
|
expect(tree.files).toContain('/e2e/.gitignore');
|
||||||
expect(tree.files).not.toContain(getProjectFile('e2e/tests/app.e2e.ts'));
|
expect(tree.files).not.toContain('/e2e/tests/app.e2e.ts');
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tests/app.test.ts'));
|
expect(tree.files).toContain('/e2e/tests/app.test.ts');
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`tsc`, '-p', 'e2e/tsconfig.json'],
|
[`./node_modules/.bin/tsc`, '-p', 'e2e/tsconfig.json'],
|
||||||
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
|
|
||||||
import {buildTestingTree, getProjectFile, setupHttpHooks} from './utils.js';
|
import {buildTestingTree, setupHttpHooks} from './utils.js';
|
||||||
|
|
||||||
describe('@puppeteer/ng-schematics: test', () => {
|
describe('@puppeteer/ng-schematics: test', () => {
|
||||||
setupHttpHooks();
|
setupHttpHooks();
|
||||||
@ -9,10 +9,8 @@ describe('@puppeteer/ng-schematics: test', () => {
|
|||||||
const tree = await buildTestingTree('test', {
|
const tree = await buildTestingTree('test', {
|
||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
});
|
});
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tests/my-test.e2e.ts'));
|
expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts');
|
||||||
expect(tree.files).not.toContain(
|
expect(tree.files).not.toContain('/e2e/tests/my-test.test.ts');
|
||||||
getProjectFile('e2e/tests/my-test.test.ts')
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create Node file', async () => {
|
it('should create Node file', async () => {
|
||||||
@ -20,9 +18,7 @@ describe('@puppeteer/ng-schematics: test', () => {
|
|||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
testingFramework: 'node',
|
testingFramework: 'node',
|
||||||
});
|
});
|
||||||
expect(tree.files).not.toContain(
|
expect(tree.files).not.toContain('/e2e/tests/my-test.e2e.ts');
|
||||||
getProjectFile('e2e/tests/my-test.e2e.ts')
|
expect(tree.files).toContain('/e2e/tests/my-test.test.ts');
|
||||||
);
|
|
||||||
expect(tree.files).toContain(getProjectFile('e2e/tests/my-test.test.ts'));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,14 +8,11 @@ import {
|
|||||||
} from '@angular-devkit/schematics/testing';
|
} from '@angular-devkit/schematics/testing';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
const WORKSPACE_OPTIONS = {
|
|
||||||
name: 'workspace',
|
|
||||||
newProjectRoot: 'projects',
|
|
||||||
version: '14.0.0',
|
|
||||||
};
|
|
||||||
|
|
||||||
const APPLICATION_OPTIONS = {
|
const APPLICATION_OPTIONS = {
|
||||||
name: 'sandbox',
|
name: 'sandbox',
|
||||||
|
directory: '.',
|
||||||
|
createApplication: true,
|
||||||
|
version: '14.0.0',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setupHttpHooks(): void {
|
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(
|
export function getAngularJsonScripts(
|
||||||
tree: UnitTestTree,
|
tree: UnitTestTree,
|
||||||
isDefault = true
|
isDefault = true
|
||||||
@ -85,15 +78,8 @@ export async function buildTestingTree(
|
|||||||
// Build workspace
|
// Build workspace
|
||||||
workingTree = await runner.runExternalSchematic(
|
workingTree = await runner.runExternalSchematic(
|
||||||
'@schematics/angular',
|
'@schematics/angular',
|
||||||
'workspace',
|
'ng-new',
|
||||||
WORKSPACE_OPTIONS
|
APPLICATION_OPTIONS
|
||||||
);
|
|
||||||
// Build dummy application
|
|
||||||
workingTree = await runner.runExternalSchematic(
|
|
||||||
'@schematics/angular',
|
|
||||||
'application',
|
|
||||||
APPLICATION_OPTIONS,
|
|
||||||
workingTree
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (command !== 'ng-add') {
|
if (command !== 'ng-add') {
|
||||||
|
Loading…
Reference in New Issue
Block a user