@@ -766,6 +766,133 @@ it.live(
766766 ) . pipe ( Effect . provide ( layer ) ) ,
767767) ;
768768
769+ it . live . each ( [
770+ {
771+ name : "hover burst before a click" ,
772+ inputs : [
773+ ...Array . from ( { length : 120 } , ( _ , x ) => ( {
774+ type : "mouse" ,
775+ action : "move" ,
776+ x,
777+ buttons : 0 ,
778+ button : "none" ,
779+ } ) ) ,
780+ { type : "mouse" , action : "down" , x : 119 , buttons : 1 , button : "left" } ,
781+ { type : "mouse" , action : "up" , x : 119 , buttons : 0 , button : "left" } ,
782+ ] ,
783+ expected : [
784+ { type : "mouseMoved" , x : - 1 } ,
785+ { type : "mouseMoved" , x : 119 } ,
786+ { type : "mousePressed" , x : 119 } ,
787+ { type : "mouseReleased" , x : 119 } ,
788+ ] ,
789+ } ,
790+ {
791+ name : "modifier changes and drag points" ,
792+ inputs : [
793+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
794+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" , modifiers : 2 } ,
795+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" , modifiers : 2 } ,
796+ { type : "mouse" , action : "down" , x : 3 , buttons : 1 , button : "left" } ,
797+ { type : "mouse" , action : "move" , x : 4 , buttons : 1 , button : "left" } ,
798+ { type : "mouse" , action : "move" , x : 5 , buttons : 1 , button : "left" } ,
799+ { type : "mouse" , action : "up" , x : 5 , buttons : 0 , button : "left" } ,
800+ ] ,
801+ expected : [
802+ { type : "mouseMoved" , x : - 1 } ,
803+ { type : "mouseMoved" , x : 1 , modifiers : 0 } ,
804+ { type : "mouseMoved" , x : 3 , modifiers : 2 } ,
805+ { type : "mousePressed" , x : 3 } ,
806+ { type : "mouseMoved" , x : 4 } ,
807+ { type : "mouseMoved" , x : 5 } ,
808+ { type : "mouseReleased" , x : 5 } ,
809+ ] ,
810+ } ,
811+ {
812+ name : "wheel and keyboard boundaries" ,
813+ inputs : [
814+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
815+ { type : "wheel" , x : 1 , deltaY : 20 } ,
816+ { type : "wheel" , x : 1 , deltaY : 30 } ,
817+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" } ,
818+ { type : "key" , action : "down" , key : "a" , code : "KeyA" , text : "a" } ,
819+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" } ,
820+ ] ,
821+ expected : [
822+ { type : "mouseMoved" , x : - 1 } ,
823+ { type : "mouseMoved" , x : 1 } ,
824+ { type : "mouseWheel" , deltaY : 20 } ,
825+ { type : "mouseWheel" , deltaY : 30 } ,
826+ { type : "mouseMoved" , x : 2 } ,
827+ { type : "keyDown" , key : "a" } ,
828+ { type : "mouseMoved" , x : 3 } ,
829+ ] ,
830+ } ,
831+ {
832+ name : "text, navigation and resize boundaries" ,
833+ inputs : [
834+ { type : "mouse" , action : "move" , x : 1 , buttons : 0 , button : "none" } ,
835+ { type : "text" , text : "typed" } ,
836+ { type : "mouse" , action : "move" , x : 2 , buttons : 0 , button : "none" } ,
837+ { type : "navigate" , url : "http://localhost:5173/next" } ,
838+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 , button : "none" } ,
839+ { type : "resize" , width : 640 , height : 480 } ,
840+ { type : "mouse" , action : "move" , x : 4 , buttons : 0 , button : "none" } ,
841+ ] ,
842+ expected : [
843+ { type : "mouseMoved" , x : - 1 } ,
844+ { type : "mouseMoved" , x : 1 } ,
845+ { text : "typed" } ,
846+ { type : "mouseMoved" , x : 2 } ,
847+ { type : "mouseMoved" , x : 3 } ,
848+ { type : "mouseMoved" , x : 4 } ,
849+ ] ,
850+ } ,
851+ {
852+ name : "ambiguous button fields" ,
853+ inputs : [
854+ { type : "mouse" , action : "move" , x : 1 , button : "none" } ,
855+ { type : "mouse" , action : "move" , x : 2 , button : "none" } ,
856+ { type : "mouse" , action : "move" , x : 3 , buttons : 0 } ,
857+ { type : "mouse" , action : "move" , x : 4 , buttons : 0 } ,
858+ ] ,
859+ expected : [ - 1 , 1 , 2 , 3 , 4 ] . map ( ( x ) => ( { type : "mouseMoved" , x } ) ) ,
860+ } ,
861+ ] ) ( "orders streamed input correctly for $name" , ( testCase ) =>
862+ Effect . scoped (
863+ Effect . gen ( function * ( ) {
864+ const { browser, tabId } = yield * ready ;
865+ const viewer = yield * browser . attachViewer ( viewerInput ( tabId , true ) ) ;
866+ yield * viewer . input ( { type : "takeControl" } ) ;
867+ const session = contexts [ 0 ] ! . sessions . at ( - 1 ) ! ;
868+ const send = session . send . getMockImplementation ( ) ! ;
869+ const started = Promise . withResolvers < void > ( ) ;
870+ const finish = Promise . withResolvers < void > ( ) ;
871+ yield * Effect . addFinalizer ( ( ) => Effect . sync ( ( ) => finish . resolve ( ) ) ) ;
872+ session . send . mockClear ( ) ;
873+ session . send . mockImplementationOnce ( async ( method , input ) => {
874+ started . resolve ( ) ;
875+ await finish . promise ;
876+ return send ( method , input ) ;
877+ } ) ;
878+ const running = yield * viewer
879+ . input ( { type : "mouse" , action : "move" , x : - 1 , button : "none" , buttons : 0 } )
880+ . pipe ( Effect . forkScoped ( { startImmediately : true } ) ) ;
881+ yield * Effect . promise ( ( ) => started . promise ) ;
882+ const waiting = yield * Effect . forEach ( testCase . inputs , ( input ) =>
883+ viewer . input ( input ) . pipe ( Effect . forkScoped ( { startImmediately : true } ) ) ,
884+ ) ;
885+ finish . resolve ( ) ;
886+ yield * Effect . forEach ( [ running , ...waiting ] , Fiber . join ) ;
887+ const dispatched = session . send . mock . calls . flatMap ( ( [ method , input ] ) =>
888+ method . startsWith ( "Input." ) ? [ input ] : [ ] ,
889+ ) ;
890+ expect ( dispatched ) . toHaveLength ( testCase . expected . length ) ;
891+ expect ( dispatched ) . toMatchObject ( testCase . expected ) ;
892+ } ) ,
893+ ) . pipe ( Effect . provide ( layer ) ) ,
894+ ) ;
895+
769896it . live ( "only the controlling viewer's copy and cut keys reach its clipboard" , ( ) =>
770897 Effect . scoped (
771898 Effect . gen ( function * ( ) {
0 commit comments