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.
5 #include "chrome/browser/printing/print_dialog_cloud.h"
6 #include "chrome/browser/printing/print_dialog_cloud_internal.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/file_util.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/path_service.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/url_constants.h"
22 #include "components/cloud_devices/common/cloud_devices_urls.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/notification_types.h"
26 #include "content/public/test/test_browser_thread.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 using content::BrowserThread
;
31 using content::WebContents
;
32 using content::WebUIMessageHandler
;
34 using testing::AtLeast
;
36 using testing::HasSubstr
;
37 using testing::IsNull
;
38 using testing::NotNull
;
39 using testing::Return
;
42 using ui::ExternalWebDialogUI
;
44 const char kPDFTestFile
[] = "printing/cloud_print_unittest.pdf";
45 const char kMockJobTitle
[] = "Mock Job Title";
46 const char kMockPrintTicket
[] = "Resolution=300";
49 base::FilePath
GetTestDataFileName() {
50 base::FilePath test_data_directory
;
51 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_directory
);
52 base::FilePath test_file
= test_data_directory
.AppendASCII(kPDFTestFile
);
57 static std::string sTestFileData
;
58 if (sTestFileData
.empty()) {
59 base::FilePath test_file
= GetTestDataFileName();
60 base::ReadFileToString(test_file
, &sTestFileData
);
62 return &sTestFileData
[0];
65 MATCHER_P(StringValueEq
, expected
, "StringValue") {
66 if (expected
->Equals(&arg
))
68 std::string expected_string
, arg_string
;
69 expected
->GetAsString(&expected_string
);
70 arg
.GetAsString(&arg_string
);
71 *result_listener
<< "'" << arg_string
72 << "' (expected '" << expected_string
<< "')";
76 namespace internal_cloud_print_helpers
{
78 class MockCloudPrintFlowHandler
79 : public CloudPrintFlowHandler
,
80 public base::SupportsWeakPtr
<MockCloudPrintFlowHandler
> {
82 MockCloudPrintFlowHandler(const base::string16
& title
,
83 const base::string16
& print_ticket
,
84 const std::string
& file_type
)
85 : CloudPrintFlowHandler(NULL
, title
, print_ticket
, file_type
) {}
86 MOCK_METHOD0(DestructorCalled
, void());
87 MOCK_METHOD0(RegisterMessages
, void());
90 const content::NotificationSource
& source
,
91 const content::NotificationDetails
& details
));
92 MOCK_METHOD1(SetDialogDelegate
,
93 void(CloudPrintWebDialogDelegate
* delegate
));
94 MOCK_METHOD0(CreateCloudPrintDataSender
,
95 scoped_refptr
<CloudPrintDataSender
>());
98 class MockCloudPrintWebDialogDelegate
: public CloudPrintWebDialogDelegate
{
100 MOCK_CONST_METHOD0(GetDialogModalType
,
102 MOCK_CONST_METHOD0(GetDialogTitle
,
104 MOCK_CONST_METHOD0(GetDialogContentURL
,
106 MOCK_CONST_METHOD1(GetWebUIMessageHandlers
,
107 void(std::vector
<WebUIMessageHandler
*>* handlers
));
108 MOCK_CONST_METHOD1(GetDialogSize
,
109 void(gfx::Size
* size
));
110 MOCK_CONST_METHOD0(GetDialogArgs
,
112 MOCK_METHOD1(OnDialogClosed
,
113 void(const std::string
& json_retval
));
114 MOCK_METHOD2(OnCloseContents
,
115 void(WebContents
* source
, bool *out_close_dialog
));
118 } // namespace internal_cloud_print_helpers
120 using internal_cloud_print_helpers::CloudPrintDataSenderHelper
;
121 using internal_cloud_print_helpers::CloudPrintDataSender
;
123 class MockExternalWebDialogUI
: public ExternalWebDialogUI
{
125 MOCK_METHOD1(RenderViewCreated
,
126 void(content::RenderViewHost
* render_view_host
));
129 class MockCloudPrintDataSenderHelper
: public CloudPrintDataSenderHelper
{
131 // TODO(scottbyer): At some point this probably wants to use a
132 // MockTabContents instead of NULL, and to pre-load it with a bunch
133 // of expects/results.
134 MockCloudPrintDataSenderHelper() : CloudPrintDataSenderHelper(NULL
) {}
135 MOCK_METHOD3(CallJavascriptFunction
, void(const std::string
&,
136 const base::Value
& arg1
,
137 const base::Value
& arg2
));
140 // Testing for CloudPrintDataSender needs a mock WebUI.
141 class CloudPrintDataSenderTest
: public testing::Test
{
143 CloudPrintDataSenderTest()
144 : file_thread_(BrowserThread::FILE, &message_loop_
),
145 io_thread_(BrowserThread::IO
, &message_loop_
) {}
148 virtual void SetUp() {
149 mock_helper_
.reset(new MockCloudPrintDataSenderHelper
);
152 scoped_refptr
<CloudPrintDataSender
> CreateSender(
153 const base::RefCountedString
* data
) {
154 return new CloudPrintDataSender(mock_helper_
.get(),
155 base::ASCIIToUTF16(kMockJobTitle
),
156 base::ASCIIToUTF16(kMockPrintTicket
),
157 std::string("application/pdf"),
161 scoped_refptr
<CloudPrintDataSender
> print_data_sender_
;
162 scoped_ptr
<MockCloudPrintDataSenderHelper
> mock_helper_
;
164 base::MessageLoop message_loop_
;
165 content::TestBrowserThread file_thread_
;
166 content::TestBrowserThread io_thread_
;
169 TEST_F(CloudPrintDataSenderTest
, CanSend
) {
170 base::StringValue
mock_job_title(kMockJobTitle
);
171 EXPECT_CALL(*mock_helper_
,
172 CallJavascriptFunction(_
, _
, StringValueEq(&mock_job_title
))).
175 std::string
data("test_data");
176 scoped_refptr
<CloudPrintDataSender
> print_data_sender(
177 CreateSender(base::RefCountedString::TakeString(&data
)));
178 base::FilePath test_data_file_name
= GetTestDataFileName();
179 BrowserThread::PostTask(
180 BrowserThread::IO
, FROM_HERE
,
181 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
182 base::MessageLoop::current()->RunUntilIdle();
185 TEST_F(CloudPrintDataSenderTest
, NoData
) {
186 EXPECT_CALL(*mock_helper_
, CallJavascriptFunction(_
, _
, _
)).Times(0);
188 scoped_refptr
<CloudPrintDataSender
> print_data_sender(CreateSender(NULL
));
189 base::FilePath test_data_file_name
= GetTestDataFileName();
190 BrowserThread::PostTask(
191 BrowserThread::IO
, FROM_HERE
,
192 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
193 base::MessageLoop::current()->RunUntilIdle();
196 TEST_F(CloudPrintDataSenderTest
, EmptyData
) {
197 EXPECT_CALL(*mock_helper_
, CallJavascriptFunction(_
, _
, _
)).Times(0);
200 scoped_refptr
<CloudPrintDataSender
> print_data_sender(
201 CreateSender(base::RefCountedString::TakeString(&data
)));
202 base::FilePath test_data_file_name
= GetTestDataFileName();
203 BrowserThread::PostTask(
204 BrowserThread::IO
, FROM_HERE
,
205 base::Bind(&CloudPrintDataSender::SendPrintData
, print_data_sender
));
206 base::MessageLoop::current()->RunUntilIdle();
209 // Testing for CloudPrintFlowHandler needs a mock
210 // CloudPrintWebDialogDelegate, mock CloudPrintDataSender, and a mock
213 // Testing for CloudPrintWebDialogDelegate needs a mock
214 // CloudPrintFlowHandler.
216 using internal_cloud_print_helpers::MockCloudPrintFlowHandler
;
217 using internal_cloud_print_helpers::CloudPrintWebDialogDelegate
;
219 class CloudPrintWebDialogDelegateTest
: public testing::Test
{
221 CloudPrintWebDialogDelegateTest()
222 : ui_thread_(BrowserThread::UI
, &message_loop_
) {}
225 virtual void SetUp() {
226 base::string16 mock_title
;
227 base::string16 mock_print_ticket
;
228 std::string mock_file_type
;
229 MockCloudPrintFlowHandler
* handler
=
230 new MockCloudPrintFlowHandler(mock_print_ticket
, mock_title
,
232 mock_flow_handler_
= handler
->AsWeakPtr();
233 EXPECT_CALL(*mock_flow_handler_
.get(), SetDialogDelegate(_
));
234 EXPECT_CALL(*mock_flow_handler_
.get(), SetDialogDelegate(NULL
));
235 delegate_
.reset(new CloudPrintWebDialogDelegate(mock_flow_handler_
.get(),
239 virtual void TearDown() {
241 if (mock_flow_handler_
.get())
242 delete mock_flow_handler_
.get();
245 base::MessageLoopForUI message_loop_
;
246 content::TestBrowserThread ui_thread_
;
247 base::WeakPtr
<MockCloudPrintFlowHandler
> mock_flow_handler_
;
248 scoped_ptr
<CloudPrintWebDialogDelegate
> delegate_
;
251 TEST_F(CloudPrintWebDialogDelegateTest
, BasicChecks
) {
252 EXPECT_THAT(delegate_
->GetDialogContentURL().spec(),
253 StrEq(chrome::kChromeUICloudPrintResourcesURL
));
254 EXPECT_TRUE(delegate_
->GetDialogTitle().empty());
256 bool close_dialog
= false;
257 delegate_
->OnCloseContents(NULL
, &close_dialog
);
258 EXPECT_TRUE(close_dialog
);
261 TEST_F(CloudPrintWebDialogDelegateTest
, OwnedFlowDestroyed
) {
263 EXPECT_THAT(mock_flow_handler_
.get(), IsNull());
266 TEST_F(CloudPrintWebDialogDelegateTest
, UnownedFlowLetGo
) {
267 std::vector
<WebUIMessageHandler
*> handlers
;
268 delegate_
->GetWebUIMessageHandlers(&handlers
);
270 EXPECT_THAT(mock_flow_handler_
.get(), NotNull());
273 // Testing for ExternalWebDialogUI needs a mock WebContents and mock
274 // CloudPrintWebDialogDelegate (attached to the mock web_contents).
276 // Testing for PrintDialogCloud needs a mock Browser.