| 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..87616833a3135b3ee77a3cbd793bf3657b154c84 100644
|
| --- a/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
|
| +++ b/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
|
| @@ -10,121 +10,183 @@
|
| #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/test_views.h"
|
| #include "ui/views/test/views_test_base.h"
|
| +#include "ui/views/widget/widget.h"
|
|
|
| using base::ASCIIToUTF16;
|
|
|
| namespace views {
|
| +namespace test {
|
| +namespace {
|
|
|
| -// A view for testing that takes a fixed preferred size upon construction.
|
| -class FixedSizeView : public View {
|
| +base::string16 DefaultTabTitle() {
|
| + return ASCIIToUTF16("tab");
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class TabbedPaneTest : public ViewsTestBase {
|
| public:
|
| - explicit FixedSizeView(const gfx::Size& size)
|
| - : size_(size) {}
|
| + TabbedPaneTest() {
|
| + tabbed_pane_ = base::MakeUnique<TabbedPane>();
|
| + tabbed_pane_->set_owned_by_client();
|
| + }
|
| +
|
| + protected:
|
| + Tab* GetTabAt(int index) {
|
| + return static_cast<Tab*>(tabbed_pane_->tab_strip_->child_at(index));
|
| + }
|
|
|
| - // Overridden from View:
|
| - gfx::Size GetPreferredSize() const override { return size_; }
|
| + View* GetSelectedTabContentView() {
|
| + return tabbed_pane_->GetSelectedTabContentView();
|
| + }
|
|
|
| - private:
|
| - const gfx::Size size_;
|
| + void SendKeyPressToSelectedTab(ui::KeyboardCode keyboard_code) {
|
| + tabbed_pane_->GetSelectedTab()->OnKeyPressed(
|
| + ui::KeyEvent(ui::ET_KEY_PRESSED, keyboard_code,
|
| + ui::UsLayoutKeyboardCodeToDomCode(keyboard_code), 0));
|
| + }
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(FixedSizeView);
|
| -};
|
| + std::unique_ptr<TabbedPane> tabbed_pane_;
|
|
|
| -typedef ViewsTestBase TabbedPaneTest;
|
| + 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));
|
| - tabbed_pane->AddTab(ASCIIToUTF16("tab1"), child1);
|
| - View* child2 = new FixedSizeView(gfx::Size(5, 5));
|
| - tabbed_pane->AddTab(ASCIIToUTF16("tab2"), child2);
|
| - tabbed_pane->SelectTabAt(0);
|
| -
|
| - // The |tabbed_pane| implementation of Views has no border by default.
|
| + View* child1 = new StaticSizedView(gfx::Size(20, 10));
|
| + tabbed_pane_->AddTab(ASCIIToUTF16("tab1"), child1);
|
| + View* child2 = new StaticSizedView(gfx::Size(5, 5));
|
| + tabbed_pane_->AddTab(ASCIIToUTF16("tab2"), child2);
|
| + tabbed_pane_->SelectTabAt(0);
|
| +
|
| + // 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_.get());
|
| + 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) {
|
| + NativeViewAccessibility* nva = NativeViewAccessibility::Create(GetTabAt(i));
|
| + ui::AXNodeData data = nva->GetData();
|
| + 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));
|
| + nva->Destroy();
|
| + }
|
| +
|
| + 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
|
| } // namespace views
|
|
|