@@ -3,11 +3,12 @@ import type { DaemonRequest } from '../../../daemon/types.ts';
33import { createDaemonMaestroRuntimePort } from '../daemon-runtime-port.ts' ;
44import {
55 MAESTRO_OBSERVATION_POLL_MS ,
6+ resolveTypedMaestroTarget ,
67 waitForTypedSnapshotStability ,
78} from '../daemon-runtime-port-observation.ts' ;
89import { makeBaseRequest , makeDependencies , makeSnapshot } from './daemon-runtime-port-fixtures.ts' ;
910
10- test ( 'does not pair an observation with later same-generation snapshots ' , async ( ) => {
11+ test ( 'replaces pre-mutation evidence with the stable post-mutation snapshot ' , async ( ) => {
1112 const requests : DaemonRequest [ ] = [ ] ;
1213 let snapshots = 0 ;
1314 const port = createDaemonMaestroRuntimePort ( {
@@ -16,7 +17,7 @@ test('does not pair an observation with later same-generation snapshots', async
1617 requests . push ( request ) ;
1718 if ( request . command !== 'snapshot' ) return { ok : true , data : { } } ;
1819 snapshots += 1 ;
19- const targetX = snapshots >= 4 ? 40 : 200 ;
20+ const targetX = snapshots >= 2 ? 40 : 200 ;
2021 return {
2122 ok : true ,
2223 data : {
@@ -49,7 +50,7 @@ test('does not pair an observation with later same-generation snapshots', async
4950 platform : 'ios' ,
5051 } ) ;
5152
52- const observation = await port . observe ( {
53+ await port . observe ( {
5354 condition : { kind : 'visible' , selector : { id : 'ready' } } ,
5455 timeoutMs : 0 ,
5556 generation : 0 ,
@@ -58,7 +59,6 @@ test('does not pair an observation with later same-generation snapshots', async
5859 await port . execute ( {
5960 command : { kind : 'inputText' , source : { line : 2 } , text : 'hello' } ,
6061 generation : 0 ,
61- cachedObservation : observation ,
6262 env : { } ,
6363 invalidateObservation ( ) { } ,
6464 } ) ;
@@ -68,8 +68,7 @@ test('does not pair an observation with later same-generation snapshots', async
6868 source : { line : 3 } ,
6969 target : { space : 'target' , selector : { id : 'continue' } } ,
7070 } ,
71- generation : 0 ,
72- cachedObservation : observation ,
71+ generation : 1 ,
7372 env : { } ,
7473 invalidateObservation ( ) { } ,
7574 } ) ;
@@ -79,10 +78,49 @@ test('does not pair an observation with later same-generation snapshots', async
7978 'type' ,
8079 'snapshot' ,
8180 'snapshot' ,
82- 'snapshot' ,
8381 'click' ,
8482 ] ) ;
8583 expect ( requests . at ( - 1 ) ?. positionals ) . toEqual ( [ 'id="continue"' ] ) ;
84+ expect ( requests . at ( - 1 ) ?. flags ?. maestro ?. expectedTapPoint ) . toEqual ( { x : 100 , y : 122 } ) ;
85+ } ) ;
86+
87+ test ( 'computes expensive target evidence only for the command policies that consume it' , ( ) => {
88+ const snapshot = makeSnapshot ( [
89+ { index : 0 , type : 'Application' , rect : { x : 0 , y : 0 , width : 402 , height : 874 } } ,
90+ {
91+ index : 1 ,
92+ parentIndex : 0 ,
93+ type : 'Button' ,
94+ identifier : 'continue' ,
95+ hittable : true ,
96+ rect : { x : 20 , y : 40 , width : 120 , height : 44 } ,
97+ } ,
98+ ] ) ;
99+ const base = {
100+ context : { generation : 0 , env : { } } ,
101+ snapshot,
102+ platform : 'ios' as const ,
103+ } ;
104+
105+ const ordinary = resolveTypedMaestroTarget ( {
106+ ...base ,
107+ query : { selector : { id : 'continue' } , purpose : 'tap' , timeoutMs : 0 } ,
108+ } ) ;
109+ const atomicRetry = resolveTypedMaestroTarget ( {
110+ ...base ,
111+ query : {
112+ selector : { id : 'continue' } ,
113+ purpose : 'tap' ,
114+ timeoutMs : 0 ,
115+ allowAtomicSelectorDispatch : true ,
116+ includeSurfaceSignature : true ,
117+ } ,
118+ } ) ;
119+
120+ expect ( ordinary ) . not . toHaveProperty ( 'surfaceSignature' ) ;
121+ expect ( ordinary ) . not . toHaveProperty ( 'dispatchSelector' ) ;
122+ expect ( atomicRetry . surfaceSignature ) . toMatch ( / ^ [ a - f 0 - 9 ] { 64 } $ / ) ;
123+ expect ( atomicRetry . dispatchSelector ) . toEqual ( { key : 'id' , value : 'continue' } ) ;
86124} ) ;
87125
88126test ( 'compares snapshots before sleeping and captures once beyond a zero settle budget' , async ( ) => {
0 commit comments