@@ -35,6 +35,7 @@ import snapshotCommand, {
3535 computeSnapshotTimes ,
3636 formatSnapshotTimestamp ,
3737 parseZoomScale ,
38+ recaptureSnapshotComposite ,
3839 requireSnapshotFfmpeg ,
3940 resolveSnapshotVideoClipStart ,
4041 resolveSnapshotVideoFrameTime ,
@@ -517,3 +518,56 @@ describe("requireSnapshotFfmpeg", () => {
517518 expect ( requireSnapshotFfmpeg ( "C:\\tools\\ffmpeg.exe" ) ) . toBe ( "C:\\tools\\ffmpeg.exe" ) ;
518519 } ) ;
519520} ) ;
521+
522+ describe ( "snapshot composite recapture" , ( ) => {
523+ it . each ( [ false , true ] ) ( "recaptures only when a resolver exists: %s" , async ( hasResolver ) => {
524+ const order : string [ ] = [ ] ;
525+ const runtimeWindow = {
526+ __hf_page_composite_prepare : vi . fn ( async ( ) => {
527+ order . push ( "prepare" ) ;
528+ return true ;
529+ } ) ,
530+ __hf_page_composite_resolve : hasResolver
531+ ? vi . fn ( ( ) => {
532+ order . push ( "resolve" ) ;
533+ return true ;
534+ } )
535+ : undefined ,
536+ } ;
537+ vi . stubGlobal ( "window" , runtimeWindow ) ;
538+ try {
539+ await recaptureSnapshotComposite ( {
540+ async evaluate < T > ( callback : ( ) => T ) : Promise < Awaited < T > > {
541+ return await callback ( ) ;
542+ } ,
543+ async screenshot ( options ) {
544+ expect ( options ) . toEqual ( {
545+ type : "jpeg" ,
546+ quality : 1 ,
547+ clip : { x : 0 , y : 0 , width : 1 , height : 1 } ,
548+ } ) ;
549+ order . push ( "paint" ) ;
550+ return new Uint8Array ( ) ;
551+ } ,
552+ } ) ;
553+ expect ( order ) . toEqual ( hasResolver ? [ "prepare" , "paint" , "resolve" ] : [ ] ) ;
554+ } finally {
555+ vi . unstubAllGlobals ( ) ;
556+ }
557+ } ) ;
558+
559+ it ( "places recapture after frame injection and visibility sync, before final capture" , ( ) => {
560+ const source = readFileSync ( new URL ( "./snapshot.ts" , import . meta. url ) , "utf8" ) ;
561+ const injection = source . indexOf ( "await injectVideoFramesBatch(page, updates)" ) ;
562+ const visibility = source . indexOf ( "await syncVideoFrameVisibility(" , injection ) ;
563+ const recapture = source . indexOf ( "await recaptureSnapshotComposite(page)" , visibility ) ;
564+ const finalCapture = source . indexOf (
565+ 'page.screenshot({ path: framePath, type: "png"' ,
566+ recapture ,
567+ ) ;
568+ expect ( injection ) . toBeGreaterThan ( - 1 ) ;
569+ expect ( visibility ) . toBeGreaterThan ( injection ) ;
570+ expect ( recapture ) . toBeGreaterThan ( visibility ) ;
571+ expect ( finalCapture ) . toBeGreaterThan ( recapture ) ;
572+ } ) ;
573+ } ) ;
0 commit comments