11import { describe , expect , it , vi } from 'vitest' ;
22import { LocalCloakRuntimeProvider } from './provider.js' ;
33
4- function fakePage ( url : string ) {
4+ function fakePage ( url : string , initialViewport : { width : number ; height : number } | null = { width : 1280 , height : 720 } ) {
55 let closed = false ;
6- let viewportSize = { width : 1280 , height : 720 } ;
6+ let viewportSize = initialViewport ;
77 return {
88 isClosed : vi . fn ( ( ) => closed ) ,
99 goto : vi . fn ( async ( nextUrl : string ) => {
@@ -26,8 +26,9 @@ function fakePage(url: string) {
2626 } ;
2727}
2828
29- function makeProviderWithFakePage ( ) {
30- const pages = [ fakePage ( 'https://example.com/' ) ] ;
29+ function makeProviderWithFakePage ( initialViewport : { width : number ; height : number } | null = { width : 1280 , height : 720 } ) {
30+ const pages = [ fakePage ( 'https://example.com/' , initialViewport ) ] ;
31+ const cdpSession = { send : vi . fn ( ) . mockResolvedValue ( undefined ) , detach : vi . fn ( ) . mockResolvedValue ( undefined ) } ;
3132 const context = {
3233 on : vi . fn ( ) ,
3334 pages : vi . fn ( ( ) => pages . filter ( ( page ) => ! page . isClosed ( ) ) ) ,
@@ -36,14 +37,15 @@ function makeProviderWithFakePage() {
3637 pages . push ( page ) ;
3738 return page ;
3839 } ) ,
40+ newCDPSession : vi . fn ( ) . mockResolvedValue ( cdpSession ) ,
3941 cookies : vi . fn ( ) . mockResolvedValue ( [ { name : 'sid' , value : '1' , domain : 'example.com' , path : '/' } ] ) ,
4042 close : vi . fn ( ) . mockResolvedValue ( undefined ) ,
4143 } ;
4244 const provider = new LocalCloakRuntimeProvider ( {
4345 baseDir : '/tmp/webcmd-test' ,
4446 launchPersistentContext : vi . fn ( ) . mockResolvedValue ( context ) ,
4547 } ) ;
46- return { provider, page : pages [ 0 ] , pages, context } ;
48+ return { provider, page : pages [ 0 ] , pages, context, cdpSession } ;
4749}
4850
4951describe ( 'LocalCloakRuntimeProvider' , ( ) => {
@@ -173,6 +175,21 @@ describe('LocalCloakRuntimeProvider', () => {
173175 expect ( page . screenshot ) . toHaveBeenCalledTimes ( 1 ) ;
174176 } ) ;
175177
178+ it ( 'reversibly overrides via CDP and never pins the viewport when the context has no fixed viewport' , async ( ) => {
179+ const { provider, page, cdpSession } = makeProviderWithFakePage ( null ) ;
180+ const nav = await provider . dispatch ( { id : 'nav' , action : 'navigate' , session : 'work' , surface : 'browser' , url : 'https://example.com/' , profileId : 'default' } ) ;
181+
182+ await provider . dispatch ( { id : 'shot' , action : 'screenshot' , session : 'work' , surface : 'browser' , page : nav . page , format : 'png' , width : 375 , height : 812 , profileId : 'default' } ) ;
183+
184+ // The override must not permanently pin the real window via setViewportSize (#120).
185+ expect ( page . setViewportSize ) . not . toHaveBeenCalled ( ) ;
186+ expect ( cdpSession . send ) . toHaveBeenCalledWith ( 'Emulation.setDeviceMetricsOverride' , expect . objectContaining ( { width : 375 , height : 812 } ) ) ;
187+ // ...and it must be cleared afterward so the override is per-shot only.
188+ expect ( cdpSession . send ) . toHaveBeenCalledWith ( 'Emulation.clearDeviceMetricsOverride' ) ;
189+ expect ( cdpSession . detach ) . toHaveBeenCalledTimes ( 1 ) ;
190+ expect ( page . screenshot ) . toHaveBeenCalledTimes ( 1 ) ;
191+ } ) ;
192+
176193 it ( 'ignores screenshot height overrides for full-page captures while applying width' , async ( ) => {
177194 const { provider, page } = makeProviderWithFakePage ( ) ;
178195 const nav = await provider . dispatch ( { id : 'nav' , action : 'navigate' , session : 'work' , surface : 'browser' , url : 'https://example.com/' , profileId : 'default' } ) ;
0 commit comments