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