11import { describe , expect , it } from "./suite.ts" ;
2- import { setTimeout as sleep } from ' node:timers/promises' ;
2+ import { setTimeout as sleep } from " node:timers/promises" ;
33import { createInput , type InputEvent , type InputOptions } from "../input.ts" ;
44
55function str ( s : string ) : Uint8Array {
@@ -17,6 +17,23 @@ function concat(...parts: Uint8Array[]): Uint8Array {
1717 return out ;
1818}
1919
20+ function bytes ( ...parts : Array < string | Uint8Array > ) : Uint8Array {
21+ return concat ( ...parts . map ( ( p ) => typeof p === "string" ? str ( p ) : p ) ) ;
22+ }
23+
24+ function arrowUp ( ) : Uint8Array {
25+ return str ( "\x1b[A" ) ;
26+ }
27+
28+ function mousePress ( { x, y } : { x : number ; y : number } ) : Uint8Array {
29+ // SGR coords are 1-based; callers pass 0-based to match emitted events.
30+ return str ( `\x1b[<0;${ x + 1 } ;${ y + 1 } M` ) ;
31+ }
32+
33+ function kittyAltKey ( key : string ) : Uint8Array {
34+ return str ( `\x1b[${ key . codePointAt ( 0 ) } ;3u` ) ;
35+ }
36+
2037function sig ( e : InputEvent ) : string {
2138 switch ( e . type ) {
2239 case "keydown" :
@@ -74,13 +91,13 @@ function splitAt(buf: Uint8Array, offsets: number[]): Uint8Array[] {
7491}
7592
7693describe ( "input event loop" , ( ) => {
77- let stream = concat (
78- str ( "hi" ) ,
79- new Uint8Array ( [ 0x1b , 0x5b , 0x41 ] ) , // ArrowUp
80- str ( "\x1b[<0;35;12M" ) , // SGR mouse press
81- new Uint8Array ( [ 0xe4 , 0xb8 , 0xad ] ) , // 中
82- str ( "\x1b[97;3u ") , // Kitty a+Alt
83- new Uint8Array ( [ 0xf0 , 0x9f , 0x8e , 0x89 ] ) , // 🎉
94+ let stream = bytes (
95+ "hi" ,
96+ arrowUp ( ) ,
97+ mousePress ( { x : 34 , y : 11 } ) ,
98+ "中" ,
99+ kittyAltKey ( "a ") ,
100+ "🎉" ,
84101 ) ;
85102
86103 let expected = [
@@ -107,29 +124,27 @@ describe("input event loop", () => {
107124
108125 describe ( "pending ESC flush" , ( ) => {
109126 it ( "flushes a lone trailing ESC as Escape after the latency" , async ( ) => {
110- expect ( await drive ( [ str ( "hi" ) , new Uint8Array ( [ 0x1b ] ) ] ) ) . toEqual ( [
127+ expect ( await drive ( [ bytes ( "hi" ) , str ( "\x1b" ) ] ) ) . toEqual ( [
111128 "keydown:h" ,
112129 "keydown:i" ,
113130 "keydown:Escape" ,
114131 ] ) ;
115132 } ) ;
116133
117134 it ( "resolves ESC as a sequence when the rest arrives next chunk" , async ( ) => {
118- expect (
119- await drive ( [ new Uint8Array ( [ 0x1b ] ) , new Uint8Array ( [ 0x5b , 0x41 ] ) ] ) ,
120- ) . toEqual ( [ "keydown:ArrowUp" ] ) ;
135+ expect ( await drive ( splitAt ( arrowUp ( ) , [ 1 ] ) ) ) . toEqual ( [ "keydown:ArrowUp" ] ) ;
121136 } ) ;
122137 } ) ;
123138
124139 it ( "handles a large mixed burst across many small chunks" , async ( ) => {
125- let unit = concat (
126- new Uint8Array ( [ 0x1b , 0x5b , 0x41 ] ) , // ArrowUp
127- str ( "ab" ) ,
128- str ( "\x1b[<0;1;1M" ) , // mouse at 0,0
129- new Uint8Array ( [ 0xe4 , 0xb8 , 0xad ] ) , // 中
140+ let unit = bytes (
141+ arrowUp ( ) ,
142+ "ab" ,
143+ mousePress ( { x : 0 , y : 0 } ) ,
144+ "中" ,
130145 ) ;
131146 let n = 50 ;
132- let big = concat ( ...new Array ( n ) . fill ( unit ) ) ;
147+ let big = bytes ( ...new Array ( n ) . fill ( unit ) ) ;
133148 let chunks : Uint8Array [ ] = [ ] ;
134149 for ( let i = 0 ; i < big . length ; i += 7 ) chunks . push ( big . subarray ( i , i + 7 ) ) ;
135150
0 commit comments