@@ -29,55 +29,22 @@ export async function invokeMaestroAssertVisible(params: {
2929 invoke : MaestroRuntimeInvoke ;
3030 scope ?: ReplayVarScope ;
3131} ) : Promise < DaemonResponse > {
32- const [ selector , timeoutValue = '5000' ] = params . positionals ;
33- if ( ! selector ) {
34- return errorResponse ( 'INVALID_ARGS' , 'assertVisible requires a selector.' ) ;
35- }
36- const timeoutMs = Number ( timeoutValue ) ;
37- if ( ! Number . isFinite ( timeoutMs ) || timeoutMs < 0 ) {
38- return errorResponse ( 'INVALID_ARGS' , 'assertVisible timeout must be a non-negative number.' ) ;
39- }
32+ const args = readAssertVisibleArgs ( params . positionals ) ;
33+ if ( ! args . ok ) return args . response ;
4034
4135 const startedAt = Date . now ( ) ;
42- const deadlineMs = timeoutMs + MAESTRO_ASSERTION_POLICY . assertVisibleGraceMs ;
36+ const deadlineMs = args . timeoutMs + MAESTRO_ASSERTION_POLICY . assertVisibleGraceMs ;
4337 let lastResponse : DaemonResponse | undefined ;
4438 let capturedAfterDeadline = false ;
4539 while ( true ) {
4640 const captureStartedAt = Date . now ( ) ;
47- const response = await captureMaestroRawSnapshot ( params ) ;
48- lastResponse = response ;
49- if ( response . ok ) {
50- const snapshot = readSnapshotState ( response . data ) ;
51- if ( ! snapshot ) {
52- return errorResponse ( 'COMMAND_FAILED' , 'Unable to read snapshot data for assertVisible.' ) ;
53- }
54- const target = resolveVisibleMaestroNodeFromSnapshot (
55- snapshot ,
56- selector ,
57- readMaestroSelectorPlatform ( params . baseReq . flags ) ,
58- getSnapshotReferenceFrame ( snapshot ) ,
59- ) ;
60- if ( target . ok ) {
61- return {
62- ok : true ,
63- data : {
64- selector,
65- matches : target . matches ,
66- nodeIndex : target . node . index ,
67- nodeType : target . node . type ,
68- nodeLabel : target . node . label ,
69- nodeIdentifier : target . node . identifier ,
70- rect : target . rect ,
71- waitedMs : Date . now ( ) - startedAt ,
72- } ,
73- } ;
74- }
75- lastResponse = errorResponse ( 'COMMAND_FAILED' , target . message , { selector } ) ;
76- }
41+ const attempt = await readAssertVisibleAttempt ( params , args . selector , startedAt ) ;
42+ if ( attempt . done ) return attempt . response ;
43+ lastResponse = attempt . response ;
7744
7845 const elapsedMs = Date . now ( ) - startedAt ;
7946 if ( elapsedMs >= deadlineMs ) {
80- if ( ! capturedAfterDeadline && captureStartedAt - startedAt < deadlineMs ) {
47+ if ( shouldCaptureOnceAfterDeadline ( capturedAfterDeadline , captureStartedAt , startedAt , deadlineMs ) ) {
8148 capturedAfterDeadline = true ;
8249 continue ;
8350 }
@@ -88,13 +55,87 @@ export async function invokeMaestroAssertVisible(params: {
8855
8956 return (
9057 lastResponse ??
91- errorResponse ( 'COMMAND_FAILED' , `Expected visible but did not match: ${ selector } ` , {
92- selector,
93- timeoutMs,
58+ errorResponse ( 'COMMAND_FAILED' , `Expected visible but did not match: ${ args . selector } ` , {
59+ selector : args . selector ,
60+ timeoutMs : args . timeoutMs ,
9461 } )
9562 ) ;
9663}
9764
65+ function readAssertVisibleArgs (
66+ positionals : string [ ] ,
67+ ) :
68+ | { ok : true ; selector : string ; timeoutMs : number }
69+ | { ok : false ; response : DaemonResponse } {
70+ const [ selector , timeoutValue = '5000' ] = positionals ;
71+ if ( ! selector ) {
72+ return { ok : false , response : errorResponse ( 'INVALID_ARGS' , 'assertVisible requires a selector.' ) } ;
73+ }
74+ const timeoutMs = Number ( timeoutValue ) ;
75+ if ( ! Number . isFinite ( timeoutMs ) || timeoutMs < 0 ) {
76+ return {
77+ ok : false ,
78+ response : errorResponse ( 'INVALID_ARGS' , 'assertVisible timeout must be a non-negative number.' ) ,
79+ } ;
80+ }
81+ return { ok : true , selector, timeoutMs } ;
82+ }
83+
84+ async function readAssertVisibleAttempt (
85+ params : {
86+ baseReq : ReplayBaseRequest ;
87+ positionals : string [ ] ;
88+ invoke : MaestroRuntimeInvoke ;
89+ scope ?: ReplayVarScope ;
90+ } ,
91+ selector : string ,
92+ startedAt : number ,
93+ ) : Promise < { done : true ; response : DaemonResponse } | { done : false ; response : DaemonResponse } > {
94+ const response = await captureMaestroRawSnapshot ( params ) ;
95+ if ( ! response . ok ) return { done : false , response } ;
96+ const snapshot = readSnapshotState ( response . data ) ;
97+ if ( ! snapshot ) {
98+ return {
99+ done : true ,
100+ response : errorResponse ( 'COMMAND_FAILED' , 'Unable to read snapshot data for assertVisible.' ) ,
101+ } ;
102+ }
103+ const target = resolveVisibleMaestroNodeFromSnapshot (
104+ snapshot ,
105+ selector ,
106+ readMaestroSelectorPlatform ( params . baseReq . flags ) ,
107+ getSnapshotReferenceFrame ( snapshot ) ,
108+ ) ;
109+ if ( ! target . ok ) {
110+ return { done : false , response : errorResponse ( 'COMMAND_FAILED' , target . message , { selector } ) } ;
111+ }
112+ return {
113+ done : true ,
114+ response : {
115+ ok : true ,
116+ data : {
117+ selector,
118+ matches : target . matches ,
119+ nodeIndex : target . node . index ,
120+ nodeType : target . node . type ,
121+ nodeLabel : target . node . label ,
122+ nodeIdentifier : target . node . identifier ,
123+ rect : target . rect ,
124+ waitedMs : Date . now ( ) - startedAt ,
125+ } ,
126+ } ,
127+ } ;
128+ }
129+
130+ function shouldCaptureOnceAfterDeadline (
131+ capturedAfterDeadline : boolean ,
132+ captureStartedAt : number ,
133+ startedAt : number ,
134+ deadlineMs : number ,
135+ ) : boolean {
136+ return ! capturedAfterDeadline && captureStartedAt - startedAt < deadlineMs ;
137+ }
138+
98139export async function invokeMaestroAssertNotVisible ( params : {
99140 baseReq : ReplayBaseRequest ;
100141 positionals : string [ ] ;
0 commit comments