mirror of https://github.com/mum4k/termdash.git
1519 lines
35 KiB
Go
1519 lines
35 KiB
Go
// Copyright 2018 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package container
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/mum4k/termdash/cell"
|
|
"github.com/mum4k/termdash/keyboard"
|
|
"github.com/mum4k/termdash/linestyle"
|
|
"github.com/mum4k/termdash/mouse"
|
|
"github.com/mum4k/termdash/private/event"
|
|
"github.com/mum4k/termdash/private/event/testevent"
|
|
"github.com/mum4k/termdash/private/faketerm"
|
|
"github.com/mum4k/termdash/terminal/terminalapi"
|
|
)
|
|
|
|
// pointCase is a test case for the pointCont function.
|
|
type pointCase struct {
|
|
desc string
|
|
point image.Point
|
|
wantNil bool
|
|
wantColor cell.Color // expected container identified by its border color
|
|
}
|
|
|
|
func TestPointCont(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
termSize image.Point
|
|
container func(ft *faketerm.Terminal) (*Container, error)
|
|
cases []pointCase
|
|
}{
|
|
{
|
|
desc: "single container, no border",
|
|
termSize: image.Point{3, 3},
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
BorderColor(cell.ColorBlue),
|
|
)
|
|
},
|
|
cases: []pointCase{
|
|
{
|
|
desc: "inside the container",
|
|
point: image.Point{1, 1},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "top left corner",
|
|
point: image.Point{0, 0},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "top right corner",
|
|
point: image.Point{2, 0},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "bottom left corner",
|
|
point: image.Point{0, 2},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "bottom right corner",
|
|
point: image.Point{2, 2},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "outside of the container, too large",
|
|
point: image.Point{3, 3},
|
|
wantNil: true,
|
|
},
|
|
{
|
|
desc: "outside of the container, too small",
|
|
point: image.Point{-1, -1},
|
|
wantNil: true,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "single container, border",
|
|
termSize: image.Point{3, 3},
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
Border(linestyle.Light),
|
|
BorderColor(cell.ColorBlue),
|
|
)
|
|
},
|
|
cases: []pointCase{
|
|
{
|
|
desc: "inside the container",
|
|
point: image.Point{1, 1},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
{
|
|
desc: "on the border",
|
|
point: image.Point{0, 1},
|
|
wantColor: cell.ColorBlue,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "split containers, parent has no border",
|
|
termSize: image.Point{10, 10},
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
BorderColor(cell.ColorBlack),
|
|
SplitVertical(
|
|
Left(
|
|
SplitHorizontal(
|
|
Top(
|
|
BorderColor(cell.ColorGreen),
|
|
),
|
|
Bottom(
|
|
BorderColor(cell.ColorWhite),
|
|
),
|
|
),
|
|
),
|
|
Right(
|
|
BorderColor(cell.ColorRed),
|
|
),
|
|
),
|
|
)
|
|
},
|
|
cases: []pointCase{
|
|
{
|
|
desc: "right sub container, inside corner",
|
|
point: image.Point{5, 5},
|
|
wantColor: cell.ColorRed,
|
|
},
|
|
{
|
|
desc: "right sub container, outside corner",
|
|
point: image.Point{9, 9},
|
|
wantColor: cell.ColorRed,
|
|
},
|
|
{
|
|
desc: "top left",
|
|
point: image.Point{0, 0},
|
|
wantColor: cell.ColorGreen,
|
|
},
|
|
{
|
|
desc: "bottom left",
|
|
point: image.Point{0, 9},
|
|
wantColor: cell.ColorWhite,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "split containers, parent has border",
|
|
termSize: image.Point{10, 10},
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
Border(linestyle.Light),
|
|
BorderColor(cell.ColorBlack),
|
|
SplitVertical(
|
|
Left(
|
|
SplitHorizontal(
|
|
Top(
|
|
BorderColor(cell.ColorGreen),
|
|
),
|
|
Bottom(
|
|
BorderColor(cell.ColorWhite),
|
|
),
|
|
),
|
|
),
|
|
Right(
|
|
BorderColor(cell.ColorRed),
|
|
),
|
|
),
|
|
)
|
|
},
|
|
cases: []pointCase{
|
|
{
|
|
desc: "right sub container, inside corner",
|
|
point: image.Point{5, 5},
|
|
wantColor: cell.ColorRed,
|
|
},
|
|
{
|
|
desc: "top right corner focuses parent",
|
|
point: image.Point{9, 9},
|
|
wantColor: cell.ColorBlack,
|
|
},
|
|
{
|
|
desc: "right sub container, outside corner",
|
|
point: image.Point{8, 8},
|
|
wantColor: cell.ColorRed,
|
|
},
|
|
{
|
|
desc: "top left focuses parent",
|
|
point: image.Point{0, 0},
|
|
wantColor: cell.ColorBlack,
|
|
},
|
|
{
|
|
desc: "top left sub container",
|
|
point: image.Point{1, 1},
|
|
wantColor: cell.ColorGreen,
|
|
},
|
|
{
|
|
desc: "bottom left focuses parent",
|
|
point: image.Point{0, 9},
|
|
wantColor: cell.ColorBlack,
|
|
},
|
|
{
|
|
desc: "bottom left sub container",
|
|
point: image.Point{1, 8},
|
|
wantColor: cell.ColorWhite,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
ft, err := faketerm.New(tc.termSize)
|
|
if err != nil {
|
|
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
|
}
|
|
|
|
cont, err := tc.container(ft)
|
|
if err != nil {
|
|
t.Fatalf("tc.container => unexpected error: %v", err)
|
|
}
|
|
// Initial draw to determine sizes of containers.
|
|
if err := cont.Draw(); err != nil {
|
|
t.Fatalf("Draw => unexpected error: %v", err)
|
|
}
|
|
for _, pc := range tc.cases {
|
|
gotCont := pointCont(cont, pc.point)
|
|
if (gotCont == nil) != pc.wantNil {
|
|
t.Errorf("%s, pointCont%v => got %v, wantNil: %v", pc.desc, pc.point, gotCont, pc.wantNil)
|
|
}
|
|
if gotCont == nil {
|
|
continue
|
|
}
|
|
|
|
gotColor := gotCont.opts.inherited.borderColor
|
|
if gotColor != pc.wantColor {
|
|
t.Errorf("%s, pointCont%v => got container with border color %v, want %v", pc.desc, pc.point, gotColor, pc.wantColor)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// contLocIntro3 prints out an introduction explaining the used container
|
|
// locations on test failures.
|
|
func contLocIntro3() string {
|
|
var s strings.Builder
|
|
s.WriteString("Container locations refer to containers in the following tree, i.e. contLocA is the root container:\n")
|
|
s.WriteString(`
|
|
A
|
|
/ \
|
|
B C
|
|
`)
|
|
return s.String()
|
|
}
|
|
|
|
// contLocIntro5 prints out an introduction explaining the used container
|
|
// locations on test failures.
|
|
func contLocIntro5() string {
|
|
var s strings.Builder
|
|
s.WriteString("Container locations refer to containers in the following tree, i.e. contLocA is the root container:\n")
|
|
s.WriteString(`
|
|
A
|
|
/ \
|
|
B C
|
|
/ \
|
|
D E
|
|
`)
|
|
return s.String()
|
|
}
|
|
|
|
// contLoc is used in tests to indicate the desired location of a container.
|
|
type contLoc int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (cl contLoc) String() string {
|
|
if n, ok := contLocNames[cl]; ok {
|
|
return n
|
|
}
|
|
return "contLocUnknown"
|
|
}
|
|
|
|
// contLocNames maps contLoc values to human readable names.
|
|
var contLocNames = map[contLoc]string{
|
|
contLocA: "contLocA",
|
|
contLocB: "contLocB",
|
|
contLocC: "contLocC",
|
|
contLocD: "contLocD",
|
|
contLocE: "contLocE",
|
|
}
|
|
|
|
const (
|
|
contLocUnknown contLoc = iota
|
|
contLocA
|
|
contLocB
|
|
contLocC
|
|
contLocD
|
|
contLocE
|
|
)
|
|
|
|
func TestFocusTrackerMouse(t *testing.T) {
|
|
t.Log(contLocIntro3())
|
|
|
|
ft, err := faketerm.New(image.Point{10, 10})
|
|
if err != nil {
|
|
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
|
}
|
|
|
|
var (
|
|
insideB = image.Point{1, 1}
|
|
insideC = image.Point{6, 6}
|
|
)
|
|
|
|
tests := []struct {
|
|
desc string
|
|
// Can be either the mouse event or a time.Duration to pause for.
|
|
events []*terminalapi.Mouse
|
|
wantFocused contLoc
|
|
wantProcessed int
|
|
}{
|
|
{
|
|
desc: "initially the root is focused",
|
|
wantFocused: contLocA,
|
|
},
|
|
{
|
|
desc: "click and release moves focus to the left",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: image.Point{0, 0}, Button: mouse.ButtonLeft},
|
|
{Position: image.Point{1, 1}, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "click and release moves focus to the right",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: image.Point{5, 5}, Button: mouse.ButtonLeft},
|
|
{Position: image.Point{6, 6}, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "click in the same container is a no-op",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideC, Button: mouse.ButtonRelease},
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideC, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 4,
|
|
},
|
|
{
|
|
desc: "click in the same container and release never happens",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideB, Button: mouse.ButtonLeft},
|
|
{Position: insideB, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "click in the same container, release elsewhere",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideB, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "other buttons are ignored",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideB, Button: mouse.ButtonMiddle},
|
|
{Position: insideB, Button: mouse.ButtonRelease},
|
|
{Position: insideB, Button: mouse.ButtonRight},
|
|
{Position: insideB, Button: mouse.ButtonRelease},
|
|
{Position: insideB, Button: mouse.ButtonWheelUp},
|
|
{Position: insideB, Button: mouse.ButtonWheelDown},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 6,
|
|
},
|
|
{
|
|
desc: "moving mouse with pressed button and then releasing moves focus",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: image.Point{0, 0}, Button: mouse.ButtonLeft},
|
|
{Position: image.Point{1, 1}, Button: mouse.ButtonLeft},
|
|
{Position: image.Point{2, 2}, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "click ignored if followed by another click of the same button elsewhere",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideB, Button: mouse.ButtonLeft},
|
|
{Position: insideC, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "click ignored if followed by another click of a different button",
|
|
events: []*terminalapi.Mouse{
|
|
{Position: insideC, Button: mouse.ButtonLeft},
|
|
{Position: insideC, Button: mouse.ButtonMiddle},
|
|
{Position: insideC, Button: mouse.ButtonRelease},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 3,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
root, err := New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("New => unexpected error: %v", err)
|
|
}
|
|
|
|
eds := event.NewDistributionSystem()
|
|
root.Subscribe(eds)
|
|
// Initial draw to determine sizes of containers.
|
|
if err := root.Draw(); err != nil {
|
|
t.Fatalf("Draw => unexpected error: %v", err)
|
|
}
|
|
for _, ev := range tc.events {
|
|
eds.Event(ev)
|
|
}
|
|
if err := testevent.WaitFor(5*time.Second, func() error {
|
|
if got, want := eds.Processed(), tc.wantProcessed; got != want {
|
|
return fmt.Errorf("the event distribution system processed %d events, want %d", got, want)
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
t.Fatalf("testevent.WaitFor => %v", err)
|
|
}
|
|
|
|
var wantFocused *Container
|
|
switch wf := tc.wantFocused; wf {
|
|
case contLocA:
|
|
wantFocused = root
|
|
case contLocB:
|
|
wantFocused = root.first
|
|
case contLocC:
|
|
wantFocused = root.second
|
|
default:
|
|
t.Fatalf("unsupported wantFocused value => %v", wf)
|
|
}
|
|
|
|
if !root.focusTracker.isActive(wantFocused) {
|
|
t.Errorf("isActive(%v) => false, want true, status: contLocA(%v):%v, contLocB(%v):%v, contLocC(%v):%v",
|
|
tc.wantFocused,
|
|
contLocA, root.focusTracker.isActive(root),
|
|
contLocB, root.focusTracker.isActive(root.first),
|
|
contLocC, root.focusTracker.isActive(root.second),
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// contDir represents a direction in which we want to change container focus.
|
|
type contDir int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (cd contDir) String() string {
|
|
if n, ok := contDirNames[cd]; ok {
|
|
return n
|
|
}
|
|
return "contDirUnknown"
|
|
}
|
|
|
|
// contDirNames maps contDir values to human readable names.
|
|
var contDirNames = map[contDir]string{
|
|
contDirNext: "contDirNext",
|
|
contDirPrevious: "contDirPrevious",
|
|
}
|
|
|
|
const (
|
|
contDirUnknown contDir = iota
|
|
contDirNext
|
|
contDirPrevious
|
|
)
|
|
|
|
// contSize determines the size of the container used in the test.
|
|
type contSize int
|
|
|
|
const (
|
|
contSize3 contSize = iota
|
|
contSize5
|
|
)
|
|
|
|
func TestFocusTrackerNextAndPrevious(t *testing.T) {
|
|
ft, err := faketerm.New(image.Point{10, 10})
|
|
if err != nil {
|
|
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
|
}
|
|
|
|
const (
|
|
keyNext keyboard.Key = keyboard.KeyTab
|
|
keyPrevious keyboard.Key = '~'
|
|
)
|
|
|
|
tests := []struct {
|
|
desc string
|
|
contSize contSize
|
|
container func(ft *faketerm.Terminal) (*Container, error)
|
|
events []*terminalapi.Keyboard
|
|
wantFocused contLoc
|
|
wantProcessed int
|
|
}{
|
|
{
|
|
desc: "initially the root is focused by default",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
wantFocused: contLocA,
|
|
},
|
|
{
|
|
desc: "focus root explicitly",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
Focused(),
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
wantFocused: contLocA,
|
|
},
|
|
{
|
|
desc: "focus can be set to a container other than root",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(Focused()),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
wantFocused: contLocB,
|
|
},
|
|
{
|
|
desc: "option Focused used on multiple containers, the last one takes effect",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(Focused()),
|
|
Right(Focused()),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
wantFocused: contLocC,
|
|
},
|
|
{
|
|
desc: "keyNext does nothing when only root exists",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "keyNext focuses the first container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "two keyNext presses focuses the second container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "three keyNext presses focuses the first container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "four keyNext presses focuses the second container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 4,
|
|
},
|
|
{
|
|
desc: "five keyNext presses focuses the first container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 5,
|
|
},
|
|
{
|
|
desc: "keyPrevious does nothing when only root exists",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "keyPrevious focuses the last container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "two keyPrevious presses focuses the first container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "three keyPrevious presses focuses the second container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "four keyPrevious presses focuses the first container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 4,
|
|
},
|
|
{
|
|
desc: "five keyPrevious presses focuses the second container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 5,
|
|
},
|
|
{
|
|
desc: "first container requests to be skipped on key based focus changes, using next",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
),
|
|
Right(),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "last container requests to be skipped on key based focus changes, using next",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "all containers request to be skipped on key based focus changes, using next",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
),
|
|
),
|
|
KeyFocusNext(keyNext),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyNext},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "first container requests to be skipped on key based focus changes, using previous",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
),
|
|
Right(),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "last container requests to be skipped on key based focus changes, using previous",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "all containers request to be skipped on key based focus changes, using previous",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
),
|
|
),
|
|
KeyFocusPrevious(keyPrevious),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: keyPrevious},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "containers don't belong to focus group by default",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
SplitVertical(
|
|
Left(),
|
|
Right(),
|
|
),
|
|
KeyFocusGroupsNext('n', 0),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
},
|
|
wantFocused: contLocA,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "moves to the next container in focus group, pressing KeysFocusGroupNext once focuses the first container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "moves to the next container in focus group, pressing KeysFocusGroupNext twice focuses the second container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
{Key: 'n'},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "moves to the next container in focus group, pressing KeysFocusGroupNext three times focuses the first container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(2),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(2),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(2),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
{Key: 'n'},
|
|
{Key: 'n'},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "moves to the previous container in focus group, pressing KeysFocusGroupPrevious once focuses the second container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsPrevious('p', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'p'},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "moves to the previous container in focus group, pressing KeysFocusGroupPrevious twice focuses the first container",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsPrevious('p', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'p'},
|
|
{Key: 'p'},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "moves to the previous container in focus group, pressing KeysFocusGroupPrevious three times focuses the second container again",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsPrevious('p', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'p'},
|
|
{Key: 'p'},
|
|
{Key: 'p'},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "configuring container with KeyFocusSkip has no effect on a closed focus group",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 1,
|
|
},
|
|
{
|
|
desc: "a focus group can have multiple keys configured for next",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusSkip(),
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusSkip(),
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
KeyFocusGroupsNext(keyboard.KeyArrowRight, 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
{Key: keyboard.KeyArrowRight},
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "a focus group can have multiple keys configured for previous",
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New(
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left(
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right(
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsPrevious('n', 1),
|
|
KeyFocusGroupsPrevious(keyboard.KeyArrowRight, 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'},
|
|
{Key: keyboard.KeyArrowRight},
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "a container can be in multiple focus groups, rotates within group while on next",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
KeyFocusGroupsNext(keyboard.KeyArrowRight, 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocD
|
|
{Key: 'n'}, // focuses contLocE
|
|
{Key: keyboard.KeyArrowRight}, // focuses contLocC
|
|
{Key: keyboard.KeyArrowRight}, // rotates focus to contLocE
|
|
},
|
|
wantFocused: contLocE,
|
|
wantProcessed: 4,
|
|
},
|
|
{
|
|
desc: "a container can be in multiple focus groups, rotates within group while on previous",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
KeyFocusGroupsPrevious('n', 1),
|
|
KeyFocusGroupsPrevious(keyboard.KeyArrowLeft, 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocC
|
|
{Key: keyboard.KeyArrowLeft}, // focuses contLocE
|
|
{Key: keyboard.KeyArrowLeft}, // rotates focus back to contLocC
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 3,
|
|
},
|
|
{
|
|
desc: "same key and group, first group takes priority, group 1 is first",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
KeyFocusGroupsNext('n', 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocD
|
|
{Key: 'n'}, // focuses contLocE
|
|
},
|
|
wantFocused: contLocE,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "same key and group, first group takes priority, group 2 is first",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(2, 1),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
KeyFocusGroupsNext('n', 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocD
|
|
{Key: 'n'}, // focuses contLocC
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "KeyFocusGroups called multiple times, same key and group, first group takes priority, group 2 is first",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(2),
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1, 2),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
KeyFocusGroupsNext('n', 2),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocD
|
|
{Key: 'n'}, // focuses contLocC
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "global KeyFocusNext moves focus out of a focus group",
|
|
contSize: contSize3,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right( // contLocC
|
|
),
|
|
),
|
|
KeyFocusNext('n'),
|
|
KeyFocusGroupsNext(keyboard.KeyArrowRight, 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocB in focus group 1
|
|
{Key: 'n'}, // focuses contLocC
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "global KeyFocusPrevious moves focus out of a focus group",
|
|
contSize: contSize3,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusPrevious('p'),
|
|
KeyFocusGroupsPrevious(keyboard.KeyArrowLeft, 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'p'}, // focuses contLocC in focus group 1
|
|
{Key: 'p'}, // focuses contLocB
|
|
},
|
|
wantFocused: contLocB,
|
|
wantProcessed: 2,
|
|
},
|
|
{
|
|
desc: "KeyFocusGroups with no arguments removes all groups",
|
|
contSize: contSize5,
|
|
container: func(ft *faketerm.Terminal) (*Container, error) {
|
|
return New( // contLocA
|
|
ft,
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocB
|
|
KeyFocusGroups(1),
|
|
SplitVertical(
|
|
Left( // contLocD
|
|
KeyFocusGroups(1),
|
|
),
|
|
Right( // contLocE
|
|
KeyFocusGroups(1),
|
|
KeyFocusGroups(),
|
|
),
|
|
),
|
|
),
|
|
Right( // contLocC
|
|
KeyFocusGroups(1),
|
|
),
|
|
),
|
|
KeyFocusGroupsNext('n', 1),
|
|
)
|
|
},
|
|
events: []*terminalapi.Keyboard{
|
|
{Key: 'n'}, // focuses contLocD
|
|
{Key: 'n'}, // focuses contLocC
|
|
},
|
|
wantFocused: contLocC,
|
|
wantProcessed: 2,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
root, err := tc.container(ft)
|
|
if err != nil {
|
|
t.Fatalf("tc.container => unexpected error: %v", err)
|
|
}
|
|
|
|
eds := event.NewDistributionSystem()
|
|
root.Subscribe(eds)
|
|
for _, ev := range tc.events {
|
|
eds.Event(ev)
|
|
}
|
|
if err := testevent.WaitFor(5*time.Second, func() error {
|
|
if got, want := eds.Processed(), tc.wantProcessed; got != want {
|
|
return fmt.Errorf("the event distribution system processed %d events, want %d", got, want)
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
t.Fatalf("testevent.WaitFor => %v", err)
|
|
}
|
|
|
|
var wantFocused *Container
|
|
switch wf := tc.wantFocused; wf {
|
|
case contLocA:
|
|
wantFocused = root
|
|
case contLocB:
|
|
wantFocused = root.first
|
|
case contLocC:
|
|
wantFocused = root.second
|
|
case contLocD:
|
|
wantFocused = root.first.first
|
|
case contLocE:
|
|
wantFocused = root.first.second
|
|
default:
|
|
t.Fatalf("unsupported wantFocused value => %v", wf)
|
|
}
|
|
|
|
switch tc.contSize {
|
|
case contSize3:
|
|
t.Log(contLocIntro3())
|
|
if !root.focusTracker.isActive(wantFocused) {
|
|
t.Errorf("isActive(%v) => false, want true, status: %v:%v, %v:%v, %v:%v",
|
|
tc.wantFocused,
|
|
contLocA, root.focusTracker.isActive(root),
|
|
contLocB, root.focusTracker.isActive(root.first),
|
|
contLocC, root.focusTracker.isActive(root.second),
|
|
)
|
|
}
|
|
|
|
case contSize5:
|
|
t.Log(contLocIntro5())
|
|
if !root.focusTracker.isActive(wantFocused) {
|
|
t.Errorf("isActive(%v) => false, want true, status: %v:%v, %v:%v, %v:%v, %v:%v, %v:%v",
|
|
tc.wantFocused,
|
|
contLocA, root.focusTracker.isActive(root),
|
|
contLocB, root.focusTracker.isActive(root.first),
|
|
contLocC, root.focusTracker.isActive(root.second),
|
|
contLocD, root.focusTracker.isActive(root.first.first),
|
|
contLocE, root.focusTracker.isActive(root.first.second),
|
|
)
|
|
}
|
|
default:
|
|
t.Errorf("unknown contSize: %v", tc.contSize)
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|