Chromium Code Reviews| Index: chrome/browser/ui/views/chooser_content_view_unittest.cc |
| diff --git a/chrome/browser/ui/views/chooser_content_view_unittest.cc b/chrome/browser/ui/views/chooser_content_view_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..aa0133c7806bc93d481fbc16de773535a179b88d |
| --- /dev/null |
| +++ b/chrome/browser/ui/views/chooser_content_view_unittest.cc |
| @@ -0,0 +1,359 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/ui/views/chooser_content_view.h" |
| + |
| +#include "base/macros.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#include "chrome/grit/generated_resources.h" |
| +#include "components/chooser_controller/chooser_controller.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "ui/views/controls/styled_label.h" |
| +#include "ui/views/controls/styled_label_listener.h" |
| +#include "ui/views/controls/table/table_view.h" |
| +#include "ui/views/controls/table/table_view_observer.h" |
| + |
| +namespace { |
| + |
| +class MockChooserController : public ChooserController { |
| + public: |
| + MockChooserController() : ChooserController(nullptr) {} |
| + ~MockChooserController() override {} |
| + |
| + // ChooserController: |
| + size_t NumOptions() const override { return option_names_.size(); } |
| + |
| + // ChooserController: |
| + const base::string16& GetOption(size_t index) const override { |
| + return option_names_[index]; |
| + } |
| + |
| + // ChooserController: |
| + void Select(size_t index) override {} |
| + void Cancel() override {} |
| + void Close() override {} |
| + void OpenHelpCenterUrl() const override {} |
| + |
| + void OptionAdded(const base::string16 option_name) { |
| + option_names_.push_back(option_name); |
| + if (observer()) |
| + observer()->OnOptionAdded(option_names_.size() - 1); |
| + } |
| + |
| + void OptionRemoved(const base::string16 option_name) { |
| + for (auto it = option_names_.begin(); it != option_names_.end(); ++it) { |
| + if (*it == option_name) { |
| + size_t index = it - option_names_.begin(); |
| + option_names_.erase(it); |
| + if (observer()) |
| + observer()->OnOptionRemoved(index); |
| + return; |
| + } |
| + } |
| + } |
| + |
| + private: |
| + std::vector<base::string16> option_names_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockChooserController); |
| +}; |
| + |
| +class MockTableViewObserver : public views::TableViewObserver { |
| + public: |
| + // views::TableViewObserver: |
| + MOCK_METHOD0(OnSelectionChanged, void()); |
| +}; |
| + |
| +class MockStyledLabelListener : public views::StyledLabelListener { |
| + public: |
| + // views::StyledLabelListener: |
| + MOCK_METHOD3(StyledLabelLinkClicked, |
| + void(views::StyledLabel* label, |
| + const gfx::Range& range, |
| + int event_flags)); |
| +}; |
| + |
| +} // namespace |
| + |
| +class ChooserContentViewTest : public testing::Test { |
| + public: |
| + ChooserContentViewTest() {} |
| + |
| + // testing::Test: |
| + void SetUp() override { |
| + mock_chooser_controller_.reset(new MockChooserController()); |
| + ASSERT_TRUE(mock_chooser_controller_); |
|
msw
2016/06/08 00:58:45
nit: this seems unnecessary.
juncai
2016/06/09 01:59:21
Done.
|
| + mock_table_view_observer_.reset(new MockTableViewObserver()); |
| + ASSERT_TRUE(mock_table_view_observer_); |
|
msw
2016/06/08 00:58:45
nit: this seems unnecessary.
juncai
2016/06/09 01:59:21
Done.
|
| + chooser_content_view_.reset(new ChooserContentView( |
| + mock_table_view_observer_.get(), mock_chooser_controller_.get())); |
| + ASSERT_TRUE(chooser_content_view_); |
|
msw
2016/06/08 00:58:45
nit: this seems unnecessary.
juncai
2016/06/09 01:59:21
Done.
|
| + table_view_.reset(chooser_content_view_->table_view()); |
| + ASSERT_TRUE(table_view_); |
| + table_model_ = table_view_->model(); |
| + ASSERT_TRUE(table_model_); |
| + mock_styled_label_listener_.reset(new MockStyledLabelListener()); |
| + ASSERT_TRUE(mock_styled_label_listener_); |
|
msw
2016/06/08 00:58:45
nit: this seems unnecessary.
juncai
2016/06/09 01:59:21
Done.
|
| + styled_label_.reset(chooser_content_view_->CreateFootnoteView( |
| + mock_styled_label_listener_.get())); |
| + ASSERT_TRUE(styled_label_); |
| + } |
| + |
| + protected: |
| + std::unique_ptr<MockChooserController> mock_chooser_controller_; |
| + std::unique_ptr<MockTableViewObserver> mock_table_view_observer_; |
| + std::unique_ptr<ChooserContentView> chooser_content_view_; |
| + std::unique_ptr<MockStyledLabelListener> mock_styled_label_listener_; |
| + std::unique_ptr<views::TableView> table_view_; |
| + ui::TableModel* table_model_; |
| + std::unique_ptr<views::StyledLabel> styled_label_; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ChooserContentViewTest); |
| +}; |
| + |
| +TEST_F(ChooserContentViewTest, InitialState) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(0); |
| + |
| + // Since "No devices found." needs to be displayed on the |table_view_|, |
| + // the number of rows is 1. |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
|
msw
2016/06/08 00:58:45
nit: put expectation before the actual value here
juncai
2016/06/09 01:59:21
Done.
|
| + EXPECT_EQ( |
| + table_model_->GetText(0, 0), |
| + l10n_util::GetStringUTF16(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT)); |
| + // |table_view_| should be disabled since there is no option shown. |
| + EXPECT_FALSE(table_view_->enabled()); |
| + // No option selected. |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, AddOption) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(0); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + EXPECT_EQ(table_model_->GetText(0, 0), base::ASCIIToUTF16("a")); |
| + // |table_view_| should be enabled since there is an option. |
| + EXPECT_TRUE(table_view_->enabled()); |
| + // No option selected. |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + EXPECT_EQ(table_model_->GetText(1, 0), base::ASCIIToUTF16("b")); |
| + EXPECT_TRUE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + EXPECT_EQ(table_view_->RowCount(), 3); |
| + EXPECT_EQ(table_model_->GetText(2, 0), base::ASCIIToUTF16("c")); |
| + EXPECT_TRUE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, RemoveOption) { |
| + // Called from TableView::OnItemsRemoved(). |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(3); |
|
msw
2016/06/08 00:58:45
q: why does the selection change on removing optio
juncai
2016/06/09 01:59:21
https://cs.chromium.org/chromium/src/ui/views/cont
msw
2016/06/09 18:31:15
Okay, it might be nice if that were only called if
|
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("b")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + EXPECT_EQ(table_model_->GetText(0, 0), base::ASCIIToUTF16("a")); |
| + EXPECT_EQ(table_model_->GetText(1, 0), base::ASCIIToUTF16("c")); |
| + EXPECT_TRUE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + // Remove a non-existent option, the number of rows should not change. |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("non-existent")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + EXPECT_EQ(table_model_->GetText(0, 0), base::ASCIIToUTF16("a")); |
| + EXPECT_EQ(table_model_->GetText(1, 0), base::ASCIIToUTF16("c")); |
| + EXPECT_TRUE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("c")); |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + EXPECT_EQ(table_model_->GetText(0, 0), base::ASCIIToUTF16("a")); |
| + EXPECT_TRUE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("a")); |
| + // There is no option shown now. But since "No devices found." |
| + // needs to be displayed on the |table_view_|, the number of rows is 1. |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + EXPECT_EQ( |
| + table_model_->GetText(0, 0), |
| + l10n_util::GetStringUTF16(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT)); |
| + // |table_view_| should be disabled since all options are removed. |
| + EXPECT_FALSE(table_view_->enabled()); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, AddAndRemoveOption) { |
| + // Called from TableView::OnItemsRemoved(). |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(3); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("b")); |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("d")); |
| + EXPECT_EQ(table_view_->RowCount(), 3); |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("d")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("c")); |
| + // There is no option shown now. But since "No devices found." |
|
msw
2016/06/08 00:58:45
This isn't right... option "a" is still present.
juncai
2016/06/09 01:59:21
Done.
|
| + // needs to be displayed on the |table_view_|, the number of rows is 1. |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, SelectAndDeselectAnOption) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(4); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + |
| + // Select option 0. |
| + table_view_->Select(0); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 0); |
| + |
| + // Disselect option 0. |
|
msw
2016/06/08 00:58:45
nit: "Unselect" here and elsewhere.
juncai
2016/06/09 01:59:21
Done.
|
| + table_view_->Select(-1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| + |
| + // Select option 1. |
| + table_view_->Select(1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 1); |
| + |
| + // Disselect option 1. |
| + table_view_->Select(-1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, SelectAnOptionAndThenSelectAnotherOption) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(3); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + |
| + // Select option 0. |
| + table_view_->Select(0); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 0); |
| + |
| + // Select option 1. |
| + table_view_->Select(1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 1); |
| + |
| + // Select option 2. |
| + table_view_->Select(2); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 2); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, SelectAnOptionAndRemoveAnotherOption) { |
| + // Called one time from TableView::Select() and two times from |
| + // TableView::OnItemsRemoved(). |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(3); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + |
| + // Select option 1. |
| + table_view_->Select(1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 1); |
| + |
| + // Remove option 0, the list becomes: b c. |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("a")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + // Since option 0 is removed, the original selected option 1 becomes |
| + // the first option in the list. |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 0); |
| + |
| + // Remove option 1. |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("c")); |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 0); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, SelectAnOptionAndRemoveTheSelectedOption) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(2); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("b")); |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("c")); |
| + |
| + // Select option 1. |
| + table_view_->Select(1); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 1); |
| + |
| + // Remove option 1. |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("b")); |
| + EXPECT_EQ(table_view_->RowCount(), 2); |
| + // No option selected. |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, |
| + AddAnOptionAndSelectItAndRemoveTheSelectedOption) { |
| + EXPECT_CALL(*mock_table_view_observer_, OnSelectionChanged()).Times(2); |
| + |
| + mock_chooser_controller_->OptionAdded(base::ASCIIToUTF16("a")); |
| + |
| + // Select option 0. |
| + table_view_->Select(0); |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 1); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), 0); |
| + |
| + // Remove option 0. |
| + mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("a")); |
| + // There is no option shown now. But since "No devices found." |
| + // needs to be displayed on the |table_view_|, the number of rows is 1. |
| + EXPECT_EQ(table_view_->RowCount(), 1); |
| + EXPECT_EQ( |
| + table_model_->GetText(0, 0), |
| + l10n_util::GetStringUTF16(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT)); |
| + // |table_view_| should be disabled since all options are removed. |
| + EXPECT_FALSE(table_view_->enabled()); |
| + // No option selected. |
| + EXPECT_EQ(table_view_->SelectedRowCount(), 0); |
| + EXPECT_EQ(table_view_->FirstSelectedRow(), -1); |
| +} |
| + |
| +TEST_F(ChooserContentViewTest, ClickStyledLabelLink) { |
| + EXPECT_CALL(*mock_styled_label_listener_, |
| + StyledLabelLinkClicked(styled_label_.get(), testing::_, 0)) |
| + .Times(1); |
| + styled_label_->LinkClicked(nullptr, 0); |
| +} |