@@ -842,6 +842,133 @@ it.live(
842842 ) . pipe ( Effect . provide ( layer ) ) ,
843843) ;
844844
845+ it . effect . each ( [
846+ {
847+ name : "hover burst before a click" ,
848+ inputs : [
849+ ...Array . from ( { length : 120 } , ( _ , x ) => ( {
850+ type : "mouse" ,
851+ action : "move" ,
852+ x,
853+ buttons : 0 ,
854+ button : "none" ,
855+ } ) ) ,
856+ { type : "mouse" , action : "down" , x : 119 , buttons : 1 , button : "left" } ,
857+ { type : "mouse" , action : "up" , x : 119 , buttons : 0 , button : "left" } ,
858+ ] ,
859+ expected : [
860+ { type : "mouseMoved" , x : - 1 } ,
861+ { type : "mouseMoved" , x : 119 } ,
862+ { type : "mousePressed" , x : 119 } ,
863+ { type : "mouseReleased" , x : 119 } ,
864+ ] ,
865+ } ,
866+ {
867+ name : "modifier changes and drag points" ,
868+ inputs : [
869+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
870+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" , modifiers : 2 } ,
871+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" , modifiers : 2 } ,
872+ { type : "mouse" , action : "down" , x : 3 , buttons : 1 , button : "left" } ,
873+ { type : "mouse" , action : "move" , x : 4 , buttons : 1 , button : "left" } ,
874+ { type : "mouse" , action : "move" , x : 5 , buttons : 1 , button : "left" } ,
875+ { type : "mouse" , action : "up" , x : 5 , buttons : 0 , button : "left" } ,
876+ ] ,
877+ expected : [
878+ { type : "mouseMoved" , x : - 1 } ,
879+ { type : "mouseMoved" , x : 1 , modifiers : 0 } ,
880+ { type : "mouseMoved" , x : 3 , modifiers : 2 } ,
881+ { type : "mousePressed" , x : 3 } ,
882+ { type : "mouseMoved" , x : 4 } ,
883+ { type : "mouseMoved" , x : 5 } ,
884+ { type : "mouseReleased" , x : 5 } ,
885+ ] ,
886+ } ,
887+ {
888+ name : "wheel and keyboard boundaries" ,
889+ inputs : [
890+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
891+ { type : "wheel" , x : 1 , deltaY : 20 } ,
892+ { type : "wheel" , x : 1 , deltaY : 30 } ,
893+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" } ,
894+ { type : "key" , action : "down" , key : "a" , code : "KeyA" , text : "a" } ,
895+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" } ,
896+ ] ,
897+ expected : [
898+ { type : "mouseMoved" , x : - 1 } ,
899+ { type : "mouseMoved" , x : 1 } ,
900+ { type : "mouseWheel" , deltaY : 20 } ,
901+ { type : "mouseWheel" , deltaY : 30 } ,
902+ { type : "mouseMoved" , x : 2 } ,
903+ { type : "keyDown" , key : "a" } ,
904+ { type : "mouseMoved" , x : 3 } ,
905+ ] ,
906+ } ,
907+ {
908+ name : "text, navigation and resize boundaries" ,
909+ inputs : [
910+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
911+ { type : "text" , text : "typed" } ,
912+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" } ,
913+ { type : "navigate" , url : "http://localhost:5173/next" } ,
914+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" } ,
915+ { type : "resize" , width : 640 , height : 480 } ,
916+ { type : "mouse" , action : "move" , x : 4 , buttons : 0 , button : "none" } ,
917+ ] ,
918+ expected : [
919+ { type : "mouseMoved" , x : - 1 } ,
920+ { type : "mouseMoved" , x : 1 } ,
921+ { text : "typed" } ,
922+ { type : "mouseMoved" , x : 2 } ,
923+ { type : "mouseMoved" , x : 3 } ,
924+ { type : "mouseMoved" , x : 4 } ,
925+ ] ,
926+ } ,
927+ {
928+ name : "ambiguous button fields" ,
929+ inputs : [
930+ { type : "mouse" , action : "move" , x : 1 , button : "none" } ,
931+ { type : "mouse" , action : "move" , x : 2 , button : "none" } ,
932+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 } ,
933+ { type : "mouse" , action : "move" , x : 4 , buttons : 0 } ,
934+ ] ,
935+ expected : [ - 1 , 1 , 2 , 3 , 4 ] . map ( ( x ) => ( { type : "mouseMoved" , x } ) ) ,
936+ } ,
937+ ] ) ( "orders streamed input correctly for $name" , ( testCase ) =>
938+ Effect . scoped (
939+ Effect . gen ( function * ( ) {
940+ const { browser, tabId } = yield * ready ;
941+ const viewer = yield * browser . attachViewer ( viewerInput ( tabId , true ) ) ;
942+ yield * viewer . input ( { type : "takeControl" } ) ;
943+ const session = contexts [ 0 ] ! . sessions . at ( - 1 ) ! ;
944+ const send = session . send . getMockImplementation ( ) ! ;
945+ const started = Promise . withResolvers < void > ( ) ;
946+ const finish = Promise . withResolvers < void > ( ) ;
947+ yield * Effect . addFinalizer ( ( ) => Effect . sync ( ( ) => finish . resolve ( ) ) ) ;
948+ session . send . mockClear ( ) ;
949+ session . send . mockImplementationOnce ( async ( method , input ) => {
950+ started . resolve ( ) ;
951+ await finish . promise ;
952+ return send ( method , input ) ;
953+ } ) ;
954+ const running = yield * viewer
955+ . input ( { type : "mouse" , action : "move" , x : - 1 , button : "none" , buttons : 0 } )
956+ . pipe ( Effect . forkScoped ( { startImmediately : true } ) ) ;
957+ yield * Effect . promise ( ( ) => started . promise ) ;
958+ const waiting = yield * Effect . forEach ( testCase . inputs , ( input ) =>
959+ viewer . input ( input ) . pipe ( Effect . forkScoped ( { startImmediately : true } ) ) ,
960+ ) ;
961+ finish . resolve ( ) ;
962+ yield * Effect . forEach ( [ running , ...waiting ] , Fiber . join ) ;
963+ const dispatched = session . send . mock . calls . flatMap ( ( [ method , input ] ) =>
964+ method . startsWith ( "Input." ) ? [ input ] : [ ] ,
965+ ) ;
966+ expect ( dispatched ) . toHaveLength ( testCase . expected . length ) ;
967+ expect ( dispatched ) . toMatchObject ( testCase . expected ) ;
968+ } ) ,
969+ ) . pipe ( Effect . provide ( layer ) ) ,
970+ ) ;
971+
845972it . live ( "only the controlling viewer's copy and cut keys reach its clipboard" , ( ) =>
846973 Effect . scoped (
847974 Effect . gen ( function * ( ) {
0 commit comments