@@ -431,6 +431,11 @@ func (self *ViewDriver) SelectPreviousItem() *ViewDriver {
431431 return self .PressFast (self .t .keys .Universal .PrevItem )
432432}
433433
434+ // i.e. pressing '<'
435+ func (self * ViewDriver ) GotoTop () * ViewDriver {
436+ return self .PressFast (self .t .keys .Universal .GotoTop )
437+ }
438+
434439// i.e. pressing space
435440func (self * ViewDriver ) PressPrimaryAction () * ViewDriver {
436441 return self .Press (self .t .keys .Universal .Select )
@@ -457,21 +462,15 @@ func (self *ViewDriver) PressEscape() *ViewDriver {
457462// - the user is not in a list item
458463// - no list item is found containing the given text
459464// - multiple list items are found containing the given text in the initial page of items
460- //
461- // NOTE: this currently assumes that BufferLines returns all the lines that can be accessed.
462- // If this changes in future, we'll need to update this code to first attempt to find the item
463- // in the current page and failing that, jump to the top of the view and iterate through all of it,
464- // looking for the item.
465465func (self * ViewDriver ) NavigateToLine (matcher * TextMatcher ) * ViewDriver {
466466 self .IsFocused ()
467467
468468 view := self .getView ()
469469 lines := view .BufferLines ()
470470
471- var matchIndex int
471+ matchIndex := - 1
472472
473473 self .t .assertWithRetries (func () (bool , string ) {
474- matchIndex = - 1
475474 var matches []string
476475 // first we look for a duplicate on the current screen. We won't bother looking beyond that though.
477476 for i , line := range lines {
@@ -483,13 +482,19 @@ func (self *ViewDriver) NavigateToLine(matcher *TextMatcher) *ViewDriver {
483482 }
484483 if len (matches ) > 1 {
485484 return false , fmt .Sprintf ("Found %d matches for `%s`, expected only a single match. Matching lines:\n %s" , len (matches ), matcher .name (), strings .Join (matches , "\n " ))
486- } else if len (matches ) == 0 {
487- return false , fmt .Sprintf ("Could not find item matching: %s. Lines:\n %s" , matcher .name (), strings .Join (lines , "\n " ))
488- } else {
489- return true , ""
490485 }
486+ return true , ""
491487 })
492488
489+ // If no match was found, it could be that this is a view that renders only
490+ // the visible lines. In that case, we jump to the top and then press
491+ // down-arrow until we found the match. We simply return the first match we
492+ // find, so we have no way to assert that there are no duplicates.
493+ if matchIndex == - 1 {
494+ self .GotoTop ()
495+ matchIndex = len (lines )
496+ }
497+
493498 selectedLineIdx := self .getSelectedLineIdx ()
494499 if selectedLineIdx == matchIndex {
495500 return self .SelectedLine (matcher )
@@ -514,12 +519,14 @@ func (self *ViewDriver) NavigateToLine(matcher *TextMatcher) *ViewDriver {
514519 for i := 0 ; i < maxNumKeyPresses ; i ++ {
515520 keyPress ()
516521 idx := self .getSelectedLineIdx ()
517- if ok , _ := matcher .test (lines [idx ]); ok {
522+ // It is important to use view.BufferLines() here and not lines, because it
523+ // could change with every keypress.
524+ if ok , _ := matcher .test (view .BufferLines ()[idx ]); ok {
518525 return self
519526 }
520527 }
521528
522- self .t .fail (fmt .Sprintf ("Could not navigate to item matching: %s. Lines:\n %s" , matcher .name (), strings .Join (lines , "\n " )))
529+ self .t .fail (fmt .Sprintf ("Could not navigate to item matching: %s. Lines:\n %s" , matcher .name (), strings .Join (view . BufferLines () , "\n " )))
523530 return self
524531}
525532
0 commit comments