chore(node): decrease e2e times (#20666)
This commit is contained in:
parent
5a305d41de
commit
4ec134f9d1
@ -6,20 +6,21 @@ import {
|
||||
promisifiedTreeKill,
|
||||
readFile,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
runCommandUntil,
|
||||
setMaxWorkers,
|
||||
tmpProjPath,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from '@nx/e2e/utils';
|
||||
import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Node Applications + esbuild', () => {
|
||||
beforeEach(() => newProject());
|
||||
beforeAll(() =>
|
||||
newProject({
|
||||
packages: ['@nx/node'],
|
||||
})
|
||||
);
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate an app using esbuild', async () => {
|
||||
const app = uniq('nodeapp');
|
||||
|
||||
@ -17,11 +17,13 @@ import { join } from 'path';
|
||||
|
||||
describe('Node Applications + webpack', () => {
|
||||
let proj: string;
|
||||
beforeEach(() => {
|
||||
proj = newProject();
|
||||
beforeAll(() => {
|
||||
proj = newProject({
|
||||
packages: ['@nx/node'],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
function addLibImport(appName: string, libName: string, importPath?: string) {
|
||||
const content = readFile(`apps/${appName}/src/main.ts`);
|
||||
|
||||
@ -17,9 +17,13 @@ import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Node Applications + webpack', () => {
|
||||
beforeEach(() => newProject());
|
||||
beforeAll(() =>
|
||||
newProject({
|
||||
packages: ['@nx/node'],
|
||||
})
|
||||
);
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate an app using webpack', async () => {
|
||||
const app = uniq('nodeapp');
|
||||
|
||||
@ -50,9 +50,13 @@ function getData(port, path = '/api'): Promise<any> {
|
||||
}
|
||||
|
||||
describe('Node Applications', () => {
|
||||
beforeEach(() => newProject());
|
||||
beforeAll(() =>
|
||||
newProject({
|
||||
packages: ['@nx/node', '@nx/express', '@nx/nest'],
|
||||
})
|
||||
);
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should be able to generate an empty application', async () => {
|
||||
const nodeapp = uniq('nodeapp');
|
||||
@ -331,12 +335,16 @@ describe('Node Applications', () => {
|
||||
});
|
||||
|
||||
describe('Build Node apps', () => {
|
||||
beforeEach(() => newProject());
|
||||
let scope: string;
|
||||
beforeAll(() => {
|
||||
scope = newProject({
|
||||
packages: ['@nx/node', '@nx/express', '@nx/nest'],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => cleanupProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate a package.json with the `--generatePackageJson` flag', async () => {
|
||||
const scope = newProject();
|
||||
const packageManager = detectPackageManager(tmpProjPath());
|
||||
const nestapp = uniq('nestapp');
|
||||
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
|
||||
@ -523,7 +531,6 @@ ${jslib}();
|
||||
|
||||
describe('NestJS', () => {
|
||||
it('should have plugin output if specified in `tsPlugins`', async () => {
|
||||
newProject();
|
||||
const nestapp = uniq('nestapp');
|
||||
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
|
||||
setMaxWorkers(join('apps', nestapp, 'project.json'));
|
||||
@ -576,99 +583,95 @@ ${jslib}();
|
||||
expect(mainJs).toContain('_OPENAPI_METADATA_FACTORY');
|
||||
}, 300000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nest libraries', function () {
|
||||
beforeEach(() => newProject());
|
||||
describe('nest libraries', function () {
|
||||
it('should be able to generate a nest library', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib}`);
|
||||
|
||||
it('should be able to generate a nest library', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib}`);
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
const testResults = runCLI(`test ${nestlib}`);
|
||||
expect(testResults).toContain(
|
||||
`Successfully ran target test for project ${nestlib}`
|
||||
);
|
||||
}, 60000);
|
||||
|
||||
const testResults = runCLI(`test ${nestlib}`);
|
||||
expect(testResults).toContain(
|
||||
`Successfully ran target test for project ${nestlib}`
|
||||
);
|
||||
}, 60000);
|
||||
it('should be able to generate a nest library w/ service', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
|
||||
it('should be able to generate a nest library w/ service', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --service`);
|
||||
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --service`);
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 1 passed, 1 total'
|
||||
);
|
||||
}, 200000);
|
||||
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 1 passed, 1 total'
|
||||
);
|
||||
}, 200000);
|
||||
it('should be able to generate a nest library w/ controller', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
|
||||
it('should be able to generate a nest library w/ controller', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --controller`);
|
||||
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --controller`);
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 1 passed, 1 total'
|
||||
);
|
||||
}, 200000);
|
||||
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 1 passed, 1 total'
|
||||
);
|
||||
}, 200000);
|
||||
it('should be able to generate a nest library w/ controller and service', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
|
||||
it('should be able to generate a nest library w/ controller and service', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --controller --service`);
|
||||
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --controller --service`);
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
|
||||
const lintResults = runCLI(`lint ${nestlib}`);
|
||||
expect(lintResults).toContain('All files pass linting.');
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 2 passed, 2 total'
|
||||
);
|
||||
}, 200000);
|
||||
|
||||
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||
expect(jestResult.combinedOutput).toContain(
|
||||
'Test Suites: 2 passed, 2 total'
|
||||
);
|
||||
}, 200000);
|
||||
it('should have plugin output if specified in `transformers`', async () => {
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --buildable`);
|
||||
|
||||
it('should have plugin output if specified in `transformers`', async () => {
|
||||
newProject();
|
||||
const nestlib = uniq('nestlib');
|
||||
runCLI(`generate @nx/nest:lib ${nestlib} --buildable`);
|
||||
packageInstall('@nestjs/swagger', undefined, '^7.0.0');
|
||||
|
||||
packageInstall('@nestjs/swagger', undefined, '^7.0.0');
|
||||
|
||||
updateJson(join('libs', nestlib, 'project.json'), (config) => {
|
||||
config.targets.build.options.transformers = [
|
||||
{
|
||||
name: '@nestjs/swagger/plugin',
|
||||
options: {
|
||||
dtoFileNameSuffix: ['.model.ts'],
|
||||
updateJson(join('libs', nestlib, 'project.json'), (config) => {
|
||||
config.targets.build.options.transformers = [
|
||||
{
|
||||
name: '@nestjs/swagger/plugin',
|
||||
options: {
|
||||
dtoFileNameSuffix: ['.model.ts'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
return config;
|
||||
});
|
||||
];
|
||||
return config;
|
||||
});
|
||||
|
||||
updateFile(
|
||||
`libs/${nestlib}/src/lib/foo.model.ts`,
|
||||
`
|
||||
updateFile(
|
||||
`libs/${nestlib}/src/lib/foo.model.ts`,
|
||||
`
|
||||
export class FooModel {
|
||||
foo?: string;
|
||||
bar?: number;
|
||||
}`
|
||||
);
|
||||
);
|
||||
|
||||
await runCLIAsync(`build ${nestlib}`);
|
||||
await runCLIAsync(`build ${nestlib}`);
|
||||
|
||||
const fooModelJs = readFile(`dist/libs/${nestlib}/src/lib/foo.model.js`);
|
||||
expect(stripIndents`${fooModelJs}`).toContain(
|
||||
stripIndents`
|
||||
const fooModelJs = readFile(`dist/libs/${nestlib}/src/lib/foo.model.js`);
|
||||
expect(stripIndents`${fooModelJs}`).toContain(
|
||||
stripIndents`
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FooModel = void 0;
|
||||
@ -681,10 +684,11 @@ class FooModel {
|
||||
exports.FooModel = FooModel;
|
||||
//# sourceMappingURL=foo.model.js.map
|
||||
`
|
||||
);
|
||||
}, 300000);
|
||||
);
|
||||
}, 300000);
|
||||
|
||||
it('should run default jest tests', async () => {
|
||||
await expectJestTestsToPass('@nx/node:lib');
|
||||
}, 100000);
|
||||
it('should run default jest tests', async () => {
|
||||
await expectJestTestsToPass('@nx/node:lib');
|
||||
}, 100000);
|
||||
});
|
||||
});
|
||||
|
||||
@ -21,6 +21,7 @@ import { angularCliVersion as defaultAngularCliVersion } from '@nx/workspace/src
|
||||
import { dump } from '@zkochan/js-yaml';
|
||||
import { execSync, ExecSyncOptions } from 'child_process';
|
||||
|
||||
import { performance, PerformanceMeasure } from 'perf_hooks';
|
||||
import { logError, logInfo } from './log-utils';
|
||||
import {
|
||||
getPackageManagerCommand,
|
||||
@ -28,13 +29,41 @@ import {
|
||||
RunCmdOpts,
|
||||
runCommand,
|
||||
} from './command-utils';
|
||||
import { NxJsonConfiguration, output } from '@nx/devkit';
|
||||
import { output } from '@nx/devkit';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { resetWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||
|
||||
let projName: string;
|
||||
|
||||
// TODO(jack): we should tag the projects (e.g. tags: ['package']) and filter from that rather than hard-code packages.
|
||||
const nxPackages = [
|
||||
`@nx/angular`,
|
||||
`@nx/eslint-plugin`,
|
||||
`@nx/express`,
|
||||
`@nx/esbuild`,
|
||||
`@nx/jest`,
|
||||
`@nx/js`,
|
||||
`@nx/eslint`,
|
||||
`@nx/nest`,
|
||||
`@nx/next`,
|
||||
`@nx/node`,
|
||||
`@nx/nuxt`,
|
||||
`@nx/plugin`,
|
||||
`@nx/playwright`,
|
||||
`@nx/rollup`,
|
||||
`@nx/react`,
|
||||
`@nx/storybook`,
|
||||
`@nx/vue`,
|
||||
`@nx/vite`,
|
||||
`@nx/web`,
|
||||
`@nx/webpack`,
|
||||
`@nx/react-native`,
|
||||
`@nx/expo`,
|
||||
] as const;
|
||||
|
||||
type NxPackage = typeof nxPackages[number];
|
||||
|
||||
/**
|
||||
* Sets up a new project in the temporary project path
|
||||
* for the currently selected CLI.
|
||||
@ -43,15 +72,34 @@ export function newProject({
|
||||
name = uniq('proj'),
|
||||
packageManager = getSelectedPackageManager(),
|
||||
unsetProjectNameAndRootFormat = true,
|
||||
packages,
|
||||
}: {
|
||||
name?: string;
|
||||
packageManager?: 'npm' | 'yarn' | 'pnpm';
|
||||
unsetProjectNameAndRootFormat?: boolean;
|
||||
readonly packages?: Array<NxPackage>;
|
||||
} = {}): string {
|
||||
const newProjectStart = performance.mark('new-project:start');
|
||||
try {
|
||||
const projScope = 'proj';
|
||||
|
||||
let createNxWorkspaceMeasure: PerformanceMeasure;
|
||||
let packageInstallMeasure: PerformanceMeasure;
|
||||
|
||||
if (!directoryExists(tmpBackupProjPath())) {
|
||||
const createNxWorkspaceStart = performance.mark(
|
||||
'create-nx-workspace:start'
|
||||
);
|
||||
runCreateWorkspace(projScope, {
|
||||
preset: 'apps',
|
||||
packageManager,
|
||||
});
|
||||
const createNxWorkspaceEnd = performance.mark('create-nx-workspace:end');
|
||||
createNxWorkspaceMeasure = performance.measure(
|
||||
'create-nx-workspace',
|
||||
createNxWorkspaceStart.name,
|
||||
createNxWorkspaceEnd.name
|
||||
);
|
||||
|
||||
if (unsetProjectNameAndRootFormat) {
|
||||
console.warn(
|
||||
@ -69,33 +117,19 @@ export function newProject({
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(jack): we should tag the projects (e.g. tags: ['package']) and filter from that rather than hard-code packages.
|
||||
const packages = [
|
||||
`@nx/angular`,
|
||||
`@nx/eslint-plugin`,
|
||||
`@nx/express`,
|
||||
`@nx/esbuild`,
|
||||
`@nx/jest`,
|
||||
`@nx/js`,
|
||||
`@nx/eslint`,
|
||||
`@nx/nest`,
|
||||
`@nx/next`,
|
||||
`@nx/node`,
|
||||
`@nx/nuxt`,
|
||||
`@nx/plugin`,
|
||||
`@nx/playwright`,
|
||||
`@nx/rollup`,
|
||||
`@nx/react`,
|
||||
`@nx/storybook`,
|
||||
`@nx/vue`,
|
||||
`@nx/vite`,
|
||||
`@nx/web`,
|
||||
`@nx/webpack`,
|
||||
`@nx/react-native`,
|
||||
`@nx/expo`,
|
||||
];
|
||||
packageInstall(packages.join(` `), projScope);
|
||||
|
||||
if (!packages) {
|
||||
console.warn(
|
||||
'ATTENTION: All packages are installed into the new workspace. To make this test faster, please pass the subset of packages that this test needs by passing a packages array in the options'
|
||||
);
|
||||
}
|
||||
const packageInstallStart = performance.mark('packageInstall:start');
|
||||
packageInstall((packages ?? nxPackages).join(` `), projScope);
|
||||
const packageInstallEnd = performance.mark('packageInstall:end');
|
||||
packageInstallMeasure = performance.measure(
|
||||
'packageInstall',
|
||||
packageInstallStart.name,
|
||||
packageInstallEnd.name
|
||||
);
|
||||
// stop the daemon
|
||||
execSync(`${getPackageManagerCommand().runNx} reset`, {
|
||||
cwd: `${e2eCwd}/proj`,
|
||||
@ -105,19 +139,55 @@ export function newProject({
|
||||
moveSync(`${e2eCwd}/proj`, `${tmpBackupProjPath()}`);
|
||||
}
|
||||
projName = name;
|
||||
copySync(`${tmpBackupProjPath()}`, `${tmpProjPath()}`);
|
||||
if (isVerbose()) {
|
||||
logInfo(`NX`, `E2E created a project: ${tmpProjPath()}`);
|
||||
}
|
||||
|
||||
const projectDirectory = tmpProjPath();
|
||||
copySync(`${tmpBackupProjPath()}`, `${projectDirectory}`);
|
||||
|
||||
// TODO: What is this for?
|
||||
if (packageManager === 'pnpm') {
|
||||
execSync(getPackageManagerCommand().install, {
|
||||
cwd: tmpProjPath(),
|
||||
cwd: projectDirectory,
|
||||
stdio: 'pipe',
|
||||
env: { CI: 'true', ...process.env },
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
|
||||
const newProjectEnd = performance.mark('new-project:end');
|
||||
const perfMeasure = performance.measure(
|
||||
'newProject',
|
||||
newProjectStart.name,
|
||||
newProjectEnd.name
|
||||
);
|
||||
|
||||
if (isVerbose()) {
|
||||
logInfo(
|
||||
`NX`,
|
||||
`E2E created a project: ${projectDirectory} in ${
|
||||
perfMeasure.duration / 1000
|
||||
} seconds
|
||||
${
|
||||
createNxWorkspaceMeasure
|
||||
? `create-nx-workspace: ${
|
||||
createNxWorkspaceMeasure.duration / 1000
|
||||
} seconds\n`
|
||||
: ''
|
||||
}${
|
||||
packageInstallMeasure
|
||||
? `packageInstall: ${
|
||||
packageInstallMeasure.duration / 1000
|
||||
} seconds\n`
|
||||
: ''
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
if (process.env.NX_E2E_EDITOR) {
|
||||
const editor = process.env.NX_E2E_EDITOR;
|
||||
execSync(`${editor} ${projectDirectory}`, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
}
|
||||
return projScope;
|
||||
} catch (e) {
|
||||
logError(`Failed to set up project for e2e tests.`, e.message);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user