-
Notifications
You must be signed in to change notification settings - Fork 320
Open
Labels
Description
Environment
| Component | Version |
|---|---|
| Node.js | v.20.11.1 |
| Client (Chrome/Chromium/...) | Chrome v.125 |
| OS running Node.js | MacOS Sonoma 14.4.1 |
| OS running the client | Also MacOS |
| chrome-remote-interface | 0.33.0 |
Is the client running in a container? YES
Description
Trying to use CDP to grab heap snapshots with Cypress.
Cypress fails to run the CDP init function:

Example
cypress.config.ts
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname, {
bundler: 'vite',
}),
baseUrl: 'http://localhost:3000',
setupNodeEvents(on, config) {
const { setRdpPortWhenBrowserLaunch, initCDPClient, takeHeapSnapshot } = cdpPlugin();
on('before:browser:launch', (_, launchOptionsOrArgs) => {
setRdpPortWhenBrowserLaunch(launchOptionsOrArgs);
});
on('task', {
takeHeapSnapshot: async (opts) => {
console.log('task: snapshot');
console.log('init check');
await initCDPClient();
console.log('snapshot');
await takeHeapSnapshot(opts);
return null;
},
});
return config;
},
},
});cdpPlugin
import CDP from 'chrome-remote-interface';
import fs from 'fs';
export interface TakeHeapSnapshotType {
filePath: string;
beforeTakeCallback?: () => void;
afterTakeCallback?: () => void;
}
let port = 0;
let client: CDP.Client | null = null;
const setRdpPortWhenBrowserLaunch = (launchOptionsOrArgs: Cypress.BrowserLaunchOptions) => {
const args = Array.isArray(launchOptionsOrArgs) ? launchOptionsOrArgs : launchOptionsOrArgs.args;
const ensureRdpPort = (args: string[] | (Cypress.BrowserLaunchOptions & any[])) => {
const existing = args.find((arg) => arg.slice(0, 23) === '--remote-debugging-port');
if (existing) {
return Number(existing.split('=')[1]);
}
const port = 40000 + Math.round(Math.random() * 25000);
args.push(`--remote-debugging-port=${port}`);
return port;
};
port = ensureRdpPort(args);
console.log('Ensure remote debugging port %d', port);
};
const initCDPClient = async () => {
if (!port) {
throw new Error('Please set the remote debugging port first!');
}
if (!client) {
console.log('generating client, port:', port);
client = await CDP({
port,
});
console.log('client', client);
}
};
const takeHeapSnapshot = async (opts: TakeHeapSnapshotType) => {
console.log('start take snapshot');
if (!client) {
console.warn('client not init');
throw new Error('Please init the cdp client first!');
}
const { filePath, beforeTakeCallback = null, afterTakeCallback = null } = opts;
if (beforeTakeCallback) {
beforeTakeCallback();
}
const writeStream = fs.createWriteStream(filePath, { encoding: 'utf-8' });
const dataHandler = (data: { chunk: string }) => {
writeStream.write(data.chunk);
};
const progressHander = (data: { done: number; total: number; finished: boolean }) => {
const percent = ((100 * data.done) / data.total) | 0;
console.log(`heap snapshot ${percent}% complete`);
};
client.on('HeapProfiler.addHeapSnapshotChunk', dataHandler);
client.on('HeapProfiler.reportHeapSnapshotProgress', progressHander as SafeAny);
await client.send('HeapProfiler.takeHeapSnapshot', {
reportProgress: true,
captureNumericValue: true,
});
writeStream.end();
if (afterTakeCallback) {
afterTakeCallback();
}
};
export const cdpPlugin = () => {
return {
setRdpPortWhenBrowserLaunch,
initCDPClient,
takeHeapSnapshot,
};
};Cypress test
describe('MemLab Test', () => {
it('should take a snapshot', () => {
cy.task('takeHeapSnapshot', {
filePath: path.join(__dirname, './snapshots/s1.heapsnapshot'),
});
});
});