fix: resolve workspace integration blockers (#5)
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const serverSpecs = [
|
||||
{ name: 'viewer-2d', args: ['run', 'dev:2d'] },
|
||||
{ name: 'viewer-3d', args: ['run', 'dev:3d'] },
|
||||
{
|
||||
name: 'viewer-3d-subpath',
|
||||
args: ['--workspace', '@hmwebviewer/viewer-3d', 'run', 'serve:subpath:e2e'],
|
||||
},
|
||||
];
|
||||
const servers = [];
|
||||
let stopping = false;
|
||||
|
||||
function stopServers() {
|
||||
if (stopping) return;
|
||||
stopping = true;
|
||||
for (const server of servers) {
|
||||
if (!server.pid) continue;
|
||||
try {
|
||||
// npm과 그 아래 Vite process를 같은 process group 단위로 종료합니다.
|
||||
process.kill(-server.pid, 'SIGTERM');
|
||||
} catch {
|
||||
// 이미 종료된 server는 별도 처리하지 않습니다.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startServer({ name, args }) {
|
||||
return new Promise((resolveReady, rejectReady) => {
|
||||
const child = spawn('npm', args, {
|
||||
cwd: projectRoot,
|
||||
detached: true,
|
||||
env: {
|
||||
...process.env,
|
||||
NO_PROXY: '127.0.0.1,localhost',
|
||||
no_proxy: '127.0.0.1,localhost',
|
||||
},
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
servers.push(child);
|
||||
|
||||
let ready = false;
|
||||
const timeout = setTimeout(() => {
|
||||
rejectReady(new Error(`${name} server가 90초 안에 준비되지 않았습니다.`));
|
||||
}, 90_000);
|
||||
|
||||
const inspect = (chunk) => {
|
||||
const output = chunk.toString();
|
||||
process.stderr.write(`[${name}] ${output}`);
|
||||
if (!ready && output.includes('Local:')) {
|
||||
ready = true;
|
||||
clearTimeout(timeout);
|
||||
resolveReady();
|
||||
}
|
||||
};
|
||||
child.stdout.on('data', inspect);
|
||||
child.stderr.on('data', inspect);
|
||||
child.once('exit', (code, signal) => {
|
||||
clearTimeout(timeout);
|
||||
if (!ready) {
|
||||
rejectReady(
|
||||
new Error(`${name} server가 준비 전에 종료됐습니다. code=${code} signal=${signal}`),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
process.once('SIGINT', () => {
|
||||
stopServers();
|
||||
process.exit(130);
|
||||
});
|
||||
process.once('SIGTERM', () => {
|
||||
stopServers();
|
||||
process.exit(143);
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(serverSpecs.map(startServer));
|
||||
|
||||
const playwright = spawn(
|
||||
resolve(projectRoot, 'node_modules/.bin/playwright'),
|
||||
['test', ...process.argv.slice(2)],
|
||||
{
|
||||
cwd: projectRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
E2E_SERVERS_READY: '1',
|
||||
NO_PROXY: '127.0.0.1,localhost',
|
||||
no_proxy: '127.0.0.1,localhost',
|
||||
},
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
const exitCode = await new Promise((resolveExit) => {
|
||||
playwright.once('exit', (code, signal) => {
|
||||
if (signal) resolveExit(1);
|
||||
else resolveExit(code ?? 1);
|
||||
});
|
||||
});
|
||||
process.exitCode = exitCode;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
stopServers();
|
||||
}
|
||||
Reference in New Issue
Block a user