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

Unified Diff: components/bubble/bubble_manager_unittest.cc

Issue 1251633002: Add BubbleManager to manage bubbles and ChromeBubbleManager for events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: TESTS! Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: components/bubble/bubble_manager_unittest.cc
diff --git a/components/bubble/bubble_manager_unittest.cc b/components/bubble/bubble_manager_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1ac6f50aee2c98bc48cf55df0590191c5b1cd42a
--- /dev/null
+++ b/components/bubble/bubble_manager_unittest.cc
@@ -0,0 +1,332 @@
+// Copyright 2015 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 "components/bubble/bubble_manager.h"
+
+#include "components/bubble/bubble_delegate.h"
+#include "components/bubble/bubble_ui.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MockBubbleUI : public BubbleUI {
+ public:
+ MockBubbleUI() {}
+ ~MockBubbleUI() override {}
+
+ MOCK_METHOD0(Show, void());
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(UpdateAnchorPosition, void());
+};
+
+class MockBubbleDelegate : public BubbleDelegate {
+ public:
+ MockBubbleDelegate() {}
+ ~MockBubbleDelegate() override {}
+
+ // Default bubble shows UI and closes when asked to close.
+ static scoped_ptr<MockBubbleDelegate> Default();
+
+ // Stubborn bubble shows UI and doesn't want to close.
+ static scoped_ptr<MockBubbleDelegate> Stubborn();
+
+ MOCK_METHOD1(ShouldClose, bool(BubbleCloseReason reason));
+
+ // A scoped_ptr can't be returned in MOCK_METHOD.
+ MOCK_METHOD0(BuildBubbleUIMock, BubbleUI*());
+ scoped_ptr<BubbleUI> BuildBubbleUI() override {
+ return make_scoped_ptr(BuildBubbleUIMock());
+ }
+};
+
+// static
+scoped_ptr<MockBubbleDelegate> MockBubbleDelegate::Default() {
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(new MockBubbleUI));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::Return(true));
+ return make_scoped_ptr(delegate);
+}
+
+// static
+scoped_ptr<MockBubbleDelegate> MockBubbleDelegate::Stubborn() {
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(new MockBubbleUI));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillRepeatedly(testing::Return(false));
+ return make_scoped_ptr(delegate);
+}
+
+class DelegateChainHelper {
msw 2015/08/21 01:48:31 nit: comment
hcarmona 2015/08/25 02:13:37 Done.
+ public:
+ DelegateChainHelper(BubbleManager* manager,
+ scoped_ptr<BubbleDelegate> next_delegate);
+
+ void Chain() { manager_->ShowBubble(next_delegate_.Pass()); }
+
+ bool BubbleWasTaken() { return !next_delegate_; }
+
+ private:
+ BubbleManager* manager_; // Weak.
+ scoped_ptr<BubbleDelegate> next_delegate_;
+};
+
+DelegateChainHelper::DelegateChainHelper(
+ BubbleManager* manager,
+ scoped_ptr<BubbleDelegate> next_delegate)
+ : manager_(manager), next_delegate_(next_delegate.Pass()) {}
+
+class BubbleManagerFixture : public BubbleManager {
msw 2015/08/21 01:48:31 Why not just use a BubbleManager instance below? (
hcarmona 2015/08/25 02:13:37 Done.
+ public:
+ BubbleManagerFixture() {}
+ ~BubbleManagerFixture() override {}
+
+ void CloseAllEvent(BubbleCloseReason reason) { CloseAllBubbles(reason); }
+};
+
+class BubbleManagerTest : public testing::Test {
+ public:
+ BubbleManagerTest();
+ ~BubbleManagerTest() override {}
+
+ void SetUp() override;
+ void TearDown() override;
+
+ protected:
+ scoped_ptr<BubbleManagerFixture> manager_;
+
+ private:
+ // The BubbleManager's show/close methods should only be called from the UI
+ // thread. This will allow the UI DCHECK pass in these tests.
msw 2015/08/21 01:48:31 nit: "DCHECK to pass"
hcarmona 2015/08/25 02:13:37 Done.
+ content::TestBrowserThreadBundle thread_bundle_;
+};
+
+BubbleManagerTest::BubbleManagerTest()
+ : thread_bundle_(content::TestBrowserThreadBundle::DEFAULT) {}
+
+void BubbleManagerTest::SetUp() {
+ testing::Test::SetUp();
+ manager_.reset(new BubbleManagerFixture);
+}
+
+void BubbleManagerTest::TearDown() {
+ manager_.reset();
+ testing::Test::TearDown();
+}
+
+TEST_F(BubbleManagerTest, ManagerShowsBubbleUI) {
+ // Manager will delete bubble_ui.
msw 2015/08/21 01:48:31 Can you EXPECT_CALL(*bubble_ui, ~MockBubbleUI());?
hcarmona 2015/08/25 02:13:37 Done.
+ MockBubbleUI* bubble_ui = new MockBubbleUI;
+ EXPECT_CALL(*bubble_ui, Show());
+ EXPECT_CALL(*bubble_ui, Close());
+ EXPECT_CALL(*bubble_ui, UpdateAnchorPosition()).Times(0);
+
+ // Manager will delete delegate.
msw 2015/08/21 01:48:31 Can you EXPECT_CALL(*delegate, ~MockBubbleDelegate
hcarmona 2015/08/25 02:13:37 Done.
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(bubble_ui));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::Return(true));
+
+ manager_->ShowBubble(make_scoped_ptr(delegate));
+}
+
+TEST_F(BubbleManagerTest, ManagerUpdatesBubbleUI) {
+ // Manager will delete bubble_ui.
+ MockBubbleUI* bubble_ui = new MockBubbleUI;
+ EXPECT_CALL(*bubble_ui, Show());
+ EXPECT_CALL(*bubble_ui, Close());
+ EXPECT_CALL(*bubble_ui, UpdateAnchorPosition());
+
+ // Manager will delete delegate.
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(bubble_ui));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::Return(true));
+
+ manager_->ShowBubble(make_scoped_ptr(delegate));
+ manager_->UpdateAllBubbleAnchors();
+}
+
+TEST_F(BubbleManagerTest, CloseInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_ACCEPTED);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_->CloseAllEvent(BUBBLE_CLOSE_ACCEPTED);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, DestroyInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_.reset();
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseAllEvent(BUBBLE_CLOSE_FORCED);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, DestroyInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_.reset();
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseDoesNotInvalidateStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_ACCEPTED);
+
+ ASSERT_TRUE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllDoesNotInvalidateStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseAllEvent(BUBBLE_CLOSE_ACCEPTED);
+
+ ASSERT_TRUE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesMixAppropriately) {
+ BubbleReference stubborn_ref1 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref1 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference stubborn_ref2 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref2 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference stubborn_ref3 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref3 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_->CloseAllEvent(BUBBLE_CLOSE_ACCEPTED);
msw 2015/08/21 01:48:31 Hmm, I wonder if we should DCHECK/guard against ce
hcarmona 2015/08/25 02:13:37 Added DCHECK for ACCEPTED and CANCELLED. I think t
+
+ ASSERT_TRUE(stubborn_ref1);
+ ASSERT_TRUE(stubborn_ref2);
+ ASSERT_TRUE(stubborn_ref3);
+ ASSERT_FALSE(normal_ref1);
+ ASSERT_FALSE(normal_ref2);
+ ASSERT_FALSE(normal_ref3);
+}
+
+TEST_F(BubbleManagerTest, UpdateAllShouldWorkWithoutBubbles) {
+ // Manager shouldn't crash if bubbles have never been added.
+ manager_->UpdateAllBubbleAnchors();
+
+ // Add a bubble and close it.
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED);
+
+ // Bubble should NOT get an update event because it's already closed.
+ manager_->UpdateAllBubbleAnchors();
+}
+
+TEST_F(BubbleManagerTest, CloseAllShouldWorkWithoutBubbles) {
+ // Manager shouldn't crash if bubbles have never been added.
+ manager_->CloseAllEvent(BUBBLE_CLOSE_ACCEPTED);
+
+ // Add a bubble and close it.
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED);
+
+ // Bubble should NOT get an update event because it's already closed.
msw 2015/08/21 01:48:31 nit: "a close event"?
hcarmona 2015/08/25 02:13:37 Done.
+ manager_->CloseAllEvent(BUBBLE_CLOSE_ACCEPTED);
+}
+
+TEST_F(BubbleManagerTest, AllowBubbleChainingOnClose) {
+ scoped_ptr<BubbleDelegate> chained_delegate = MockBubbleDelegate::Default();
+ DelegateChainHelper chain_helper(manager_.get(), chained_delegate.Pass());
+
+ // Manager will delete delegate.
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(new MockBubbleUI));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
+ &chain_helper, &DelegateChainHelper::Chain),
+ testing::Return(true)));
+
+ BubbleReference ref = manager_->ShowBubble(make_scoped_ptr(delegate));
+ manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED);
+
+ ASSERT_TRUE(chain_helper.BubbleWasTaken());
+}
+
+TEST_F(BubbleManagerTest, AllowBubbleChainingOnCloseAll) {
+ scoped_ptr<BubbleDelegate> chained_delegate = MockBubbleDelegate::Default();
+ DelegateChainHelper chain_helper(manager_.get(), chained_delegate.Pass());
+
+ // Manager will delete delegate.
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(new MockBubbleUI));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
+ &chain_helper, &DelegateChainHelper::Chain),
+ testing::Return(true)));
+
+ manager_->ShowBubble(make_scoped_ptr(delegate));
+ manager_->CloseAllEvent(BUBBLE_CLOSE_FORCED);
+
+ ASSERT_TRUE(chain_helper.BubbleWasTaken());
+}
+
+TEST_F(BubbleManagerTest, BubblesDoNotChainOnDestroy) {
+ // Manager will delete delegate.
+ MockBubbleDelegate* chained_delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*chained_delegate, BuildBubbleUIMock()).Times(0);
+ EXPECT_CALL(*chained_delegate, ShouldClose(testing::_)).Times(0);
+
+ DelegateChainHelper chain_helper(manager_.get(),
+ make_scoped_ptr(chained_delegate));
+
+ // Manager will delete delegate.
+ MockBubbleDelegate* delegate = new MockBubbleDelegate;
+ EXPECT_CALL(*delegate, BuildBubbleUIMock())
+ .WillOnce(testing::Return(new MockBubbleUI));
+ EXPECT_CALL(*delegate, ShouldClose(testing::_))
+ .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
+ &chain_helper, &DelegateChainHelper::Chain),
+ testing::Return(true)));
+
+ manager_->ShowBubble(make_scoped_ptr(delegate));
+ manager_.reset();
+
+ // The manager will take the bubble, but not show it.
+ ASSERT_TRUE(chain_helper.BubbleWasTaken());
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698