1- import { test , expect } from "@playwright/test" ;
1+ import { readFileSync } from "node:fs" ;
2+ import { expect , test } from "@playwright/test" ;
23
34/**
45 * Long-running room leak detector. Boots two peers, runs the generic
@@ -22,10 +23,19 @@ import { test, expect } from "@playwright/test";
2223const DURATION = Number ( process . env . MESH_LEAK_DURATION_MS ?? 60_000 ) ;
2324const BUDGET_MB = Number ( process . env . MESH_LEAK_BUDGET_MB ?? 15 ) ;
2425const NOISE_OPS = Number ( process . env . MESH_LEAK_NOISE_OPS ?? 200 ) ;
26+ const ENABLED = process . env . MESH_RUN_LEAK_TEST === "1" ;
27+ const pkg = JSON . parse ( readFileSync ( new URL ( "../../package.json" , import . meta. url ) , "utf8" ) ) as {
28+ name : string ;
29+ } ;
30+ const APP_NAME = pkg . name ;
2531
2632test ( "memory leak — heap growth stays under budget over a long-running room" , async ( {
2733 browser,
2834} ) => {
35+ // Keep the expensive detector opt-in. It is deliberately installed with
36+ // `test:e2e`, but only `npm run test:leak` enables its 60-second run.
37+ test . skip ( ! ENABLED , "run with `npm run test:leak`" ) ;
38+ test . setTimeout ( Math . max ( 30_000 , DURATION + 15_000 ) ) ;
2939 const ctx = await browser . newContext ( ) ;
3040 await ctx . addInitScript (
3141 ( { prefix, room } ) => {
@@ -35,14 +45,14 @@ test("memory leak — heap growth stays under budget over a long-running room",
3545 /* private mode */
3646 }
3747 } ,
38- { prefix : "mesh-caption-clash" , room : `leak-${ Date . now ( ) } ` } ,
48+ { prefix : APP_NAME , room : `leak-${ Date . now ( ) } ` } ,
3949 ) ;
4050
4151 const a = await ctx . newPage ( ) ;
4252 const b = await ctx . newPage ( ) ;
4353 await Promise . all ( [
44- a . goto ( "/mesh-caption-clash/" , { waitUntil : "domcontentloaded" } ) ,
45- b . goto ( "/mesh-caption-clash/" , { waitUntil : "domcontentloaded" } ) ,
54+ a . goto ( `/ ${ APP_NAME } /` , { waitUntil : "domcontentloaded" } ) ,
55+ b . goto ( `/ ${ APP_NAME } /` , { waitUntil : "domcontentloaded" } ) ,
4656 ] ) ;
4757
4858 // Settle the initial mount + first GC opportunity.
@@ -86,7 +96,7 @@ async function measureHeap(page: import("@playwright/test").Page): Promise<numbe
8696}
8797
8898async function clickAnything ( page : import ( "@playwright/test" ) . Page ) : Promise < void > {
89- const btn = page . locator ( "button:visible" ) . first ( ) ;
99+ const btn = page . locator ( "button:not([disabled]):not([aria-disabled='true']): visible" ) . first ( ) ;
90100 if ( ( await btn . count ( ) ) === 0 ) return ;
91101 await btn . click ( { trial : false , timeout : 2000 } ) . catch ( ( ) => undefined ) ;
92102}
0 commit comments