1// Copyright 2018 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package container
16
17import (
18	"errors"
19	"image"
20	"reflect"
21	"testing"
22
23	"github.com/mum4k/termdash/cell"
24	"github.com/mum4k/termdash/private/faketerm"
25)
26
27func TestRoot(t *testing.T) {
28	size := image.Point{4, 4}
29	ft, err := faketerm.New(size)
30	if err != nil {
31		t.Fatalf("faketerm.New => unexpected error: %v", err)
32	}
33	want, err := New(
34		ft,
35		SplitHorizontal(
36			Top(
37				SplitHorizontal(
38					Top(),
39					Bottom(),
40				),
41			),
42			Bottom(),
43		),
44	)
45	if err != nil {
46		t.Fatalf("New => unexpected error: %v", err)
47	}
48
49	if got := rootCont(want); got != want {
50		t.Errorf("rootCont(root) => got %p, want %p", got, want)
51	}
52
53	if got := rootCont(want.first.first); got != want {
54		t.Errorf("rootCont(root.first.first) => got %p, want %p", got, want)
55	}
56}
57
58func TestTraversal(t *testing.T) {
59	size := image.Point{4, 4}
60	ft, err := faketerm.New(size)
61	if err != nil {
62		t.Fatalf("faketerm.New => unexpected error: %v", err)
63	}
64	cont, err := New(
65		ft,
66		BorderColor(cell.ColorBlack),
67		SplitVertical(
68			Left(
69				BorderColor(cell.ColorRed),
70				SplitVertical(
71					Left(
72						BorderColor(cell.ColorYellow),
73					),
74					Right(
75						BorderColor(cell.ColorBlue),
76					),
77				),
78			),
79			Right(
80				BorderColor(cell.ColorGreen),
81				SplitVertical(
82					Left(
83						BorderColor(cell.ColorMagenta),
84					),
85					Right(
86						BorderColor(cell.ColorCyan),
87					),
88				),
89			),
90		),
91	)
92	if err != nil {
93		t.Fatalf("New => unexpected error: %v", err)
94	}
95
96	tests := []struct {
97		desc       string
98		travFunc   func(*Container, *string, visitFunc)
99		visitErr   error
100		wantColors []cell.Color
101		wantErr    bool
102	}{
103		{
104			desc:     "preOrder success",
105			travFunc: preOrder,
106			wantColors: []cell.Color{
107				cell.ColorBlack,
108				cell.ColorRed,
109				cell.ColorYellow,
110				cell.ColorBlue,
111				cell.ColorGreen,
112				cell.ColorMagenta,
113				cell.ColorCyan,
114			},
115		},
116		{
117			desc:     "preOrder error",
118			travFunc: preOrder,
119			visitErr: errors.New("visit error"),
120			wantErr:  true,
121		},
122		{
123			desc:     "postOrder success",
124			travFunc: postOrder,
125			wantColors: []cell.Color{
126				cell.ColorYellow,
127				cell.ColorBlue,
128				cell.ColorRed,
129				cell.ColorMagenta,
130				cell.ColorCyan,
131				cell.ColorGreen,
132				cell.ColorBlack,
133			},
134		},
135		{
136			desc:     "postOrder error",
137			travFunc: postOrder,
138			visitErr: errors.New("visit error"),
139			wantErr:  true,
140		},
141	}
142
143	for _, tc := range tests {
144		t.Run(tc.desc, func(t *testing.T) {
145			var (
146				errStr    string
147				gotColors []cell.Color
148			)
149
150			tc.travFunc(cont, &errStr, visitFunc(func(c *Container) error {
151				gotColors = append(gotColors, c.opts.inherited.borderColor)
152				return tc.visitErr
153			}))
154
155			if (errStr != "") != tc.wantErr {
156				t.Fatalf("traversal => unexpected error: %v, wantErr: %v", errStr, tc.wantErr)
157			}
158			if errStr != "" {
159				return
160			}
161
162			if !reflect.DeepEqual(gotColors, tc.wantColors) {
163				t.Fatalf("traversal => unexpected order\n  got:%v\n want:%v", gotColors, tc.wantColors)
164			}
165		})
166	}
167}
168
169func TestFindID(t *testing.T) {
170	tests := []struct {
171		desc      string
172		container func(ft *faketerm.Terminal) (*Container, error)
173		id        string
174		wantFound bool
175		wantErr   bool
176	}{
177		{
178			desc: "fails when searching with empty ID",
179			container: func(ft *faketerm.Terminal) (*Container, error) {
180				return New(ft)
181			},
182			wantErr: true,
183		},
184		{
185			desc: "no container with the specified ID",
186			container: func(ft *faketerm.Terminal) (*Container, error) {
187				return New(ft)
188			},
189			id:      "mycont",
190			wantErr: true,
191		},
192		{
193			desc: "finds the container",
194			container: func(ft *faketerm.Terminal) (*Container, error) {
195				return New(ft, ID("mycont"))
196			},
197			id:        "mycont",
198			wantFound: true,
199		},
200	}
201
202	for _, tc := range tests {
203		t.Run(tc.desc, func(t *testing.T) {
204			ft, err := faketerm.New(image.Point{10, 10})
205			if err != nil {
206				t.Fatalf("faketerm.New => unexpected error: %v", err)
207			}
208
209			cont, err := tc.container(ft)
210			if err != nil {
211				t.Fatalf("tc.container => unexpected error: %v", err)
212			}
213
214			got, err := findID(cont, tc.id)
215			if (err != nil) != tc.wantErr {
216				t.Errorf("findID => unexpected error: %v, wantErr: %v", err, tc.wantErr)
217			}
218			if err != nil {
219				return
220			}
221
222			if (got != nil) != tc.wantFound {
223				t.Errorf("findID returned %v, wantFound: %v", got, tc.wantFound)
224			}
225		})
226	}
227}
228