print_dialog_cloud_unittest.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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.
4
5#include "chrome/browser/printing/print_dialog_cloud.h"
6#include "chrome/browser/printing/print_dialog_cloud_internal.h"
7
8#include "base/file_path.h"
9#include "base/file_util.h"
10#include "base/path_service.h"
11#include "base/string_util.h"
12#include "base/values.h"
13#include "base/weak_ptr.h"
14#include "chrome/browser/chrome_thread.h"
15#include "chrome/common/chrome_paths.h"
16#include "chrome/common/notification_details.h"
17#include "chrome/common/notification_observer.h"
18#include "chrome/common/notification_registrar.h"
19#include "chrome/common/notification_source.h"
20#include "chrome/common/notification_type.h"
21#include "chrome/common/url_constants.h"
22#include "chrome/test/testing_profile.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "testing/gmock/include/gmock/gmock.h"
25
26using testing::A;
27using testing::AtLeast;
28using testing::Eq;
29using testing::HasSubstr;
30using testing::IsNull;
31using testing::NotNull;
32using testing::Return;
33using testing::StrEq;
34using testing::_;
35
36static const char* const kPDFTestFile = "printing/cloud_print_unittest.pdf";
37static const char* const kEmptyPDFTestFile =
38    "printing/cloud_print_emptytest.pdf";
39static const char* const kMockJobTitle = "Mock Job Title";
40
41FilePath GetTestDataFileName() {
42  FilePath test_data_directory;
43  PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory);
44  FilePath test_file = test_data_directory.AppendASCII(kPDFTestFile);
45  return test_file;
46}
47
48FilePath GetEmptyDataFileName() {
49  FilePath test_data_directory;
50  PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory);
51  FilePath test_file = test_data_directory.AppendASCII(kEmptyPDFTestFile);
52  return test_file;
53}
54
55char* GetTestData() {
56  static std::string sTestFileData;
57  if (sTestFileData.empty()) {
58    FilePath test_file = GetTestDataFileName();
59    file_util::ReadFileToString(test_file, &sTestFileData);
60  }
61  return &sTestFileData[0];
62}
63
64MATCHER_P(StringValueEq, expected, "StringValue") {
65  if (expected->Equals(&arg))
66    return true;
67  std::string expected_string, arg_string;
68  expected->GetAsString(&expected_string);
69  arg.GetAsString(&arg_string);
70  *result_listener << "'" << arg_string
71                   << "' (expected '" << expected_string << "')";
72  return false;
73}
74
75namespace internal_cloud_print_helpers {
76
77class MockCloudPrintFlowHandler
78    : public CloudPrintFlowHandler,
79      public base::SupportsWeakPtr<MockCloudPrintFlowHandler> {
80 public:
81  explicit MockCloudPrintFlowHandler(const FilePath& path,
82                                     const string16& title)
83      : CloudPrintFlowHandler(path, title) {}
84  MOCK_METHOD0(DestructorCalled, void());
85  MOCK_METHOD0(RegisterMessages, void());
86  MOCK_METHOD3(Observe,
87               void(NotificationType type,
88                    const NotificationSource& source,
89                    const NotificationDetails& details));
90  MOCK_METHOD1(SetDialogDelegate,
91               void(CloudPrintHtmlDialogDelegate* delegate));
92  MOCK_METHOD0(CreateCloudPrintDataSender,
93               scoped_refptr<CloudPrintDataSender>());
94};
95
96class MockCloudPrintHtmlDialogDelegate : public CloudPrintHtmlDialogDelegate {
97 public:
98  MOCK_CONST_METHOD0(IsDialogModal,
99      bool());
100  MOCK_CONST_METHOD0(GetDialogTitle,
101      std::wstring());
102  MOCK_CONST_METHOD0(GetDialogContentURL,
103      GURL());
104  MOCK_CONST_METHOD1(GetDOMMessageHandlers,
105      void(std::vector<DOMMessageHandler*>* handlers));
106  MOCK_CONST_METHOD1(GetDialogSize,
107      void(gfx::Size* size));
108  MOCK_CONST_METHOD0(GetDialogArgs,
109      std::string());
110  MOCK_METHOD1(OnDialogClosed,
111      void(const std::string& json_retval));
112  MOCK_METHOD2(OnCloseContents,
113      void(TabContents* source, bool *out_close_dialog));
114};
115
116}  // namespace internal_cloud_print_helpers
117
118using internal_cloud_print_helpers::CloudPrintDataSenderHelper;
119using internal_cloud_print_helpers::CloudPrintDataSender;
120
121class MockExternalHtmlDialogUI : public ExternalHtmlDialogUI {
122 public:
123  MOCK_METHOD1(RenderViewCreated,
124      void(RenderViewHost* render_view_host));
125};
126
127class MockCloudPrintDataSenderHelper : public CloudPrintDataSenderHelper {
128 public:
129  // TODO(scottbyer): At some point this probably wants to use a
130  // MockTabContents instead of NULL, and to pre-load it with a bunch
131  // of expects/results.
132  MockCloudPrintDataSenderHelper() : CloudPrintDataSenderHelper(NULL) {}
133  MOCK_METHOD1(CallJavascriptFunction, void(const std::wstring&));
134  MOCK_METHOD2(CallJavascriptFunction, void(const std::wstring&,
135                                            const Value& arg1));
136  MOCK_METHOD3(CallJavascriptFunction, void(const std::wstring&,
137                                            const Value& arg1,
138                                            const Value& arg2));
139};
140
141class CloudPrintURLTest : public testing::Test {
142 public:
143  CloudPrintURLTest() {}
144
145 protected:
146  virtual void SetUp() {
147    profile_.reset(new TestingProfile());
148  }
149
150  scoped_ptr<Profile> profile_;
151};
152
153TEST_F(CloudPrintURLTest, CheckDefaultURLs) {
154  std::string service_url =
155      internal_cloud_print_helpers::CloudPrintService(profile_.get()).
156      GetCloudPrintServiceURL().spec();
157  EXPECT_THAT(service_url, HasSubstr("www.google.com"));
158  EXPECT_THAT(service_url, HasSubstr("cloudprint"));
159
160  std::string dialog_url =
161      internal_cloud_print_helpers::CloudPrintService(profile_.get()).
162      GetCloudPrintServiceDialogURL().spec();
163  EXPECT_THAT(dialog_url, HasSubstr("www.google.com"));
164  EXPECT_THAT(dialog_url, HasSubstr("/cloudprint/"));
165  EXPECT_THAT(dialog_url, HasSubstr("/client/"));
166  EXPECT_THAT(dialog_url, Not(HasSubstr("cloudprint/cloudprint")));
167  EXPECT_THAT(dialog_url, HasSubstr("/dialog.html"));
168
169  // Repeat to make sure there isn't a transient glitch.
170  dialog_url =
171      internal_cloud_print_helpers::CloudPrintService(profile_.get()).
172      GetCloudPrintServiceDialogURL().spec();
173  EXPECT_THAT(dialog_url, HasSubstr("www.google.com"));
174  EXPECT_THAT(dialog_url, HasSubstr("/cloudprint/"));
175  EXPECT_THAT(dialog_url, HasSubstr("/client/"));
176  EXPECT_THAT(dialog_url, Not(HasSubstr("cloudprint/cloudprint")));
177  EXPECT_THAT(dialog_url, HasSubstr("/dialog.html"));
178}
179
180// Testing for CloudPrintDataSender needs a mock DOMUI.
181class CloudPrintDataSenderTest : public testing::Test {
182 public:
183  CloudPrintDataSenderTest()
184      : file_thread_(ChromeThread::FILE, &message_loop_),
185        io_thread_(ChromeThread::IO, &message_loop_) {}
186
187 protected:
188  virtual void SetUp() {
189    string16 mock_job_title(ASCIIToUTF16(kMockJobTitle));
190    mock_helper_.reset(new MockCloudPrintDataSenderHelper);
191    print_data_sender_ =
192        new CloudPrintDataSender(mock_helper_.get(), mock_job_title);
193  }
194
195  scoped_refptr<CloudPrintDataSender> print_data_sender_;
196  scoped_ptr<MockCloudPrintDataSenderHelper> mock_helper_;
197
198  MessageLoop message_loop_;
199  ChromeThread file_thread_;
200  ChromeThread io_thread_;
201};
202
203// TODO(scottbyer): DISABLED until the binary test file can get
204// checked in separate from the patch.
205TEST_F(CloudPrintDataSenderTest, CanSend) {
206  StringValue mock_job_title(kMockJobTitle);
207  EXPECT_CALL(*mock_helper_,
208              CallJavascriptFunction(_, _, StringValueEq(&mock_job_title))).
209      WillOnce(Return());
210
211  FilePath test_data_file_name = GetTestDataFileName();
212  ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
213                         NewRunnableMethod(
214                             print_data_sender_.get(),
215                             &CloudPrintDataSender::ReadPrintDataFile,
216                             test_data_file_name));
217  MessageLoop::current()->RunAllPending();
218}
219
220TEST_F(CloudPrintDataSenderTest, BadFile) {
221  EXPECT_CALL(*mock_helper_, CallJavascriptFunction(_, _, _)).Times(0);
222
223#if defined(OS_WIN)
224  FilePath bad_data_file_name(L"/some/file/that/isnot/there");
225#else
226  FilePath bad_data_file_name("/some/file/that/isnot/there");
227#endif
228  ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
229                         NewRunnableMethod(
230                             print_data_sender_.get(),
231                             &CloudPrintDataSender::ReadPrintDataFile,
232                             bad_data_file_name));
233  MessageLoop::current()->RunAllPending();
234}
235
236TEST_F(CloudPrintDataSenderTest, EmptyFile) {
237  EXPECT_CALL(*mock_helper_, CallJavascriptFunction(_, _, _)).Times(0);
238
239  FilePath empty_data_file_name = GetEmptyDataFileName();
240  ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
241                         NewRunnableMethod(
242                             print_data_sender_.get(),
243                             &CloudPrintDataSender::ReadPrintDataFile,
244                             empty_data_file_name));
245  MessageLoop::current()->RunAllPending();
246}
247
248// Testing for CloudPrintFlowHandler needs a mock
249// CloudPrintHtmlDialogDelegate, mock CloudPrintDataSender, and a mock
250// DOMUI.
251
252// Testing for CloudPrintHtmlDialogDelegate needs a mock
253// CloudPrintFlowHandler.
254
255using internal_cloud_print_helpers::MockCloudPrintFlowHandler;
256using internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate;
257
258class CloudPrintHtmlDialogDelegateTest : public testing::Test {
259 public:
260  CloudPrintHtmlDialogDelegateTest()
261      : ui_thread_(ChromeThread::UI, &message_loop_) {}
262
263 protected:
264  virtual void SetUp() {
265    FilePath mock_path;
266    string16 mock_title;
267    MockCloudPrintFlowHandler* handler =
268        new MockCloudPrintFlowHandler(mock_path, mock_title);
269    mock_flow_handler_ = handler->AsWeakPtr();
270    EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(_));
271    EXPECT_CALL(*mock_flow_handler_.get(), SetDialogDelegate(NULL));
272    delegate_.reset(new CloudPrintHtmlDialogDelegate(
273        mock_flow_handler_.get(), 100, 100, std::string()));
274  }
275
276  virtual void TearDown() {
277    delegate_.reset();
278    if (mock_flow_handler_)
279      delete mock_flow_handler_.get();
280  }
281
282  MessageLoopForUI message_loop_;
283  ChromeThread ui_thread_;
284  base::WeakPtr<MockCloudPrintFlowHandler> mock_flow_handler_;
285  scoped_ptr<CloudPrintHtmlDialogDelegate> delegate_;
286};
287
288TEST_F(CloudPrintHtmlDialogDelegateTest, BasicChecks) {
289  EXPECT_TRUE(delegate_->IsDialogModal());
290  EXPECT_THAT(delegate_->GetDialogContentURL().spec(),
291              StrEq(chrome::kCloudPrintResourcesURL));
292  EXPECT_THAT(delegate_->GetDialogTitle(), HasSubstr(L"Print"));
293
294  bool close_dialog = false;
295  delegate_->OnCloseContents(NULL, &close_dialog);
296  EXPECT_TRUE(close_dialog);
297}
298
299TEST_F(CloudPrintHtmlDialogDelegateTest, OwnedFlowDestroyed) {
300  delegate_.reset();
301  EXPECT_THAT(mock_flow_handler_.get(), IsNull());
302}
303
304TEST_F(CloudPrintHtmlDialogDelegateTest, UnownedFlowLetGo) {
305  std::vector<DOMMessageHandler*> handlers;
306  delegate_->GetDOMMessageHandlers(&handlers);
307  delegate_.reset();
308  EXPECT_THAT(mock_flow_handler_.get(), NotNull());
309}
310
311// Testing for ExternalHtmlDialogUI needs a mock TabContents, mock
312// CloudPrintHtmlDialogDelegate (provided through the mock
313// tab_contents)
314
315// Testing for PrintDialogCloud needs a mock Browser.
316