@@ -213,6 +213,89 @@ func TestSelectionPositionAndDragGuardBranches(t *testing.T) {
213213 }
214214}
215215
216+ func TestSelectionPositionAtMouseRejectsBlankViewportRows (t * testing.T ) {
217+ app , _ := newTestApp (t )
218+ app .width = 100
219+ app .height = 24
220+ app .applyComponentLayout (true )
221+ app .setTranscriptContent ("only-one-line" )
222+
223+ x , y , _ , h := app .transcriptBounds ()
224+ if h < 2 {
225+ t .Fatalf ("expected transcript viewport with spare rows, got height=%d" , h )
226+ }
227+
228+ if _ , _ , ok := app .selectionPositionAtMouse (tea.MouseMsg {X : x + 1 , Y : y + h - 1 }); ok {
229+ t .Fatalf ("expected blank viewport row to be ignored" )
230+ }
231+ }
232+
233+ func TestSetTranscriptContentClearsSelectionAfterContentChange (t * testing.T ) {
234+ app , _ := newTestApp (t )
235+ app .width = 100
236+ app .height = 24
237+ app .applyComponentLayout (true )
238+ app .setTranscriptContent ("line-one" )
239+ app .textSelection .active = true
240+ app .textSelection .startLine = 0
241+ app .textSelection .startCol = 0
242+ app .textSelection .endLine = 0
243+ app .textSelection .endCol = 4
244+ app .refreshTranscriptHighlight ()
245+
246+ app .setTranscriptContent ("line-two" )
247+ if app .textSelection .active || app .textSelection .dragging {
248+ t .Fatalf ("expected selection to be cleared after transcript content changes" )
249+ }
250+ if app .hasTextSelection () {
251+ t .Fatalf ("expected no valid selection range after transcript content changes" )
252+ }
253+ }
254+
255+ func TestUpdateTextSelectionSkipsUnchangedPosition (t * testing.T ) {
256+ app , _ := newTestApp (t )
257+ app .width = 100
258+ app .height = 24
259+ app .applyComponentLayout (true )
260+ app .setTranscriptContent ("alpha\n beta" )
261+
262+ x , y , _ , _ := app .transcriptBounds ()
263+ if ! app .beginTextSelection (tea.MouseMsg {X : x + 1 , Y : y + 1 }) {
264+ t .Fatalf ("expected beginTextSelection to succeed" )
265+ }
266+ if ! app .updateTextSelection (tea.MouseMsg {X : x + 2 , Y : y + 1 }) {
267+ t .Fatalf ("expected first updateTextSelection to succeed" )
268+ }
269+
270+ app .transcript .SetContent ("sentinel-marker" )
271+ if ! app .updateTextSelection (tea.MouseMsg {X : x + 2 , Y : y + 1 }) {
272+ t .Fatalf ("expected unchanged motion to be handled" )
273+ }
274+ if ! strings .Contains (app .transcript .View (), "sentinel-marker" ) {
275+ t .Fatalf ("expected unchanged motion to skip redraw" )
276+ }
277+ }
278+
279+ func TestHighlightTranscriptContentPreservesANSIOutsideSelection (t * testing.T ) {
280+ app , _ := newTestApp (t )
281+ app .width = 100
282+ app .height = 24
283+ app .applyComponentLayout (true )
284+ app .textSelection .active = true
285+ app .textSelection .startLine = 0
286+ app .textSelection .startCol = 6
287+ app .textSelection .endLine = 0
288+ app .textSelection .endCol = 11
289+
290+ highlighted := app .highlightTranscriptContent ("\x1b [31mhello world\x1b [0m" )
291+ if ! strings .Contains (highlighted , "\x1b [31m" ) {
292+ t .Fatalf ("expected highlighted content to preserve existing ANSI style runs" )
293+ }
294+ if plain := copyCodeANSIPattern .ReplaceAllString (highlighted , "" ); plain != "hello world" {
295+ t .Fatalf ("expected highlighted content to preserve visible text, got %q" , plain )
296+ }
297+ }
298+
216299func TestCopySelectionToClipboardNoSelectionNoop (t * testing.T ) {
217300 app , _ := newTestApp (t )
218301 app .setTranscriptContent ("hello" )
0 commit comments