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
3 // found in the LICENSE file.
6 #include "base/run_loop.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/speech/speech_recognition_bubble_controller.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_tabstrip.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/test/base/browser_with_test_window_test.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/gfx/rect.h"
21 using content::BrowserThread;
22 using content::WebContents;
26 // A mock bubble class which fakes a focus change or recognition cancel by the
27 // user and closing of the info bubble.
28 class MockSpeechRecognitionBubble : public SpeechRecognitionBubbleBase {
31 BUBBLE_TEST_FOCUS_CHANGED,
32 BUBBLE_TEST_CLICK_CANCEL,
33 BUBBLE_TEST_CLICK_TRY_AGAIN,
36 MockSpeechRecognitionBubble(int render_process_id, int render_view_id,
37 Delegate* delegate, const gfx::Rect&)
38 : SpeechRecognitionBubbleBase(render_process_id, render_view_id) {
39 VLOG(1) << "MockSpeechRecognitionBubble created";
40 base::MessageLoop::current()->PostTask(
41 FROM_HERE, base::Bind(&InvokeDelegate, delegate));
44 static void InvokeDelegate(Delegate* delegate) {
45 VLOG(1) << "MockSpeechRecognitionBubble invoking delegate for type "
48 case BUBBLE_TEST_FOCUS_CHANGED:
49 delegate->InfoBubbleFocusChanged();
51 case BUBBLE_TEST_CLICK_CANCEL:
52 delegate->InfoBubbleButtonClicked(
53 SpeechRecognitionBubble::BUTTON_CANCEL);
55 case BUBBLE_TEST_CLICK_TRY_AGAIN:
56 delegate->InfoBubbleButtonClicked(
57 SpeechRecognitionBubble::BUTTON_TRY_AGAIN);
62 static void set_type(BubbleType type) {
65 static BubbleType type() {
69 virtual void Show() OVERRIDE {}
70 virtual void Hide() OVERRIDE {}
71 virtual void UpdateLayout() OVERRIDE {}
72 virtual void UpdateImage() OVERRIDE {}
75 static BubbleType type_;
79 class SpeechRecognitionBubbleControllerTest
80 : public SpeechRecognitionBubbleControllerDelegate,
81 public BrowserWithTestWindowTest {
83 SpeechRecognitionBubbleControllerTest()
84 : BrowserWithTestWindowTest(),
85 cancel_clicked_(false),
86 try_again_clicked_(false),
87 focus_changed_(false),
88 controller_(new SpeechRecognitionBubbleController(this)) {
89 EXPECT_EQ(NULL, test_fixture_);
93 virtual ~SpeechRecognitionBubbleControllerTest() {
97 // SpeechRecognitionBubbleControllerDelegate methods.
98 virtual void InfoBubbleButtonClicked(
100 SpeechRecognitionBubble::Button button) OVERRIDE {
101 VLOG(1) << "Received InfoBubbleButtonClicked for button " << button;
102 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
103 if (button == SpeechRecognitionBubble::BUTTON_CANCEL) {
104 cancel_clicked_ = true;
105 } else if (button == SpeechRecognitionBubble::BUTTON_TRY_AGAIN) {
106 try_again_clicked_ = true;
110 virtual void InfoBubbleFocusChanged(int session_id) OVERRIDE {
111 VLOG(1) << "Received InfoBubbleFocusChanged";
112 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
113 focus_changed_ = true;
116 // testing::Test methods.
117 virtual void SetUp() {
118 BrowserWithTestWindowTest::SetUp();
119 SpeechRecognitionBubble::set_factory(
120 &SpeechRecognitionBubbleControllerTest::CreateBubble);
123 virtual void TearDown() {
124 SpeechRecognitionBubble::set_factory(NULL);
125 BrowserWithTestWindowTest::TearDown();
128 static void ActivateBubble() {
129 if (MockSpeechRecognitionBubble::type() !=
130 MockSpeechRecognitionBubble::BUBBLE_TEST_FOCUS_CHANGED) {
131 test_fixture_->controller_->SetBubbleMessage(base::ASCIIToUTF16("Test"));
135 static SpeechRecognitionBubble* CreateBubble(
136 WebContents* web_contents,
137 SpeechRecognitionBubble::Delegate* delegate,
138 const gfx::Rect& element_rect) {
139 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 // Set up to activate the bubble soon after it gets created, since we test
141 // events sent by the bubble and those are handled only when the bubble is
143 base::MessageLoop::current()->PostTask(FROM_HERE,
144 base::Bind(&ActivateBubble));
146 return new MockSpeechRecognitionBubble(0, 0, delegate, element_rect);
150 bool cancel_clicked_;
151 bool try_again_clicked_;
153 scoped_refptr<SpeechRecognitionBubbleController> controller_;
155 static const int kBubbleSessionId;
156 static SpeechRecognitionBubbleControllerTest* test_fixture_;
159 SpeechRecognitionBubbleControllerTest*
160 SpeechRecognitionBubbleControllerTest::test_fixture_ = NULL;
162 const int SpeechRecognitionBubbleControllerTest::kBubbleSessionId = 1;
164 MockSpeechRecognitionBubble::BubbleType MockSpeechRecognitionBubble::type_ =
165 MockSpeechRecognitionBubble::BUBBLE_TEST_FOCUS_CHANGED;
167 // Test that the speech bubble UI gets created in the UI thread and that the
168 // focus changed callback comes back in the IO thread.
169 TEST_F(SpeechRecognitionBubbleControllerTest, TestFocusChanged) {
170 MockSpeechRecognitionBubble::set_type(
171 MockSpeechRecognitionBubble::BUBBLE_TEST_FOCUS_CHANGED);
173 controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
174 base::RunLoop().RunUntilIdle();
175 EXPECT_TRUE(focus_changed_);
176 EXPECT_FALSE(cancel_clicked_);
177 EXPECT_FALSE(try_again_clicked_);
178 controller_->CloseBubble();
181 // Test that the speech bubble UI gets created in the UI thread and that the
182 // recognition cancelled callback comes back in the IO thread.
183 TEST_F(SpeechRecognitionBubbleControllerTest, TestRecognitionCancelled) {
184 MockSpeechRecognitionBubble::set_type(
185 MockSpeechRecognitionBubble::BUBBLE_TEST_CLICK_CANCEL);
187 controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
188 base::RunLoop().RunUntilIdle();
189 EXPECT_TRUE(cancel_clicked_);
190 EXPECT_FALSE(try_again_clicked_);
191 EXPECT_FALSE(focus_changed_);
192 controller_->CloseBubble();
195 // Test that the speech bubble UI gets created in the UI thread and that the
196 // try-again button click event comes back in the IO thread.
197 TEST_F(SpeechRecognitionBubbleControllerTest, TestTryAgainClicked) {
198 MockSpeechRecognitionBubble::set_type(
199 MockSpeechRecognitionBubble::BUBBLE_TEST_CLICK_TRY_AGAIN);
201 controller_->CreateBubble(kBubbleSessionId, 1, 1, gfx::Rect(1, 1));
202 base::RunLoop().RunUntilIdle();
203 EXPECT_FALSE(cancel_clicked_);
204 EXPECT_TRUE(try_again_clicked_);
205 EXPECT_FALSE(focus_changed_);
206 controller_->CloseBubble();
209 } // namespace speech