@@ -7,12 +7,7 @@ import {
77 type TerminalCopyInteractionTerminal ,
88 type TerminalCopyKeyboardEvent
99} from "../../src/web/terminal-copy-interaction.js"
10- import {
11- copyEvent ,
12- FakeTerminalCopyHost ,
13- mouseEvent ,
14- type TerminalCopyTestMouseEvent
15- } from "./fixtures/terminal-copy-interaction.js"
10+ import { copyEvent , FakeTerminalCopyHost } from "./fixtures/terminal-copy-interaction.js"
1611
1712type SelectionBufferType = "alternate" | "normal"
1813
@@ -166,6 +161,26 @@ const requireKeyHandler = (
166161) : ( event : TerminalCopyKeyboardEvent ) => boolean =>
167162 keyHandlers [ 0 ] ?? expect . fail ( "Expected terminal copy key handler to be registered." )
168163
164+ const withSelectionRestoreHarness = ( assertion : ( harness : SelectionRestoreHarness ) => void ) : void => {
165+ Effect . runSync (
166+ Effect . scoped (
167+ Effect . flatMap (
168+ Effect . acquireRelease (
169+ Effect . sync ( createSelectionRestoreHarness ) ,
170+ ( harness ) =>
171+ Effect . sync ( ( ) => {
172+ harness . disposable . dispose ( )
173+ } )
174+ ) ,
175+ ( harness ) =>
176+ Effect . sync ( ( ) => {
177+ assertion ( harness )
178+ } )
179+ )
180+ )
181+ )
182+ }
183+
169184describe ( "terminal copy selection restore" , ( ) => {
170185 it . effect ( "restores generated valid xterm selection coordinates after redraw" , ( ) =>
171186 Effect . sync ( ( ) => {
@@ -174,19 +189,18 @@ describe("terminal copy selection restore", () => {
174189 nonEmptySelectionTextArbitrary ,
175190 selectionCoordinateArbitrary ,
176191 ( selectedText , { bufferType, extraCols, startColumn, startRow } ) => {
177- const harness = createSelectionRestoreHarness ( )
178- const cols = startColumn + selectedText . length + extraCols
179-
180- harness . setCols ( cols )
181- harness . setBufferType ( bufferType )
182- harness . setSelection ( selectedText , startColumn , startRow )
183- harness . emitSelectionChange ( )
184- harness . setSelection ( "" , 0 , 0 )
185- harness . emitSelectionChange ( )
186-
187- expect ( harness . selectCalls ) . toEqual ( [ { column : startColumn , length : selectedText . length , row : startRow } ] )
188-
189- harness . disposable . dispose ( )
192+ withSelectionRestoreHarness ( ( harness ) => {
193+ const cols = startColumn + selectedText . length + extraCols
194+ harness . setCols ( cols )
195+ harness . setBufferType ( bufferType )
196+ harness . setSelection ( selectedText , startColumn , startRow )
197+ harness . emitSelectionChange ( )
198+ harness . setSelection ( "" , 0 , 0 )
199+ harness . emitSelectionChange ( )
200+ expect ( harness . selectCalls ) . toEqual ( [
201+ { column : startColumn , length : selectedText . length , row : startRow }
202+ ] )
203+ } )
190204 }
191205 ) ,
192206 { numRuns : 100 }
@@ -201,27 +215,25 @@ describe("terminal copy selection restore", () => {
201215 selectionCoordinateArbitrary ,
202216 fc . integer ( { max : 32 , min : 1 } ) ,
203217 ( selectedText , { bufferType, extraCols, startColumn, startRow } , colsDelta ) => {
204- const harness = createSelectionRestoreHarness ( )
205- const clipboardWrites : Array < { readonly data : string ; readonly format : string } > = [ ]
206- const cols = startColumn + selectedText . length + extraCols
207-
208- harness . setCols ( cols )
209- harness . setBufferType ( bufferType )
210- harness . setSelection ( selectedText , startColumn , startRow )
211- harness . emitSelectionChange ( )
212- harness . setCols ( cols + colsDelta )
213- harness . setSelection ( "" , 0 , 0 )
214- harness . emitSelectionChange ( )
215- harness . host . dispatchCopy ( copyEvent ( {
216- setData : ( format : string , data : string ) => {
217- clipboardWrites . push ( { data, format } )
218- }
219- } ) )
220-
221- expect ( harness . selectCalls ) . toEqual ( [ ] )
222- expect ( clipboardWrites ) . toEqual ( [ { data : selectedText , format : "text/plain" } ] )
223-
224- harness . disposable . dispose ( )
218+ withSelectionRestoreHarness ( ( harness ) => {
219+ const clipboardWrites : Array < { readonly data : string ; readonly format : string } > = [ ]
220+ const cols = startColumn + selectedText . length + extraCols
221+ harness . setCols ( cols )
222+ harness . setBufferType ( bufferType )
223+ harness . setSelection ( selectedText , startColumn , startRow )
224+ harness . emitSelectionChange ( )
225+ harness . setCols ( cols + colsDelta )
226+ harness . setSelection ( "" , 0 , 0 )
227+ harness . emitSelectionChange ( )
228+ harness . host . dispatchCopy ( copyEvent ( {
229+ setData : ( format : string , data : string ) => {
230+ clipboardWrites . push ( { data, format } )
231+ }
232+ } ) )
233+
234+ expect ( harness . selectCalls ) . toEqual ( [ ] )
235+ expect ( clipboardWrites ) . toEqual ( [ { data : selectedText , format : "text/plain" } ] )
236+ } )
225237 }
226238 ) ,
227239 { numRuns : 100 }
@@ -235,28 +247,25 @@ describe("terminal copy selection restore", () => {
235247 nonEmptySelectionTextArbitrary ,
236248 selectionCoordinateArbitrary ,
237249 ( selectedText , { bufferType, extraCols, startColumn, startRow } ) => {
238- const harness = createSelectionRestoreHarness ( )
239- const clipboardWrites : Array < { readonly data : string ; readonly format : string } > = [ ]
240- const cols = startColumn + selectedText . length + extraCols
241- const changedBufferType : SelectionBufferType = bufferType === "normal" ? "alternate" : "normal"
242-
243- harness . setCols ( cols )
244- harness . setBufferType ( bufferType )
245- harness . setSelection ( selectedText , startColumn , startRow )
246- harness . emitSelectionChange ( )
247- harness . setBufferType ( changedBufferType )
248- harness . setSelection ( "" , 0 , 0 )
249- harness . emitSelectionChange ( )
250- harness . host . dispatchCopy ( copyEvent ( {
251- setData : ( format : string , data : string ) => {
252- clipboardWrites . push ( { data, format } )
253- }
254- } ) )
255-
256- expect ( harness . selectCalls ) . toEqual ( [ ] )
257- expect ( clipboardWrites ) . toEqual ( [ { data : selectedText , format : "text/plain" } ] )
258-
259- harness . disposable . dispose ( )
250+ withSelectionRestoreHarness ( ( harness ) => {
251+ const clipboardWrites : Array < { readonly data : string ; readonly format : string } > = [ ]
252+ const cols = startColumn + selectedText . length + extraCols
253+ const changedBufferType : SelectionBufferType = bufferType === "normal" ? "alternate" : "normal"
254+ harness . setCols ( cols )
255+ harness . setBufferType ( bufferType )
256+ harness . setSelection ( selectedText , startColumn , startRow )
257+ harness . emitSelectionChange ( )
258+ harness . setBufferType ( changedBufferType )
259+ harness . setSelection ( "" , 0 , 0 )
260+ harness . emitSelectionChange ( )
261+ harness . host . dispatchCopy ( copyEvent ( {
262+ setData : ( format : string , data : string ) => {
263+ clipboardWrites . push ( { data, format } )
264+ }
265+ } ) )
266+ expect ( harness . selectCalls ) . toEqual ( [ ] )
267+ expect ( clipboardWrites ) . toEqual ( [ { data : selectedText , format : "text/plain" } ] )
268+ } )
260269 }
261270 ) ,
262271 { numRuns : 100 }
@@ -272,44 +281,7 @@ describe("terminal copy selection restore", () => {
272281 . toBe ( true )
273282 harness . setSelection ( "" , 0 , 0 )
274283 harness . emitSelectionChange ( )
275-
276284 expect ( harness . selectCalls ) . toEqual ( [ ] )
277-
278- harness . disposable . dispose ( )
279- } )
280-
281- it ( "does not suppress events or copy without a prior selection snapshot" , ( ) => {
282- const harness = createSelectionRestoreHarness ( )
283- const terminalMouseReports : Array < TerminalCopyTestMouseEvent > = [ ]
284- const rightClick = mouseEvent ( 2 , "mousedown" )
285- const contextMenu = mouseEvent ( 0 , "contextmenu" )
286- const copy = copyEvent ( {
287- setData : ( ) => {
288- expect . fail ( "clipboard data should not be written" )
289- }
290- } )
291- harness . host . addBubbleMouseListener ( "mousedown" , ( event ) => {
292- terminalMouseReports . push ( event )
293- } )
294- harness . host . addBubbleMouseListener ( "contextmenu" , ( event ) => {
295- terminalMouseReports . push ( event )
296- } )
297-
298- harness . emitSelectionChange ( )
299- harness . host . dispatchMouse ( "mousedown" , rightClick )
300- harness . host . dispatchMouse ( "contextmenu" , contextMenu )
301- harness . host . dispatchCopy ( copy )
302-
303- expect ( harness . selectCalls ) . toEqual ( [ ] )
304- expect ( requireKeyHandler ( harness . keyHandlers ) ( keyboardCopyEvent ) ) . toBe ( true )
305- expect ( rightClick . stopImmediatePropagationCalls ) . toBe ( 0 )
306- expect ( contextMenu . stopImmediatePropagationCalls ) . toBe ( 0 )
307- expect ( copy . preventDefaultCalls ) . toBe ( 0 )
308- expect ( harness . textarea . focusCalls ) . toBe ( 0 )
309- expect ( harness . textarea . selectCalls ) . toBe ( 0 )
310- expect ( harness . textarea . value ) . toBe ( "" )
311- expect ( terminalMouseReports ) . toEqual ( [ rightClick , contextMenu ] )
312-
313285 harness . disposable . dispose ( )
314286 } )
315287} )
0 commit comments