fix(angular): fix e2e tests to support pnpm v7 (#15587)
This commit is contained in:
parent
10a69b7d0f
commit
c6904619aa
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
|
killPort,
|
||||||
newProject,
|
newProject,
|
||||||
promisifiedTreeKill,
|
promisifiedTreeKill,
|
||||||
readProjectConfig,
|
readProjectConfig,
|
||||||
@ -15,9 +16,17 @@ import { names } from '@nrwl/devkit';
|
|||||||
|
|
||||||
describe('Angular Projects', () => {
|
describe('Angular Projects', () => {
|
||||||
let proj: string;
|
let proj: string;
|
||||||
|
let oldValue;
|
||||||
|
|
||||||
beforeAll(() => (proj = newProject()));
|
beforeAll(() => {
|
||||||
afterAll(() => cleanupProject());
|
proj = newProject();
|
||||||
|
oldValue = process.env.NX_E2E_VERBOSE_LOGGING;
|
||||||
|
process.env.NX_E2E_VERBOSE_LOGGING = 'true';
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
cleanupProject();
|
||||||
|
process.env.NX_E2E_VERBOSE_LOGGING = oldValue;
|
||||||
|
});
|
||||||
|
|
||||||
it('should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
|
it('should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
|
||||||
// ACT + ASSERT
|
// ACT + ASSERT
|
||||||
@ -135,6 +144,8 @@ describe('Angular Projects', () => {
|
|||||||
if (process && process.pid) {
|
if (process && process.pid) {
|
||||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||||
}
|
}
|
||||||
|
await killPort(port1);
|
||||||
|
await killPort(port2);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeFalsy();
|
expect(err).toBeFalsy();
|
||||||
}
|
}
|
||||||
@ -168,7 +179,11 @@ describe('Angular Projects', () => {
|
|||||||
`generate @nrwl/angular:remote ${remoteApp1} --ssr --no-interactive`
|
`generate @nrwl/angular:remote ${remoteApp1} --ssr --no-interactive`
|
||||||
);
|
);
|
||||||
|
|
||||||
let process = await runCommandUntil(`serve-ssr ${remoteApp1}`, (output) => {
|
const port = 4301;
|
||||||
|
|
||||||
|
let process = await runCommandUntil(
|
||||||
|
`serve-ssr ${remoteApp1} --port=${port}`,
|
||||||
|
(output) => {
|
||||||
return (
|
return (
|
||||||
output.includes(`Browser application bundle generation complete.`) &&
|
output.includes(`Browser application bundle generation complete.`) &&
|
||||||
output.includes(`Server application bundle generation complete.`) &&
|
output.includes(`Server application bundle generation complete.`) &&
|
||||||
@ -176,13 +191,15 @@ describe('Angular Projects', () => {
|
|||||||
`Angular Universal Live Development Server is listening`
|
`Angular Universal Live Development Server is listening`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// port and process cleanup
|
// port and process cleanup
|
||||||
try {
|
try {
|
||||||
if (process && process.pid) {
|
if (process && process.pid) {
|
||||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||||
}
|
}
|
||||||
|
await killPort(port);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeFalsy();
|
expect(err).toBeFalsy();
|
||||||
}
|
}
|
||||||
@ -204,7 +221,11 @@ describe('Angular Projects', () => {
|
|||||||
const remoteApp2Port =
|
const remoteApp2Port =
|
||||||
readProjectConfig(remoteApp2).targets.serve.options.port;
|
readProjectConfig(remoteApp2).targets.serve.options.port;
|
||||||
|
|
||||||
let process = await runCommandUntil(`serve-ssr ${hostApp}`, (output) => {
|
const port = 4401;
|
||||||
|
|
||||||
|
let process = await runCommandUntil(
|
||||||
|
`serve-ssr ${hostApp} --port=${port}`,
|
||||||
|
(output) => {
|
||||||
return (
|
return (
|
||||||
output.includes(
|
output.includes(
|
||||||
`Node Express server listening on http://localhost:${remoteApp1Port}`
|
`Node Express server listening on http://localhost:${remoteApp1Port}`
|
||||||
@ -216,13 +237,17 @@ describe('Angular Projects', () => {
|
|||||||
`Angular Universal Live Development Server is listening`
|
`Angular Universal Live Development Server is listening`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// port and process cleanup
|
// port and process cleanup
|
||||||
try {
|
try {
|
||||||
if (process && process.pid) {
|
if (process && process.pid) {
|
||||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||||
}
|
}
|
||||||
|
await killPort(port);
|
||||||
|
await killPort(remoteApp1Port);
|
||||||
|
await killPort(remoteApp2Port);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeFalsy();
|
expect(err).toBeFalsy();
|
||||||
}
|
}
|
||||||
@ -240,18 +265,24 @@ describe('Angular Projects', () => {
|
|||||||
return project;
|
return project;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const port = 4501;
|
||||||
|
|
||||||
// ACT
|
// ACT
|
||||||
let process = await runCommandUntil(`serve-ssr ${ssrApp}`, (output) => {
|
let process = await runCommandUntil(
|
||||||
|
`serve-ssr ${ssrApp} --port=${port}`,
|
||||||
|
(output) => {
|
||||||
return output.includes(
|
return output.includes(
|
||||||
`Angular Universal Live Development Server is listening on http://localhost:4200`
|
`Angular Universal Live Development Server is listening on http://localhost:${port}`
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// port and process cleanup
|
// port and process cleanup
|
||||||
try {
|
try {
|
||||||
if (process && process.pid) {
|
if (process && process.pid) {
|
||||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||||
}
|
}
|
||||||
|
await killPort(port);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeFalsy();
|
expect(err).toBeFalsy();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,13 +11,10 @@ import {
|
|||||||
import { TargetConfiguration } from '@nrwl/devkit';
|
import { TargetConfiguration } from '@nrwl/devkit';
|
||||||
import { ChildProcess, exec, execSync, ExecSyncOptions } from 'child_process';
|
import { ChildProcess, exec, execSync, ExecSyncOptions } from 'child_process';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { check as portCheck } from 'tcp-port-used';
|
|
||||||
import * as isCI from 'is-ci';
|
import * as isCI from 'is-ci';
|
||||||
import { Workspaces } from '../../packages/nx/src/config/workspaces';
|
import { Workspaces } from '../../packages/nx/src/config/workspaces';
|
||||||
import { updateFile } from './file-utils';
|
import { updateFile } from './file-utils';
|
||||||
import { logError, logInfo, logSuccess, stripConsoleColors } from './log-utils';
|
import { logError, stripConsoleColors } from './log-utils';
|
||||||
|
|
||||||
export const kill = require('kill-port');
|
|
||||||
|
|
||||||
export interface RunCmdOpts {
|
export interface RunCmdOpts {
|
||||||
silenceError?: boolean;
|
silenceError?: boolean;
|
||||||
@ -243,6 +240,15 @@ export function runCommandUntil(
|
|||||||
p.stderr?.on('data', checkCriteria);
|
p.stderr?.on('data', checkCriteria);
|
||||||
p.on('exit', (code) => {
|
p.on('exit', (code) => {
|
||||||
if (!complete) {
|
if (!complete) {
|
||||||
|
if (isVerboseE2ERun()) {
|
||||||
|
logError(
|
||||||
|
`Original output:`,
|
||||||
|
output
|
||||||
|
.split('\n')
|
||||||
|
.map((l) => ` ${l}`)
|
||||||
|
.join('\n')
|
||||||
|
);
|
||||||
|
}
|
||||||
rej(`Exited with ${code}`);
|
rej(`Exited with ${code}`);
|
||||||
} else {
|
} else {
|
||||||
res(p);
|
res(p);
|
||||||
@ -398,37 +404,6 @@ export function runLernaCLI(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const KILL_PORT_DELAY = 5000;
|
|
||||||
|
|
||||||
export async function killPort(port: number): Promise<boolean> {
|
|
||||||
if (await portCheck(port)) {
|
|
||||||
try {
|
|
||||||
logInfo(`Attempting to close port ${port}`);
|
|
||||||
await kill(port);
|
|
||||||
await new Promise<void>((resolve) =>
|
|
||||||
setTimeout(() => resolve(), KILL_PORT_DELAY)
|
|
||||||
);
|
|
||||||
if (await portCheck(port)) {
|
|
||||||
logError(`Port ${port} still open`);
|
|
||||||
} else {
|
|
||||||
logSuccess(`Port ${port} successfully closed`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
logError(`Port ${port} closing failed`);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function killPorts(port?: number): Promise<boolean> {
|
|
||||||
return port
|
|
||||||
? await killPort(port)
|
|
||||||
: (await killPort(3333)) && (await killPort(4200));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function waitUntil(
|
export function waitUntil(
|
||||||
predicate: () => boolean,
|
predicate: () => boolean,
|
||||||
opts: { timeout: number; ms: number; allowError?: boolean } = {
|
opts: { timeout: number; ms: number; allowError?: boolean } = {
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export function newProject({
|
|||||||
packageInstall(packages.join(` `), projScope);
|
packageInstall(packages.join(` `), projScope);
|
||||||
|
|
||||||
// stop the daemon
|
// stop the daemon
|
||||||
execSync('nx reset', {
|
execSync(`${getPackageManagerCommand().runNx} reset`, {
|
||||||
cwd: `${e2eCwd}/proj`,
|
cwd: `${e2eCwd}/proj`,
|
||||||
stdio: isVerbose() ? 'inherit' : 'pipe',
|
stdio: isVerbose() ? 'inherit' : 'pipe',
|
||||||
});
|
});
|
||||||
@ -94,6 +94,14 @@ export function newProject({
|
|||||||
if (isVerbose()) {
|
if (isVerbose()) {
|
||||||
logInfo(`NX`, `E2E created a project: ${tmpProjPath()}`);
|
logInfo(`NX`, `E2E created a project: ${tmpProjPath()}`);
|
||||||
}
|
}
|
||||||
|
if (packageManager === 'pnpm') {
|
||||||
|
execSync(getPackageManagerCommand().install, {
|
||||||
|
cwd: tmpProjPath(),
|
||||||
|
stdio: 'pipe',
|
||||||
|
env: { CI: 'true', ...process.env },
|
||||||
|
encoding: 'utf-8',
|
||||||
|
});
|
||||||
|
}
|
||||||
return projScope;
|
return projScope;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError(`Failed to set up project for e2e tests.`, e.message);
|
logError(`Failed to set up project for e2e tests.`, e.message);
|
||||||
@ -101,6 +109,14 @@ export function newProject({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pnpm v7 sadly doesn't automatically install peer dependencies
|
||||||
|
export function addPnpmRc() {
|
||||||
|
updateFile(
|
||||||
|
'.npmrc',
|
||||||
|
'strict-peer-dependencies=false\nauto-install-peers=true'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function runCreateWorkspace(
|
export function runCreateWorkspace(
|
||||||
name: string,
|
name: string,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import {
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { e2eCwd } from './get-env-info';
|
import { e2eCwd } from './get-env-info';
|
||||||
import { tmpProjPath } from './create-project-utils';
|
import { tmpProjPath } from './create-project-utils';
|
||||||
import { promisify } from 'util';
|
|
||||||
import * as treeKill from 'tree-kill';
|
|
||||||
|
|
||||||
export function createFile(f: string, content: string = ''): void {
|
export function createFile(f: string, content: string = ''): void {
|
||||||
const path = tmpProjPath(f);
|
const path = tmpProjPath(f);
|
||||||
@ -121,8 +119,3 @@ export function getSize(filePath: string): number {
|
|||||||
export function tmpBackupProjPath(path?: string) {
|
export function tmpBackupProjPath(path?: string) {
|
||||||
return path ? `${e2eCwd}/proj-backup/${path}` : `${e2eCwd}/proj-backup`;
|
return path ? `${e2eCwd}/proj-backup/${path}` : `${e2eCwd}/proj-backup`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const promisifiedTreeKill: (
|
|
||||||
pid: number,
|
|
||||||
signal: string
|
|
||||||
) => Promise<void> = promisify(treeKill);
|
|
||||||
|
|||||||
@ -10,3 +10,4 @@ export * from './get-env-info';
|
|||||||
export * from './log-utils';
|
export * from './log-utils';
|
||||||
export * from './project-config-utils';
|
export * from './project-config-utils';
|
||||||
export * from './test-utils';
|
export * from './test-utils';
|
||||||
|
export * from './process-utils';
|
||||||
|
|||||||
41
e2e/utils/process-utils.ts
Normal file
41
e2e/utils/process-utils.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { promisify } from 'util';
|
||||||
|
import * as treeKill from 'tree-kill';
|
||||||
|
import { logError, logInfo, logSuccess } from './log-utils';
|
||||||
|
import { check as portCheck } from 'tcp-port-used';
|
||||||
|
|
||||||
|
export const kill = require('kill-port');
|
||||||
|
const KILL_PORT_DELAY = 5000;
|
||||||
|
|
||||||
|
export const promisifiedTreeKill: (
|
||||||
|
pid: number,
|
||||||
|
signal: string
|
||||||
|
) => Promise<void> = promisify(treeKill);
|
||||||
|
|
||||||
|
export async function killPort(port: number): Promise<boolean> {
|
||||||
|
if (await portCheck(port)) {
|
||||||
|
try {
|
||||||
|
logInfo(`Attempting to close port ${port}`);
|
||||||
|
await kill(port);
|
||||||
|
await new Promise<void>((resolve) =>
|
||||||
|
setTimeout(() => resolve(), KILL_PORT_DELAY)
|
||||||
|
);
|
||||||
|
if (await portCheck(port)) {
|
||||||
|
logError(`Port ${port} still open`);
|
||||||
|
} else {
|
||||||
|
logSuccess(`Port ${port} successfully closed`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
logError(`Port ${port} closing failed`);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function killPorts(port?: number): Promise<boolean> {
|
||||||
|
return port
|
||||||
|
? await killPort(port)
|
||||||
|
: (await killPort(3333)) && (await killPort(4200));
|
||||||
|
}
|
||||||
@ -124,7 +124,8 @@ function run(): void {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
export * from './bootstrap.server';"
|
export * from './bootstrap.server';
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Host App Generator --ssr should generate the correct files 5`] = `"import('./src/main.server');"`;
|
exports[`Host App Generator --ssr should generate the correct files 5`] = `"import('./src/main.server');"`;
|
||||||
|
|||||||
@ -13,6 +13,8 @@ import {
|
|||||||
corsVersion,
|
corsVersion,
|
||||||
expressVersion,
|
expressVersion,
|
||||||
moduleFederationNodeVersion,
|
moduleFederationNodeVersion,
|
||||||
|
typesCorsVersion,
|
||||||
|
typesExpressVersion,
|
||||||
} from '../../../utils/versions';
|
} from '../../../utils/versions';
|
||||||
|
|
||||||
export async function addSsr(tree: Tree, options: Schema, appName: string) {
|
export async function addSsr(tree: Tree, options: Schema, appName: string) {
|
||||||
@ -65,7 +67,10 @@ export async function addSsr(tree: Tree, options: Schema, appName: string) {
|
|||||||
express: expressVersion,
|
express: expressVersion,
|
||||||
'@module-federation/node': moduleFederationNodeVersion,
|
'@module-federation/node': moduleFederationNodeVersion,
|
||||||
},
|
},
|
||||||
{}
|
{
|
||||||
|
'@types/cors': typesCorsVersion,
|
||||||
|
'@types/express': typesExpressVersion,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return installTask;
|
return installTask;
|
||||||
|
|||||||
@ -120,7 +120,8 @@ function run(): void {
|
|||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
export * from './bootstrap.server';"
|
export * from './bootstrap.server';
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`MF Remote App Generator --ssr should generate the correct files 5`] = `"import('./src/main.server');"`;
|
exports[`MF Remote App Generator --ssr should generate the correct files 5`] = `"import('./src/main.server');"`;
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import {
|
|||||||
corsVersion,
|
corsVersion,
|
||||||
expressVersion,
|
expressVersion,
|
||||||
moduleFederationNodeVersion,
|
moduleFederationNodeVersion,
|
||||||
|
typesCorsVersion,
|
||||||
|
typesExpressVersion,
|
||||||
} from '../../../utils/versions';
|
} from '../../../utils/versions';
|
||||||
|
|
||||||
export async function addSsr(
|
export async function addSsr(
|
||||||
@ -70,7 +72,10 @@ export async function addSsr(
|
|||||||
express: expressVersion,
|
express: expressVersion,
|
||||||
'@module-federation/node': moduleFederationNodeVersion,
|
'@module-federation/node': moduleFederationNodeVersion,
|
||||||
},
|
},
|
||||||
{}
|
{
|
||||||
|
'@types/cors': typesCorsVersion,
|
||||||
|
'@types/express': typesExpressVersion,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return installTask;
|
return installTask;
|
||||||
|
|||||||
@ -22,7 +22,9 @@ export const backwardCompatibleVersions: Record<
|
|||||||
tsLibVersion: '^2.3.0',
|
tsLibVersion: '^2.3.0',
|
||||||
ngUniversalVersion: '~14.2.0',
|
ngUniversalVersion: '~14.2.0',
|
||||||
corsVersion: '~2.8.5',
|
corsVersion: '~2.8.5',
|
||||||
|
typesCorsVersion: '~2.8.5',
|
||||||
expressVersion: '~4.18.2',
|
expressVersion: '~4.18.2',
|
||||||
|
typesExpressVersion: '4.17.14',
|
||||||
moduleFederationNodeVersion: '^0.10.1',
|
moduleFederationNodeVersion: '^0.10.1',
|
||||||
angularEslintVersion: '~14.0.4',
|
angularEslintVersion: '~14.0.4',
|
||||||
tailwindVersion: '^3.0.2',
|
tailwindVersion: '^3.0.2',
|
||||||
|
|||||||
@ -11,7 +11,9 @@ export const tsLibVersion = '^2.3.0';
|
|||||||
|
|
||||||
export const ngUniversalVersion = '~15.1.0';
|
export const ngUniversalVersion = '~15.1.0';
|
||||||
export const corsVersion = '~2.8.5';
|
export const corsVersion = '~2.8.5';
|
||||||
|
export const typesCorsVersion = '~2.8.5';
|
||||||
export const expressVersion = '~4.18.2';
|
export const expressVersion = '~4.18.2';
|
||||||
|
export const typesExpressVersion = '4.17.14';
|
||||||
export const moduleFederationNodeVersion = '~0.10.1';
|
export const moduleFederationNodeVersion = '~0.10.1';
|
||||||
|
|
||||||
export const angularEslintVersion = '~15.0.0';
|
export const angularEslintVersion = '~15.0.0';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user