Chromium Code Reviews| Index: ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc |
| diff --git a/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc b/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc |
| index e02a2529307a0847d53b6a0cec5156fea606a5c7..659a2caae9e7537d4f386389fe5f07d66cdc95f0 100644 |
| --- a/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc |
| +++ b/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc |
| @@ -10,13 +10,21 @@ |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/accessibility/ax_action_data.h" |
| +#include "ui/accessibility/ax_enums.h" |
| #include "ui/events/keycodes/keyboard_code_conversion.h" |
| +#include "ui/views/accessibility/native_view_accessibility.h" |
| #include "ui/views/test/views_test_base.h" |
| +#include "ui/views/widget/widget.h" |
| using base::ASCIIToUTF16; |
| namespace views { |
|
tapted
2017/01/10 16:22:19
nit: remove blank line
Patti Lor
2017/01/11 05:51:45
Done.
|
| +namespace test { |
| + |
|
tapted
2017/01/10 16:22:19
nit: remove blank line
Patti Lor
2017/01/11 05:51:45
Done.
|
| +namespace { |
| + |
| // A view for testing that takes a fixed preferred size upon construction. |
| class FixedSizeView : public View { |
| public: |
| @@ -32,99 +40,177 @@ class FixedSizeView : public View { |
| DISALLOW_COPY_AND_ASSIGN(FixedSizeView); |
| }; |
| -typedef ViewsTestBase TabbedPaneTest; |
| +base::string16 DefaultTabTitle() { |
| + return ASCIIToUTF16("tab"); |
| +} |
| + |
| +} // namespace |
| + |
| +class TabbedPaneTest : public ViewsTestBase { |
| + public: |
| + TabbedPaneTest() {} |
| + |
| + void SetUp() override { |
| + tabbed_pane_ = new TabbedPane(); |
|
tapted
2017/01/10 16:22:19
There's a lifetime problem here -- the existing te
Patti Lor
2017/01/11 05:51:44
Done, thanks!
|
| + ViewsTestBase::SetUp(); |
| + } |
| + |
| + void TearDown() override { |
| + if (tabbed_pane_) |
| + tabbed_pane_ = nullptr; |
| + ViewsTestBase::TearDown(); |
| + } |
| + |
| + protected: |
| + Tab* GetTabAt(int index) { |
| + return static_cast<Tab*>(tabbed_pane_->tab_strip_->child_at(index)); |
| + } |
| + |
| + View* GetSelectedTabContentView() { |
| + return tabbed_pane_->GetSelectedTabContentView(); |
| + } |
| + |
| + void SendKeyPressToSelectedTab(ui::KeyboardCode keyboard_code) { |
| + tabbed_pane_->GetSelectedTab()->OnKeyPressed( |
| + ui::KeyEvent(ui::ET_KEY_PRESSED, keyboard_code, |
| + ui::UsLayoutKeyboardCodeToDomCode(keyboard_code), 0)); |
| + } |
| + |
| + TabbedPane* tabbed_pane_; |
|
tapted
2017/01/10 16:22:19
this needs to be a unique_ptr
Patti Lor
2017/01/11 05:51:45
Done.
|
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(TabbedPaneTest); |
| +}; |
| // Tests TabbedPane::GetPreferredSize() and TabbedPane::Layout(). |
| TEST_F(TabbedPaneTest, SizeAndLayout) { |
| - std::unique_ptr<TabbedPane> tabbed_pane(new TabbedPane()); |
| View* child1 = new FixedSizeView(gfx::Size(20, 10)); |
|
tapted
2017/01/10 16:22:19
Since we're refactoring.. I think instead of `Fixe
Patti Lor
2017/01/11 05:51:44
Done.
|
| - tabbed_pane->AddTab(ASCIIToUTF16("tab1"), child1); |
| + tabbed_pane_->AddTab(ASCIIToUTF16("tab1"), child1); |
| View* child2 = new FixedSizeView(gfx::Size(5, 5)); |
| - tabbed_pane->AddTab(ASCIIToUTF16("tab2"), child2); |
| - tabbed_pane->SelectTabAt(0); |
| + tabbed_pane_->AddTab(ASCIIToUTF16("tab2"), child2); |
| + tabbed_pane_->SelectTabAt(0); |
| - // The |tabbed_pane| implementation of Views has no border by default. |
| + // The |tabbed_pane_| implementation of Views has no border by default. |
| // Therefore it should be as wide as the widest tab. The native Windows |
| // tabbed pane has a border that used up extra space. Therefore the preferred |
| // width is larger than the largest child. |
| - gfx::Size pref(tabbed_pane->GetPreferredSize()); |
| + gfx::Size pref(tabbed_pane_->GetPreferredSize()); |
| EXPECT_GE(pref.width(), 20); |
| EXPECT_GT(pref.height(), 10); |
| // The bounds of our children should be smaller than the tabbed pane's bounds. |
| - tabbed_pane->SetBounds(0, 0, 100, 200); |
| + tabbed_pane_->SetBounds(0, 0, 100, 200); |
| RunPendingMessages(); |
| gfx::Rect bounds(child1->bounds()); |
| EXPECT_GT(bounds.width(), 0); |
| - // The |tabbed_pane| has no border. Therefore the children should be as wide |
| - // as the |tabbed_pane|. |
| + // The |tabbed_pane_| has no border. Therefore the children should be as wide |
| + // as the |tabbed_pane_|. |
| EXPECT_LE(bounds.width(), 100); |
| EXPECT_GT(bounds.height(), 0); |
| EXPECT_LT(bounds.height(), 200); |
| // If we switch to the other tab, it should get assigned the same bounds. |
| - tabbed_pane->SelectTabAt(1); |
| + tabbed_pane_->SelectTabAt(1); |
| EXPECT_EQ(bounds, child2->bounds()); |
| } |
| TEST_F(TabbedPaneTest, AddAndSelect) { |
| - std::unique_ptr<TabbedPane> tabbed_pane(new TabbedPane()); |
| - // Add several tabs; only the first should be a selected automatically. |
| + // Add several tabs; only the first should be selected automatically. |
| for (int i = 0; i < 3; ++i) { |
| View* tab = new View(); |
| - tabbed_pane->AddTab(ASCIIToUTF16("tab"), tab); |
| - EXPECT_EQ(i + 1, tabbed_pane->GetTabCount()); |
| - EXPECT_EQ(0, tabbed_pane->GetSelectedTabIndex()); |
| + tabbed_pane_->AddTab(DefaultTabTitle(), tab); |
| + EXPECT_EQ(i + 1, tabbed_pane_->GetTabCount()); |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| } |
| // Select each tab. |
| - for (int i = 0; i < tabbed_pane->GetTabCount(); ++i) { |
| - tabbed_pane->SelectTabAt(i); |
| - EXPECT_EQ(i, tabbed_pane->GetSelectedTabIndex()); |
| + for (int i = 0; i < tabbed_pane_->GetTabCount(); ++i) { |
| + tabbed_pane_->SelectTabAt(i); |
| + EXPECT_EQ(i, tabbed_pane_->GetSelectedTabIndex()); |
| } |
| // Add a tab at index 0, it should not be selected automatically. |
| View* tab0 = new View(); |
| - tabbed_pane->AddTabAtIndex(0, ASCIIToUTF16("tab0"), tab0); |
| - EXPECT_NE(tab0, tabbed_pane->GetSelectedTabContentView()); |
| - EXPECT_NE(0, tabbed_pane->GetSelectedTabIndex()); |
| -} |
| - |
| -ui::KeyEvent MakeKeyPressedEvent(ui::KeyboardCode keyboard_code, int flags) { |
| - return ui::KeyEvent(ui::ET_KEY_PRESSED, keyboard_code, |
| - ui::UsLayoutKeyboardCodeToDomCode(keyboard_code), flags); |
| + tabbed_pane_->AddTabAtIndex(0, ASCIIToUTF16("tab0"), tab0); |
| + EXPECT_NE(tab0, GetSelectedTabContentView()); |
| + EXPECT_NE(0, tabbed_pane_->GetSelectedTabIndex()); |
| } |
| TEST_F(TabbedPaneTest, ArrowKeyBindings) { |
| - std::unique_ptr<TabbedPane> tabbed_pane(new TabbedPane()); |
| - // Add several tabs; only the first should be a selected automatically. |
| + // Add several tabs; only the first should be selected automatically. |
| for (int i = 0; i < 3; ++i) { |
| View* tab = new View(); |
| - tabbed_pane->AddTab(ASCIIToUTF16("tab"), tab); |
| - EXPECT_EQ(i + 1, tabbed_pane->GetTabCount()); |
| + tabbed_pane_->AddTab(DefaultTabTitle(), tab); |
| + EXPECT_EQ(i + 1, tabbed_pane_->GetTabCount()); |
| } |
| - EXPECT_EQ(0, tabbed_pane->GetSelectedTabIndex()); |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| // Right arrow should select tab 1: |
| - tabbed_pane->GetSelectedTab()->OnKeyPressed( |
| - MakeKeyPressedEvent(ui::VKEY_RIGHT, 0)); |
| - EXPECT_EQ(1, tabbed_pane->GetSelectedTabIndex()); |
| + SendKeyPressToSelectedTab(ui::VKEY_RIGHT); |
| + EXPECT_EQ(1, tabbed_pane_->GetSelectedTabIndex()); |
| // Left arrow should select tab 0: |
| - tabbed_pane->GetSelectedTab()->OnKeyPressed( |
| - MakeKeyPressedEvent(ui::VKEY_LEFT, 0)); |
| - EXPECT_EQ(0, tabbed_pane->GetSelectedTabIndex()); |
| + SendKeyPressToSelectedTab(ui::VKEY_LEFT); |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| // Left arrow again should wrap to tab 2: |
| - tabbed_pane->GetSelectedTab()->OnKeyPressed( |
| - MakeKeyPressedEvent(ui::VKEY_LEFT, 0)); |
| - EXPECT_EQ(2, tabbed_pane->GetSelectedTabIndex()); |
| + SendKeyPressToSelectedTab(ui::VKEY_LEFT); |
| + EXPECT_EQ(2, tabbed_pane_->GetSelectedTabIndex()); |
| // Right arrow again should wrap to tab 0: |
| - tabbed_pane->GetSelectedTab()->OnKeyPressed( |
| - MakeKeyPressedEvent(ui::VKEY_RIGHT, 0)); |
| - EXPECT_EQ(0, tabbed_pane->GetSelectedTabIndex()); |
| + SendKeyPressToSelectedTab(ui::VKEY_RIGHT); |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| } |
| +// Use TabbedPane::HandleAccessibleAction() to select tabs and make sure their |
| +// a11y information is correct. |
| +TEST_F(TabbedPaneTest, SelectTabWithAccessibleAction) { |
| + // Testing accessibility information requires the View to have a Widget. |
| + Widget* widget = new Widget; |
| + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
| + widget->Init(params); |
| + widget->GetContentsView()->AddChildView(tabbed_pane_); |
| + widget->Show(); |
| + |
| + constexpr int kNumTabs = 3; |
| + for (int i = 0; i < kNumTabs; ++i) { |
| + tabbed_pane_->AddTab(DefaultTabTitle(), new View()); |
| + } |
| + // Check the first tab is selected. |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| + |
| + // Check the a11y information for each tab. |
| + for (int i = 0; i < kNumTabs; ++i) { |
| + ui::AXNodeData data = |
| + NativeViewAccessibility::Create(GetTabAt(i))->GetData(); |
|
tapted
2017/01/10 16:22:19
ooh - i think the result of `Create` here is leake
Patti Lor
2017/01/11 05:51:45
Oops, yeah you are right - thanks for picking them
|
| + SCOPED_TRACE(testing::Message() << "Tab at index: " << i); |
| + EXPECT_EQ(ui::AX_ROLE_TAB, data.role); |
| + EXPECT_EQ(DefaultTabTitle(), data.GetString16Attribute(ui::AX_ATTR_NAME)); |
| + EXPECT_TRUE(data.HasStateFlag(ui::AX_STATE_SELECTABLE)); |
| + EXPECT_EQ(i == 0, data.HasStateFlag(ui::AX_STATE_SELECTED)); |
| + } |
| + |
| + ui::AXActionData action; |
| + action.action = ui::AX_ACTION_SET_SELECTION; |
| + // Select the first tab. |
| + NativeViewAccessibility* nva = NativeViewAccessibility::Create(GetTabAt(0)); |
| + nva->AccessibilityPerformAction(action); |
| + EXPECT_EQ(0, tabbed_pane_->GetSelectedTabIndex()); |
| + nva->Destroy(); |
| + |
| + // Select the second tab. |
| + nva = NativeViewAccessibility::Create(GetTabAt(1)); |
| + nva->AccessibilityPerformAction(action); |
| + EXPECT_EQ(1, tabbed_pane_->GetSelectedTabIndex()); |
| + // Select the second tab again. |
| + nva->AccessibilityPerformAction(action); |
| + EXPECT_EQ(1, tabbed_pane_->GetSelectedTabIndex()); |
| + nva->Destroy(); |
| + |
| + widget->CloseNow(); |
| +} |
| + |
| +} // namespace test |
| + |
|
tapted
2017/01/10 16:22:19
nit: remove blank line
Patti Lor
2017/01/11 05:51:44
Done.
|
| } // namespace views |