Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: ui/views/controls/table/table_view_unittest.cc

Issue 2780833004: Improve TableView unit tests and fix bugs that were uncovered. (Closed)
Patch Set: fix TapOnRow for desktop linux Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/table/table_view.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/table/table_view.h" 5 #include "ui/views/controls/table/table_view.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/events/event_utils.h" 13 #include "ui/events/event_utils.h"
14 #include "ui/events/test/event_generator.h"
14 #include "ui/views/controls/table/table_grouper.h" 15 #include "ui/views/controls/table/table_grouper.h"
15 #include "ui/views/controls/table/table_header.h" 16 #include "ui/views/controls/table/table_header.h"
16 #include "ui/views/controls/table/table_view_observer.h" 17 #include "ui/views/controls/table/table_view_observer.h"
18 #include "ui/views/test/views_test_base.h"
17 19
18 // Put the tests in the views namespace to make it easier to declare them as 20 // Put the tests in the views namespace to make it easier to declare them as
19 // friend classes. 21 // friend classes.
20 namespace views { 22 namespace views {
21 23
22 class TableViewTestHelper { 24 class TableViewTestHelper {
23 public: 25 public:
24 explicit TableViewTestHelper(TableView* table) : table_(table) {} 26 explicit TableViewTestHelper(TableView* table) : table_(table) {}
25 27
26 std::string GetPaintRegion(const gfx::Rect& bounds) { 28 std::string GetPaintRegion(const gfx::Rect& bounds) {
27 TableView::PaintRegion region(table_->GetPaintRegion(bounds)); 29 TableView::PaintRegion region(table_->GetPaintRegion(bounds));
28 return "rows=" + base::IntToString(region.min_row) + " " + 30 return "rows=" + base::IntToString(region.min_row) + " " +
29 base::IntToString(region.max_row) + " cols=" + 31 base::IntToString(region.max_row) + " cols=" +
30 base::IntToString(region.min_column) + " " + 32 base::IntToString(region.min_column) + " " +
31 base::IntToString(region.max_column); 33 base::IntToString(region.max_column);
32 } 34 }
33 35
34 size_t visible_col_count() { 36 size_t visible_col_count() {
35 return table_->visible_columns().size(); 37 return table_->visible_columns().size();
36 } 38 }
37 39
38 TableHeader* header() { return table_->header_; } 40 TableHeader* header() { return table_->header_; }
39 41
40 void SetSelectionModel(const ui::ListSelectionModel& new_selection) { 42 void SetSelectionModel(const ui::ListSelectionModel& new_selection) {
41 table_->SetSelectionModel(new_selection); 43 table_->SetSelectionModel(new_selection);
42 } 44 }
43 45
44 void OnFocus() {
45 table_->OnFocus();
46 }
47
48 private: 46 private:
49 TableView* table_; 47 TableView* table_;
50 48
51 DISALLOW_COPY_AND_ASSIGN(TableViewTestHelper); 49 DISALLOW_COPY_AND_ASSIGN(TableViewTestHelper);
52 }; 50 };
53 51
54 namespace { 52 namespace {
55 53
56 // TestTableModel2 ------------------------------------------------------------- 54 // TestTableModel2 -------------------------------------------------------------
57 55
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 result += ", "; // Comma between each value in the row. 175 result += ", "; // Comma between each value in the row.
178 176
179 result += base::UTF16ToUTF8( 177 result += base::UTF16ToUTF8(
180 table->model()->GetText(table->ViewToModel(i), column.id)); 178 table->model()->GetText(table->ViewToModel(i), column.id));
181 } 179 }
182 result += "]"; 180 result += "]";
183 } 181 }
184 return result; 182 return result;
185 } 183 }
186 184
187 class TestTableView : public TableView {
188 public:
189 TestTableView(ui::TableModel* model,
190 const std::vector<ui::TableColumn>& columns)
191 : TableView(model, columns, TEXT_ONLY, false) {
192 }
193
194 // View overrides:
195 bool HasFocus() const override {
196 // Overriden so key processing works.
197 return true;
198 }
199
200 private:
201 DISALLOW_COPY_AND_ASSIGN(TestTableView);
202 };
203
204 } // namespace 185 } // namespace
205 186
206 class TableViewTest : public testing::Test { 187 class TableViewTest : public ViewsTestBase {
207 public: 188 public:
208 TableViewTest() : table_(NULL) {} 189 TableViewTest() : table_(NULL) {}
209 190
210 void SetUp() override { 191 void SetUp() override {
192 ViewsTestBase::SetUp();
193
211 model_.reset(new TestTableModel2); 194 model_.reset(new TestTableModel2);
212 std::vector<ui::TableColumn> columns(2); 195 std::vector<ui::TableColumn> columns(2);
213 columns[0].title = base::ASCIIToUTF16("Title Column 0"); 196 columns[0].title = base::ASCIIToUTF16("Title Column 0");
214 columns[0].sortable = true; 197 columns[0].sortable = true;
215 columns[1].title = base::ASCIIToUTF16("Title Column 1"); 198 columns[1].title = base::ASCIIToUTF16("Title Column 1");
216 columns[1].id = 1; 199 columns[1].id = 1;
217 columns[1].sortable = true; 200 columns[1].sortable = true;
218 table_ = new TestTableView(model_.get(), columns); 201 table_ = new TableView(model_.get(), columns, TEXT_ONLY, false);
219 parent_.reset(table_->CreateParentIfNecessary()); 202 View* parent = table_->CreateParentIfNecessary();
220 parent_->SetBounds(0, 0, 10000, 10000); 203 parent->SetBounds(0, 0, 10000, 10000);
221 parent_->Layout(); 204 parent->Layout();
222 helper_.reset(new TableViewTestHelper(table_)); 205 helper_.reset(new TableViewTestHelper(table_));
206
207 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
208 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
209 params.bounds = gfx::Rect(0, 0, 650, 650);
tapted 2017/04/04 00:07:36 Offsetting the (x,y) coordinate here might resolve
210 widget_.reset(new Widget);
211 widget_->Init(params);
212 widget_->GetContentsView()->AddChildView(parent);
213 widget_->Show();
214 }
215
216 void TearDown() override {
217 widget_.reset();
218 ViewsTestBase::TearDown();
223 } 219 }
224 220
225 void ClickOnRow(int row, int flags) { 221 void ClickOnRow(int row, int flags) {
226 const int y = row * table_->row_height(); 222 ui::test::EventGenerator generator(widget_->GetNativeWindow());
227 const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(0, y), 223 generator.set_flags(flags);
228 gfx::Point(0, y), ui::EventTimeForNow(), 224 generator.set_current_location(GetPointForRow(row));
229 ui::EF_LEFT_MOUSE_BUTTON | flags, 225 generator.PressLeftButton();
230 ui::EF_LEFT_MOUSE_BUTTON);
231 table_->OnMousePressed(pressed);
232 } 226 }
233 227
234 void TapOnRow(int row) { 228 void TapOnRow(int row) {
235 const int y = row * table_->row_height(); 229 ui::test::EventGenerator generator(widget_->GetNativeWindow());
236 const ui::GestureEventDetails event_details(ui::ET_GESTURE_TAP); 230 generator.GestureTapAt(GetPointForRow(row));
237 ui::GestureEvent tap(0, y, 0, base::TimeTicks(), event_details);
238 table_->OnGestureEvent(&tap);
239 } 231 }
240 232
241 // Returns the state of the selection model as a string. The format is: 233 // Returns the state of the selection model as a string. The format is:
242 // 'active=X anchor=X selection=X X X...'. 234 // 'active=X anchor=X selection=X X X...'.
243 std::string SelectionStateAsString() const { 235 std::string SelectionStateAsString() const {
244 const ui::ListSelectionModel& model(table_->selection_model()); 236 const ui::ListSelectionModel& model(table_->selection_model());
245 std::string result = "active=" + base::IntToString(model.active()) + 237 std::string result = "active=" + base::IntToString(model.active()) +
246 " anchor=" + base::IntToString(model.anchor()) + 238 " anchor=" + base::IntToString(model.anchor()) +
247 " selection="; 239 " selection=";
248 const ui::ListSelectionModel::SelectedIndices& selection( 240 const ui::ListSelectionModel::SelectedIndices& selection(
249 model.selected_indices()); 241 model.selected_indices());
250 for (size_t i = 0; i < selection.size(); ++i) { 242 for (size_t i = 0; i < selection.size(); ++i) {
251 if (i != 0) 243 if (i != 0)
252 result += " "; 244 result += " ";
253 result += base::IntToString(selection[i]); 245 result += base::IntToString(selection[i]);
254 } 246 }
255 return result; 247 return result;
256 } 248 }
257 249
258 void PressKey(ui::KeyboardCode code) { 250 void PressKey(ui::KeyboardCode code) {
259 ui::KeyEvent event(ui::ET_KEY_PRESSED, code, ui::EF_NONE); 251 ui::test::EventGenerator generator(widget_->GetNativeWindow());
260 table_->OnKeyPressed(event); 252 generator.PressKey(code, ui::EF_NONE);
261 } 253 }
262 254
263 protected: 255 protected:
264 std::unique_ptr<TestTableModel2> model_; 256 std::unique_ptr<TestTableModel2> model_;
265 257
266 // Owned by |parent_|. 258 // Owned by |parent_|.
267 TableView* table_; 259 TableView* table_;
268 260
269 std::unique_ptr<TableViewTestHelper> helper_; 261 std::unique_ptr<TableViewTestHelper> helper_;
270 262
271 private: 263 private:
272 std::unique_ptr<View> parent_; 264 gfx::Point GetPointForRow(int row) {
265 const int y = (row + 0.5) * table_->row_height();
266 return table_->GetBoundsInScreen().origin() + gfx::Vector2d(5, y);
267 }
268
269 std::unique_ptr<Widget> widget_;
273 270
274 DISALLOW_COPY_AND_ASSIGN(TableViewTest); 271 DISALLOW_COPY_AND_ASSIGN(TableViewTest);
275 }; 272 };
276 273
277 // Verifies GetPaintRegion. 274 // Verifies GetPaintRegion.
278 TEST_F(TableViewTest, GetPaintRegion) { 275 TEST_F(TableViewTest, GetPaintRegion) {
279 // Two columns should be visible. 276 // Two columns should be visible.
280 EXPECT_EQ(2u, helper_->visible_col_count()); 277 EXPECT_EQ(2u, helper_->visible_col_count());
281 278
282 EXPECT_EQ("rows=0 4 cols=0 2", helper_->GetPaintRegion(table_->bounds())); 279 EXPECT_EQ("rows=0 4 cols=0 2", helper_->GetPaintRegion(table_->bounds()));
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 } 725 }
729 726
730 // Verifies selection works by way of a gesture. 727 // Verifies selection works by way of a gesture.
731 TEST_F(TableViewTest, SelectOnTap) { 728 TEST_F(TableViewTest, SelectOnTap) {
732 // Initially no selection. 729 // Initially no selection.
733 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); 730 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
734 731
735 TableViewObserverImpl observer; 732 TableViewObserverImpl observer;
736 table_->set_observer(&observer); 733 table_->set_observer(&observer);
737 734
738 // Click on the first row, should select it. 735 // Tap on the first row, should select it.
739 TapOnRow(0); 736 TapOnRow(0);
740 EXPECT_EQ(1, observer.GetChangedCountAndClear()); 737 EXPECT_EQ(1, observer.GetChangedCountAndClear());
741 EXPECT_EQ("active=0 anchor=0 selection=0", SelectionStateAsString()); 738 EXPECT_EQ("active=0 anchor=0 selection=0", SelectionStateAsString());
742 739
743 table_->set_observer(NULL); 740 table_->set_observer(NULL);
744 } 741 }
745 742
746 // Verifies up/down correctly navigates through groups. 743 // Verifies up/down correctly navigates through groups.
747 TEST_F(TableViewTest, KeyUpDown) { 744 TEST_F(TableViewTest, KeyUpDown) {
748 // Configure the grouper so that there are three groups: 745 // Configure the grouper so that there are three groups:
749 // A 0 746 // A 0
750 // 1 747 // 1
751 // B 5 748 // B 5
752 // C 2 749 // C 2
753 // 3 750 // 3
754 model_->AddRow(2, 5, 0); 751 model_->AddRow(2, 5, 0);
755 TableGrouperImpl grouper; 752 TableGrouperImpl grouper;
756 std::vector<int> ranges; 753 std::vector<int> ranges;
757 ranges.push_back(2); 754 ranges.push_back(2);
758 ranges.push_back(1); 755 ranges.push_back(1);
759 ranges.push_back(2); 756 ranges.push_back(2);
760 grouper.SetRanges(ranges); 757 grouper.SetRanges(ranges);
761 table_->SetGrouper(&grouper); 758 table_->SetGrouper(&grouper);
762 759
763 TableViewObserverImpl observer; 760 TableViewObserverImpl observer;
764 table_->set_observer(&observer); 761 table_->set_observer(&observer);
762 table_->RequestFocus();
765 763
766 // Initially no selection. 764 // Initially no selection.
767 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); 765 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
768 766
769 PressKey(ui::VKEY_DOWN); 767 PressKey(ui::VKEY_DOWN);
770 EXPECT_EQ(1, observer.GetChangedCountAndClear()); 768 EXPECT_EQ(1, observer.GetChangedCountAndClear());
771 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString()); 769 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
772 770
773 PressKey(ui::VKEY_DOWN); 771 PressKey(ui::VKEY_DOWN);
774 EXPECT_EQ(1, observer.GetChangedCountAndClear()); 772 EXPECT_EQ(1, observer.GetChangedCountAndClear());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 TableGrouperImpl grouper; 883 TableGrouperImpl grouper;
886 std::vector<int> ranges; 884 std::vector<int> ranges;
887 ranges.push_back(2); 885 ranges.push_back(2);
888 ranges.push_back(1); 886 ranges.push_back(1);
889 ranges.push_back(2); 887 ranges.push_back(2);
890 grouper.SetRanges(ranges); 888 grouper.SetRanges(ranges);
891 table_->SetGrouper(&grouper); 889 table_->SetGrouper(&grouper);
892 890
893 TableViewObserverImpl observer; 891 TableViewObserverImpl observer;
894 table_->set_observer(&observer); 892 table_->set_observer(&observer);
893 table_->RequestFocus();
895 894
896 // Initially no selection. 895 // Initially no selection.
897 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); 896 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
898 897
899 PressKey(ui::VKEY_HOME); 898 PressKey(ui::VKEY_HOME);
900 EXPECT_EQ(1, observer.GetChangedCountAndClear()); 899 EXPECT_EQ(1, observer.GetChangedCountAndClear());
901 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString()); 900 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
902 901
903 PressKey(ui::VKEY_END); 902 PressKey(ui::VKEY_END);
904 EXPECT_EQ(1, observer.GetChangedCountAndClear()); 903 EXPECT_EQ(1, observer.GetChangedCountAndClear());
905 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString()); 904 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
906 905
906 PressKey(ui::VKEY_HOME);
907 EXPECT_EQ(1, observer.GetChangedCountAndClear());
908 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
909
907 table_->set_observer(NULL); 910 table_->set_observer(NULL);
908 } 911 }
909 912
910 // Verifies multiple selection gestures work (control-click, shift-click ...). 913 // Verifies multiple selection gestures work (control-click, shift-click ...).
911 TEST_F(TableViewTest, Multiselection) { 914 TEST_F(TableViewTest, Multiselection) {
912 // Configure the grouper so that there are three groups: 915 // Configure the grouper so that there are three groups:
913 // A 0 916 // A 0
914 // 1 917 // 1
915 // B 5 918 // B 5
916 // C 2 919 // C 2
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 TEST_F(TableViewTest, FocusAfterRemovingAnchor) { 1016 TEST_F(TableViewTest, FocusAfterRemovingAnchor) {
1014 table_->ToggleSortOrder(0); 1017 table_->ToggleSortOrder(0);
1015 1018
1016 ui::ListSelectionModel new_selection; 1019 ui::ListSelectionModel new_selection;
1017 new_selection.AddIndexToSelection(0); 1020 new_selection.AddIndexToSelection(0);
1018 new_selection.AddIndexToSelection(1); 1021 new_selection.AddIndexToSelection(1);
1019 new_selection.set_active(0); 1022 new_selection.set_active(0);
1020 new_selection.set_anchor(0); 1023 new_selection.set_anchor(0);
1021 helper_->SetSelectionModel(new_selection); 1024 helper_->SetSelectionModel(new_selection);
1022 model_->RemoveRow(0); 1025 model_->RemoveRow(0);
1023 helper_->OnFocus(); 1026 table_->RequestFocus();
1024 }
1025
1026 // Tests that focusing the table will activate the first row, but only if
1027 // there's no active row.
1028 TEST_F(TableViewTest, InitialFocusActivatesFirstRow) {
1029 EXPECT_EQ(-1, table_->selection_model().active());
1030 helper_->OnFocus();
1031 EXPECT_EQ(0, table_->selection_model().active());
1032
1033 ui::ListSelectionModel new_selection;
1034 new_selection.set_active(1);
1035 helper_->SetSelectionModel(new_selection);
1036 EXPECT_EQ(1, table_->selection_model().active());
1037 helper_->OnFocus();
1038 EXPECT_EQ(1, table_->selection_model().active());
1039
1040 // Remove all rows; focusing should not activate a non existent first row.
1041 while (model_->RowCount())
1042 model_->RemoveRow(0);
1043
1044 new_selection.set_active(-1);
1045 helper_->SetSelectionModel(new_selection);
1046 helper_->OnFocus();
1047 EXPECT_EQ(-1, table_->selection_model().active());
1048 } 1027 }
1049 1028
1050 } // namespace views 1029 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/table/table_view.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698