@@ -87,6 +87,14 @@ vi.mock("electron", () => ({
8787 } ,
8888 nativeImage : {
8989 createFromPath,
90+ createFromBuffer : ( buffer : Buffer ) => ( {
91+ getSize : ( ) => ( { width : buffer . length > 0 ? 1 : 0 , height : buffer . length > 0 ? 1 : 0 } ) ,
92+ toPNG : ( ) => buffer ,
93+ resize : ( ) => ( {
94+ getSize : ( ) => ( { width : 1 , height : 1 } ) ,
95+ toPNG : ( ) => buffer ,
96+ } ) ,
97+ } ) ,
9098 } ,
9199 shell : {
92100 showItemInFolder,
@@ -168,6 +176,7 @@ const makeTestPreviewWebContents = (
168176 getURL : ( ) => "https://example.com" ,
169177 getTitle : ( ) => "Example" ,
170178 isLoading : ( ) => false ,
179+ isDevToolsOpened : ( ) => false ,
171180 getZoomFactor : ( ) => 1 ,
172181 setZoomFactor : vi . fn ( ) ,
173182 on : vi . fn ( ) ,
@@ -2840,3 +2849,134 @@ describe("Preview automation diagnostics", () => {
28402849 expect ( "locator" in error ) . toBe ( false ) ;
28412850 } ) ;
28422851} ) ;
2852+
2853+ describe ( "Preview automation snapshots" , ( ) => {
2854+ const pageValue = {
2855+ url : "https://example.com" ,
2856+ title : "Example" ,
2857+ loading : false ,
2858+ visibleText : "Dashboard" ,
2859+ interactiveElements : [ ] ,
2860+ } ;
2861+
2862+ const snapshotImage = {
2863+ getSize : ( ) => ( { width : 100 , height : 80 } ) ,
2864+ toPNG : ( ) => Buffer . from ( "png" ) ,
2865+ resize : ( ) => ( {
2866+ getSize : ( ) => ( { width : 100 , height : 80 } ) ,
2867+ toPNG : ( ) => Buffer . from ( "png" ) ,
2868+ } ) ,
2869+ } ;
2870+
2871+ effectIt . effect ( "omits ax, console, and network unless include asks" , ( ) =>
2872+ withManager ( ( manager ) =>
2873+ Effect . gen ( function * ( ) {
2874+ const sendCommand = vi . fn ( async ( method : string ) => {
2875+ if ( method === "Runtime.evaluate" ) {
2876+ return { result : { value : pageValue } } ;
2877+ }
2878+ if ( method === "Accessibility.getFullAXTree" ) {
2879+ return { nodes : [ { role : "main" } ] } ;
2880+ }
2881+ return undefined ;
2882+ } ) ;
2883+ fromId . mockReturnValue ( {
2884+ ...makeTestPreviewWebContents ( vi . fn ( async ( ) => snapshotImage ) ) ,
2885+ debugger : {
2886+ isAttached : ( ) => false ,
2887+ attach : vi . fn ( ) ,
2888+ sendCommand,
2889+ on : vi . fn ( ) ,
2890+ off : vi . fn ( ) ,
2891+ } ,
2892+ } as never ) ;
2893+
2894+ yield * manager . createTab ( "tab_snapshot" ) ;
2895+ yield * manager . registerWebview ( "tab_snapshot" , 42 ) ;
2896+ const slim = yield * manager . automationSnapshot ( "tab_snapshot" ) ;
2897+ expect ( slim . accessibilityTree ) . toBeUndefined ( ) ;
2898+ expect ( slim . consoleEntries ) . toEqual ( [ ] ) ;
2899+ expect ( slim . networkEntries ) . toEqual ( [ ] ) ;
2900+ const slimMethods = sendCommand . mock . calls . map ( ( [ method ] ) => method ) ;
2901+ expect ( slimMethods ) . not . toContain ( "Accessibility.getFullAXTree" ) ;
2902+
2903+ sendCommand . mockClear ( ) ;
2904+ const withAx = yield * manager . automationSnapshot ( "tab_snapshot" , [ "ax" ] ) ;
2905+ expect ( withAx . accessibilityTree ) . toEqual ( { nodes : [ { role : "main" } ] } ) ;
2906+ expect ( sendCommand . mock . calls . map ( ( [ method ] ) => method ) ) . toContain (
2907+ "Accessibility.getFullAXTree" ,
2908+ ) ;
2909+ } ) ,
2910+ ) ,
2911+ ) ;
2912+
2913+ effectIt . effect ( "fails the snapshot when capturePage and CDP screenshot both miss" , ( ) =>
2914+ withManager ( ( manager ) =>
2915+ Effect . gen ( function * ( ) {
2916+ const sendCommand = vi . fn ( async ( method : string ) => {
2917+ if ( method === "Runtime.evaluate" ) {
2918+ return { result : { value : pageValue } } ;
2919+ }
2920+ if ( method === "Page.captureScreenshot" ) {
2921+ return { } ;
2922+ }
2923+ return undefined ;
2924+ } ) ;
2925+ fromId . mockReturnValue ( {
2926+ ...makeTestPreviewWebContents (
2927+ vi . fn ( async ( ) => {
2928+ throw new Error ( "capturePage failed" ) ;
2929+ } ) ,
2930+ ) ,
2931+ debugger : {
2932+ isAttached : ( ) => false ,
2933+ attach : vi . fn ( ) ,
2934+ sendCommand,
2935+ on : vi . fn ( ) ,
2936+ off : vi . fn ( ) ,
2937+ } ,
2938+ } as never ) ;
2939+
2940+ yield * manager . createTab ( "tab_snapshot_fail" ) ;
2941+ yield * manager . registerWebview ( "tab_snapshot_fail" , 42 ) ;
2942+ const exit = yield * Effect . exit ( manager . automationSnapshot ( "tab_snapshot_fail" ) ) ;
2943+ expect ( Exit . isFailure ( exit ) ) . toBe ( true ) ;
2944+ if ( Exit . isSuccess ( exit ) ) return ;
2945+ expect ( Option . getOrThrow ( Cause . findErrorOption ( exit . cause ) ) ) . toMatchObject ( {
2946+ _tag : "PreviewOperationError" ,
2947+ operation : "automationSnapshot.capturePage" ,
2948+ } ) ;
2949+ } ) ,
2950+ ) ,
2951+ ) ;
2952+
2953+ effectIt . effect ( "defaults waitFor text search to the main landmark" , ( ) =>
2954+ withManager ( ( manager ) =>
2955+ Effect . gen ( function * ( ) {
2956+ const expressions : string [ ] = [ ] ;
2957+ const sendCommand = vi . fn ( async ( method : string , params ?: Record < string , unknown > ) => {
2958+ if ( method === "Runtime.evaluate" ) {
2959+ expressions . push ( String ( params ?. expression ?? "" ) ) ;
2960+ return { result : { value : { matched : true } } } ;
2961+ }
2962+ return undefined ;
2963+ } ) ;
2964+ fromId . mockReturnValue ( {
2965+ ...makeTestPreviewWebContents ( vi . fn ( async ( ) => snapshotImage ) ) ,
2966+ debugger : {
2967+ isAttached : ( ) => false ,
2968+ attach : vi . fn ( ) ,
2969+ sendCommand,
2970+ on : vi . fn ( ) ,
2971+ off : vi . fn ( ) ,
2972+ } ,
2973+ } as never ) ;
2974+
2975+ yield * manager . createTab ( "tab_wait" ) ;
2976+ yield * manager . registerWebview ( "tab_wait" , 42 ) ;
2977+ yield * manager . automationWaitFor ( "tab_wait" , { text : "Dashboard" } ) ;
2978+ expect ( expressions . some ( ( expression ) => expression . includes ( '"main"' ) ) ) . toBe ( true ) ;
2979+ } ) ,
2980+ ) ,
2981+ ) ;
2982+ } ) ;
0 commit comments