@@ -8,143 +8,143 @@ module TestHelpers
88 property? closed : Bool = false
99 property read_timeout : Time ::Span ? = nil
1010 property mode : Symbol = :cooked
11-
11+
1212 def initialize (@input : Array (String ) = [] of String )
1313 @input .each do |str |
1414 @input_buffer .concat(str.chars)
1515 end
1616 end
17-
17+
1818 def read (slice : Bytes ) : Int32
1919 return 0 if @closed || @input_buffer .empty?
20-
20+
2121 bytes_read = 0
2222 slice.each_with_index do |_ , i |
2323 break if @input_buffer .empty?
2424 char = @input_buffer .shift
2525 slice[i] = char.ord.to_u8
2626 bytes_read += 1
2727 end
28-
28+
2929 bytes_read
3030 end
31-
31+
3232 def write (slice : Bytes ) : Nil
3333 @output_buffer += String .new(slice)
3434 end
35-
35+
3636 def close : Nil
3737 @closed = true
3838 end
39-
39+
4040 def fd : Int32
4141 -1
4242 end
43-
43+
4444 def blocking : Bool
4545 true
4646 end
47-
47+
4848 def blocking = (value : Bool )
4949 # no-op for mock
5050 end
51-
51+
5252 def read_timeout = (timeout : Time ::Span ?)
5353 @read_timeout = timeout
5454 end
55-
55+
5656 def cooked !
5757 @mode = :cooked
5858 end
59-
59+
6060 def raw !
6161 @mode = :raw
6262 end
63-
63+
6464 def echo !
6565 @mode = :echo
6666 end
67-
67+
6868 def tty ?
6969 true
7070 end
71-
71+
7272 # Add more characters to the input buffer
7373 def inject_input (str : String )
7474 @input_buffer .concat(str.chars)
7575 end
76-
76+
7777 # Clear the output buffer and return its contents
7878 def consume_output : String
7979 output = @output_buffer
8080 @output_buffer = " "
8181 output
8282 end
8383 end
84-
84+
8585 # Helper to create key sequences
8686 module Keys
8787 ESC = " \e "
88-
88+
8989 def self.up
9090 " #{ ESC } [A"
9191 end
92-
92+
9393 def self.down
9494 " #{ ESC } [B"
9595 end
96-
96+
9797 def self.right
9898 " #{ ESC } [C"
9999 end
100-
100+
101101 def self.left
102102 " #{ ESC } [D"
103103 end
104-
104+
105105 def self.home
106106 " #{ ESC } [H"
107107 end
108-
108+
109109 def self.end_key
110110 " #{ ESC } [F"
111111 end
112-
112+
113113 def self.delete
114114 " #{ ESC } [3~"
115115 end
116-
116+
117117 def self.backspace
118118 " \b "
119119 end
120-
120+
121121 def self.tab
122122 " \t "
123123 end
124-
124+
125125 def self.enter
126126 " \r "
127127 end
128-
128+
129129 def self.ctrl (letter : Char )
130130 (letter.upcase.ord - 64 ).chr
131131 end
132-
132+
133133 def self.alt (letter : Char )
134134 " #{ ESC } #{ letter } "
135135 end
136-
136+
137137 def self.f (num : Int32 )
138138 case num
139- when 1 then " #{ ESC } OP"
140- when 2 then " #{ ESC } OQ"
141- when 3 then " #{ ESC } OR"
142- when 4 then " #{ ESC } OS"
143- when 5 then " #{ ESC } [15~"
144- when 6 then " #{ ESC } [17~"
145- when 7 then " #{ ESC } [18~"
146- when 8 then " #{ ESC } [19~"
147- when 9 then " #{ ESC } [20~"
139+ when 1 then " #{ ESC } OP"
140+ when 2 then " #{ ESC } OQ"
141+ when 3 then " #{ ESC } OR"
142+ when 4 then " #{ ESC } OS"
143+ when 5 then " #{ ESC } [15~"
144+ when 6 then " #{ ESC } [17~"
145+ when 7 then " #{ ESC } [18~"
146+ when 8 then " #{ ESC } [19~"
147+ when 9 then " #{ ESC } [20~"
148148 when 10 then " #{ ESC } [21~"
149149 when 11 then " #{ ESC } [23~"
150150 when 12 then " #{ ESC } [24~"
@@ -153,55 +153,54 @@ module TestHelpers
153153 end
154154 end
155155 end
156-
156+
157157 # Helper to create a mock file descriptor
158158 class MockFileDescriptor < IO::FileDescriptor
159159 property input_data : String = " "
160160 property output_data : String = " "
161161 property read_pos : Int32 = 0
162162 property? blocking_mode : Bool = true
163-
163+
164164 def initialize (fd : Int32 = 0 )
165165 super (handle: fd.unsafe_as(LibC ::Int ), close_on_finalize: false )
166166 end
167-
168-
167+
169168 def blocking : Bool
170169 @blocking_mode
171170 end
172-
171+
173172 def blocking = (value : Bool )
174173 @blocking_mode = value
175174 end
176-
175+
177176 def read (slice : Bytes ) : Int32
178177 return 0 if @read_pos >= @input_data .size
179-
178+
180179 bytes_to_read = Math .min(slice.size, @input_data .size - @read_pos )
181180 return 0 if bytes_to_read == 0
182-
181+
183182 @input_data .to_slice[@read_pos , bytes_to_read].copy_to(slice.to_unsafe, bytes_to_read)
184183 @read_pos += bytes_to_read
185184 bytes_to_read
186185 end
187-
186+
188187 def read_char : Char ?
189188 return nil if @read_pos >= @input_data .size
190189 char = @input_data [@read_pos ]
191190 @read_pos += 1
192191 char
193192 end
194-
193+
195194 def write (slice : Bytes ) : Nil
196195 @output_data += String .new(slice)
197196 nil
198197 end
199-
198+
200199 def print (* args)
201200 args.each { |arg | @output_data += arg.to_s }
202201 nil
203202 end
204-
203+
205204 def puts (* args)
206205 if args.empty?
207206 @output_data += " \n "
@@ -210,95 +209,97 @@ module TestHelpers
210209 end
211210 nil
212211 end
213-
212+
214213 def close
215214 @closed = true
216215 nil
217216 end
218-
217+
219218 def closed ? : Bool
220219 @closed
221220 end
222-
221+
223222 def reset
224223 @input_data = " "
225224 @output_data = " "
226225 @read_pos = 0
227226 end
228-
227+
229228 def inject_input (data : String )
230229 @input_data += data
231230 end
232-
231+
233232 def tty ? : Bool
234233 true
235234 end
236-
235+
237236 def cooked : Nil
238237 # No-op for testing
239238 end
240-
239+
241240 def cooked ! : Nil
242241 # No-op for testing
243242 end
244-
245- def raw : Nil
243+
244+ def raw : Nil
246245 # No-op for testing
247246 end
248-
247+
249248 def raw ! : Nil
250249 # No-op for testing
251250 end
252-
251+
253252 def echo = (value : Bool ) : Nil
254253 # No-op for testing
255254 end
256-
257- def sync ? : Bool
258- true
255+
256+ property? sync_state : Bool ? = true
257+
258+ def sync ? : Bool ?
259+ @sync_state
259260 end
260-
261+
261262 def sync = (value : Bool )
262- # No-op for testing
263+ @sync_state = value
263264 end
264-
265+
265266 def noecho (& block)
266267 yield
267268 end
268-
269+
269270 def raw (& block)
270271 yield
271272 end
272-
273+
273274 def cooked (& block)
274275 yield
275276 end
276277 end
277-
278+
278279 # Helper to capture events
279280 class EventCapture
280281 property events : Array ({String , Term ::Reader ::KeyEvent }) = [] of {String , Term ::Reader ::KeyEvent }
281-
282+
282283 def handler
283284 - > (name : String , event : Term ::Reader ::KeyEvent ) {
284285 @events << {name, event}
285286 nil
286287 }
287288 end
288-
289+
289290 def clear
290291 @events .clear
291292 end
292-
293+
293294 def has_event ?(name : String ) : Bool
294295 @events .any? { |n , _ | n == name }
295296 end
296-
297+
297298 def event_count (name : String ) : Int32
298299 @events .count { |n , _ | n == name }
299300 end
300301 end
301-
302+
302303 # Platform detection helpers
303304 def windows ?
304305 {% if flag?(:windows ) % }
@@ -307,8 +308,8 @@ module TestHelpers
307308 false
308309 {% end % }
309310 end
310-
311+
311312 def unix ?
312313 ! windows?
313314 end
314- end
315+ end
0 commit comments