package buffer import "testing" func TestNoSelectionByDefault(t *testing.T) { b := NewFromString("abc") if _, ok := b.Selection(); ok { t.Error("a fresh buffer must have no selection") } if got := b.SelectedText(); got != "" { t.Errorf("SelectedText() = %q, want empty", got) } } func TestSelectionExtendsFromTheAnchor(t *testing.T) { b := NewFromString("hello world") b.SetCursor(Position{Line: 0, Col: 6}) b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 0, Col: 11}) r, ok := b.Selection() if !ok { t.Fatal("Selection() reported none after extending from an anchor") } if r.Start != (Position{Line: 0, Col: 6}) || r.End != (Position{Line: 0, Col: 11}) { t.Errorf("Selection() = %+v, want columns 6 to 11", r) } if got := b.SelectedText(); got != "world" { t.Errorf("SelectedText() = %q, want %q", got, "world") } } func TestSelectionIsOrderedWhenTheCursorGoesBackwards(t *testing.T) { b := NewFromString("hello world") b.SetCursor(Position{Line: 0, Col: 5}) b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 0, Col: 0}) if got := b.SelectedText(); got != "hello" { t.Errorf("SelectedText() = %q, want %q even though the cursor moved left", got, "hello") } } func TestSelectionSpanningLinesJoinsWithLineFeeds(t *testing.T) { b := NewFromString("one\r\ntwo\r\nthree\r\n") b.SetCursor(Position{Line: 0, Col: 1}) b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 2, Col: 2}) if got := b.SelectedText(); got != "ne\ntwo\nth" { t.Errorf("SelectedText() = %q, want line feeds regardless of the file's CRLF endings", got) } } func TestSelectionCollapsedOntoItsAnchorCountsAsAbsent(t *testing.T) { b := NewFromString("abc") b.SetCursor(Position{Line: 0, Col: 1}) b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 0, Col: 2}) b.SetCursorKeepingSelection(Position{Line: 0, Col: 1}) if _, ok := b.Selection(); ok { t.Error("a selection reduced to nothing must report as absent") } } func TestClearSelectionDropsTheAnchor(t *testing.T) { b := NewFromString("abc") b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 0, Col: 3}) b.ClearSelection() if _, ok := b.Selection(); ok { t.Error("ClearSelection left a selection behind") } } func TestSetCursorDropsTheSelectionButSetCursorKeepingSelectionDoesNot(t *testing.T) { b := NewFromString("abcdef") b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 0, Col: 3}) if _, ok := b.Selection(); !ok { t.Fatal("SetCursorKeepingSelection must keep the anchor") } b.SetCursor(Position{Line: 0, Col: 5}) if _, ok := b.Selection(); ok { t.Error("SetCursor must drop the anchor") } } func TestSelectAllCoversTheWholeBuffer(t *testing.T) { b := NewFromString("one\ntwo") b.SelectAll() if got := b.SelectedText(); got != "one\ntwo" { t.Errorf("SelectedText() = %q, want the whole text", got) } if got := b.Cursor(); got != (Position{Line: 1, Col: 3}) { t.Errorf("Cursor() = %+v, want the end of the buffer", got) } } func TestDeleteSelectionRemovesItAndReportsSo(t *testing.T) { b := NewFromString("one\ntwo\nthree") b.SetCursor(Position{Line: 0, Col: 1}) b.StartSelection() b.SetCursorKeepingSelection(Position{Line: 2, Col: 2}) if !b.DeleteSelection() { t.Fatal("DeleteSelection() = false, want true when something is selected") } if got := b.Text(); got != "oree" { t.Errorf("Text() = %q, want %q", got, "oree") } if got := b.Cursor(); got != (Position{Line: 0, Col: 1}) { t.Errorf("Cursor() = %+v, want the start of the deleted span", got) } } func TestDeleteSelectionWithoutOneChangesNothing(t *testing.T) { b := NewFromString("abc") if b.DeleteSelection() { t.Error("DeleteSelection() = true, want false when nothing is selected") } if got := b.Text(); got != "abc" { t.Errorf("Text() = %q, want it unchanged", got) } if b.Modified() { t.Error("DeleteSelection with no selection must not mark the buffer modified") } }