autofill_dialog_controller_browsertest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// Use of this source code is governed by a BSD-style license that can be
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// found in the LICENSE file.
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/bind.h"
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/command_line.h"
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/memory/ref_counted.h"
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/message_loop.h"
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/strings/utf_string_conversions.h"
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "base/time.h"
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/autofill/autofill_dialog_view.h"
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/autofill/data_model_wrapper.h"
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/autofill/testable_autofill_dialog_view.h"
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/browser.h"
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/browser/ui/tabs/tab_strip_model.h"
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "chrome/test/base/in_process_browser_test.h"
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/browser/autofill_common_test.h"
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/browser/autofill_metrics.h"
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/browser/test_personal_data_manager.h"
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/browser/validation.h"
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/content/browser/wallet/wallet_test_util.h"
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/core/common/autofill_switches.h"
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/core/common/form_data.h"
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "components/autofill/core/common/form_field_data.h"
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "content/public/test/test_utils.h"
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#include "testing/gtest/include/gtest/gtest.h"
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectnamespace autofill {
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectnamespace {
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectvoid MockCallback(const FormStructure*, const std::string&) {}
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectclass MockAutofillMetrics : public AutofillMetrics {
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public:
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  MockAutofillMetrics()
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      : dialog_type_(static_cast<DialogType>(-1)),
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        dialog_dismissal_action_(
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            static_cast<AutofillMetrics::DialogDismissalAction>(-1)),
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        autocheckout_status_(
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            static_cast<AutofillMetrics::AutocheckoutCompletionStatus>(-1)) {}
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual ~MockAutofillMetrics() {}
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // AutofillMetrics:
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual void LogAutocheckoutDuration(
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      const base::TimeDelta& duration,
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      AutocheckoutCompletionStatus status) const OVERRIDE {
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // Ignore constness for testing.
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this);
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    mutable_this->autocheckout_status_ = status;
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual void LogDialogUiDuration(
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      const base::TimeDelta& duration,
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      DialogType dialog_type,
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      DialogDismissalAction dismissal_action) const OVERRIDE {
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // Ignore constness for testing.
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    MockAutofillMetrics* mutable_this = const_cast<MockAutofillMetrics*>(this);
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    mutable_this->dialog_type_ = dialog_type;
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    mutable_this->dialog_dismissal_action_ = dismissal_action;
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  DialogType dialog_type() const { return dialog_type_; }
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  AutofillMetrics::DialogDismissalAction dialog_dismissal_action() const {
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return dialog_dismissal_action_;
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  AutofillMetrics::AutocheckoutCompletionStatus autocheckout_status() const {
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return autocheckout_status_;
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private:
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  DialogType dialog_type_;
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  AutofillMetrics::DialogDismissalAction dialog_dismissal_action_;
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  AutofillMetrics::AutocheckoutCompletionStatus autocheckout_status_;
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project};
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectclass TestAutofillDialogController : public AutofillDialogControllerImpl {
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public:
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  TestAutofillDialogController(content::WebContents* contents,
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               const FormData& form_data,
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               const AutofillMetrics& metric_logger,
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               scoped_refptr<content::MessageLoopRunner> runner,
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               const DialogType dialog_type)
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      : AutofillDialogControllerImpl(contents,
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                     form_data,
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                     GURL(),
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                     dialog_type,
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                     base::Bind(&MockCallback)),
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        metric_logger_(metric_logger),
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        message_loop_runner_(runner) {}
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual ~TestAutofillDialogController() {}
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual void ViewClosed() OVERRIDE {
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    message_loop_runner_->Quit();
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    AutofillDialogControllerImpl::ViewClosed();
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual string16 InputValidityMessage(
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      DialogSection section,
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      AutofillFieldType type,
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      const string16& value) OVERRIDE {
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return string16();
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual ValidityData InputsAreValid(
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      DialogSection section,
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      const DetailOutputMap& inputs,
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      ValidationType validation_type) OVERRIDE {
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return ValidityData();
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // Saving to Chrome is tested in AutofillDialogController unit tests.
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // TODO(estade): test that the view defaults to saving to Chrome.
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual bool ShouldOfferToSaveInChrome() const OVERRIDE {
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return false;
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // Increase visibility for testing.
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  using AutofillDialogControllerImpl::view;
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  using AutofillDialogControllerImpl::input_showing_popup;
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual std::vector<DialogNotification> CurrentNotifications() OVERRIDE {
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return notifications_;
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  void set_notifications(const std::vector<DialogNotification>& notifications) {
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    notifications_ = notifications;
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  TestPersonalDataManager* GetTestingManager() {
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return &test_manager_;
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  using AutofillDialogControllerImpl::DisableWallet;
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  using AutofillDialogControllerImpl::IsEditingExistingData;
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected:
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual PersonalDataManager* GetManager() OVERRIDE {
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return &test_manager_;
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private:
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // To specify our own metric logger.
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return metric_logger_;
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  const AutofillMetrics& metric_logger_;
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  TestPersonalDataManager test_manager_;
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // A list of notifications to show in the notification area of the dialog.
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  // This is used to control what |CurrentNotifications()| returns for testing.
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  std::vector<DialogNotification> notifications_;
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project};
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project}  // namespace
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectclass AutofillDialogControllerTest : public InProcessBrowserTest {
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public:
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  AutofillDialogControllerTest() {}
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  virtual ~AutofillDialogControllerTest() {}
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  void InitializeControllerOfType(DialogType dialog_type) {
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    FormData form;
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.name = ASCIIToUTF16("TestForm");
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.method = ASCIIToUTF16("POST");
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.origin = GURL("http://example.com/form.html");
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.action = GURL("http://example.com/submit.html");
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.user_submitted = true;
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    FormFieldData field;
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    field.autocomplete_attribute = "email";
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    form.fields.push_back(field);
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    message_loop_runner_ = new content::MessageLoopRunner;
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    controller_ = new TestAutofillDialogController(
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        GetActiveWebContents(),
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        form,
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        metric_logger_,
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        message_loop_runner_,
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        dialog_type);
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    controller_->Show();
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  content::WebContents* GetActiveWebContents() {
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    return browser()->tab_strip_model()->GetActiveWebContents();
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  const MockAutofillMetrics& metric_logger() { return metric_logger_; }
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  TestAutofillDialogController* controller() { return controller_; }
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  void RunMessageLoop() {
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    message_loop_runner_->Run();
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  }
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private:
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  MockAutofillMetrics metric_logger_;
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  TestAutofillDialogController* controller_;  // Weak reference.
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerTest);
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project};
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// TODO(isherman): Enable these tests on other platforms once the UI is
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// implemented on those platforms.
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project#if defined(TOOLKIT_VIEWS)
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// Submit the form data.
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source ProjectIN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Submit) {
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  controller()->view()->GetTestableView()->SubmitForTesting();
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  RunMessageLoop();
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            metric_logger().dialog_dismissal_action());
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  EXPECT_EQ(DIALOG_TYPE_REQUEST_AUTOCOMPLETE, metric_logger().dialog_type());
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project}
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// Cancel out of the dialog.
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source ProjectIN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Cancel) {
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project  controller()->view()->GetTestableView()->CancelForTesting();
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
231  RunMessageLoop();
232
233  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
234            metric_logger().dialog_dismissal_action());
235  EXPECT_EQ(DIALOG_TYPE_REQUEST_AUTOCOMPLETE, metric_logger().dialog_type());
236}
237
238// Take some other action that dismisses the dialog.
239IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, Hide) {
240  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
241  controller()->Hide();
242
243  RunMessageLoop();
244
245  EXPECT_EQ(AutofillMetrics::DIALOG_CANCELED,
246            metric_logger().dialog_dismissal_action());
247  EXPECT_EQ(DIALOG_TYPE_REQUEST_AUTOCOMPLETE, metric_logger().dialog_type());
248}
249
250// Test Autocheckout success metrics.
251IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutSuccess) {
252  InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
253  controller()->view()->GetTestableView()->SubmitForTesting();
254
255  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
256            metric_logger().dialog_dismissal_action());
257  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
258
259  controller()->OnAutocheckoutSuccess();
260  controller()->view()->GetTestableView()->CancelForTesting();
261  RunMessageLoop();
262
263  EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_SUCCEEDED,
264            metric_logger().autocheckout_status());
265
266  // Ensure closing the dialog doesn't fire any new metrics.
267  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
268            metric_logger().dialog_dismissal_action());
269  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
270}
271
272// Test Autocheckout failure metric.
273IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutError) {
274  InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
275  controller()->view()->GetTestableView()->SubmitForTesting();
276
277  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
278            metric_logger().dialog_dismissal_action());
279  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
280
281  controller()->OnAutocheckoutError();
282  controller()->view()->GetTestableView()->CancelForTesting();
283  RunMessageLoop();
284
285  EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_FAILED,
286            metric_logger().autocheckout_status());
287
288  // Ensure closing the dialog doesn't fire any new metrics.
289  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
290            metric_logger().dialog_dismissal_action());
291  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
292}
293
294IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, AutocheckoutCancelled) {
295  InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
296  controller()->view()->GetTestableView()->SubmitForTesting();
297
298  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
299            metric_logger().dialog_dismissal_action());
300  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
301
302  controller()->view()->GetTestableView()->CancelForTesting();
303  RunMessageLoop();
304
305  EXPECT_EQ(AutofillMetrics::AUTOCHECKOUT_CANCELLED,
306            metric_logger().autocheckout_status());
307
308  // Ensure closing the dialog doesn't fire any new metrics.
309  EXPECT_EQ(AutofillMetrics::DIALOG_ACCEPTED,
310            metric_logger().dialog_dismissal_action());
311  EXPECT_EQ(DIALOG_TYPE_AUTOCHECKOUT, metric_logger().dialog_type());
312}
313
314IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillInputFromAutofill) {
315  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
316  controller()->DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
317
318  AutofillProfile full_profile(test::GetFullProfile());
319  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
320
321  const DetailInputs& inputs =
322      controller()->RequestedFieldsForSection(SECTION_SHIPPING);
323  const DetailInput& triggering_input = inputs[0];
324  string16 value = full_profile.GetRawInfo(triggering_input.type);
325  TestableAutofillDialogView* view = controller()->view()->GetTestableView();
326  view->SetTextContentsOfInput(triggering_input,
327                               value.substr(0, value.size() / 2));
328  view->ActivateInput(triggering_input);
329
330  ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
331  controller()->DidAcceptSuggestion(string16(), 0);
332
333  // All inputs should be filled.
334  AutofillProfileWrapper wrapper(&full_profile, 0);
335  for (size_t i = 0; i < inputs.size(); ++i) {
336    EXPECT_EQ(wrapper.GetInfo(inputs[i].type),
337              view->GetTextContentsOfInput(inputs[i]));
338  }
339
340  // Now simulate some user edits and try again.
341  std::vector<string16> expectations;
342  for (size_t i = 0; i < inputs.size(); ++i) {
343    string16 users_input = i % 2 == 0 ? string16() : ASCIIToUTF16("dummy");
344    view->SetTextContentsOfInput(inputs[i], users_input);
345    // Empty inputs should be filled, others should be left alone.
346    string16 expectation =
347        &inputs[i] == &triggering_input || users_input.empty() ?
348        wrapper.GetInfo(inputs[i].type) :
349        users_input;
350    expectations.push_back(expectation);
351  }
352
353  view->SetTextContentsOfInput(triggering_input,
354                               value.substr(0, value.size() / 2));
355  view->ActivateInput(triggering_input);
356  ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
357  controller()->DidAcceptSuggestion(string16(), 0);
358
359  for (size_t i = 0; i < inputs.size(); ++i) {
360    EXPECT_EQ(expectations[i], view->GetTextContentsOfInput(inputs[i]));
361  }
362}
363
364// Test that the Autocheckout progress bar is showing after submitting the
365// dialog for controller with type DIALOG_TYPE_AUTOCHECKOUT.
366IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
367                       AutocheckoutShowsProgressBar) {
368  InitializeControllerOfType(DIALOG_TYPE_AUTOCHECKOUT);
369  EXPECT_TRUE(controller()->ShouldShowDetailArea());
370  EXPECT_FALSE(controller()->ShouldShowProgressBar());
371
372  controller()->view()->GetTestableView()->SubmitForTesting();
373  EXPECT_FALSE(controller()->ShouldShowDetailArea());
374  EXPECT_TRUE(controller()->ShouldShowProgressBar());
375}
376
377// Test that the Autocheckout progress bar is not showing after submitting the
378// dialog for controller with type DIALOG_TYPE_REQUEST_AUTOCOMPLETE.
379IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
380                       RequestAutocompleteDoesntShowProgressBar) {
381  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
382  EXPECT_TRUE(controller()->ShouldShowDetailArea());
383  EXPECT_FALSE(controller()->ShouldShowProgressBar());
384
385  controller()->view()->GetTestableView()->SubmitForTesting();
386  EXPECT_TRUE(controller()->ShouldShowDetailArea());
387  EXPECT_FALSE(controller()->ShouldShowProgressBar());
388}
389
390// Tests that changing the value of a CC expiration date combobox works as
391// expected when Autofill is used to fill text inputs.
392IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, FillComboboxFromAutofill) {
393  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
394  controller()->DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
395
396  CreditCard card1;
397  test::SetCreditCardInfo(&card1, "JJ Smith", "4111111111111111", "12", "2018");
398  controller()->GetTestingManager()->AddTestingCreditCard(&card1);
399  CreditCard card2;
400  test::SetCreditCardInfo(&card2, "B Bird", "3111111111111111", "11", "2017");
401  controller()->GetTestingManager()->AddTestingCreditCard(&card2);
402  AutofillProfile full_profile(test::GetFullProfile());
403  controller()->GetTestingManager()->AddTestingProfile(&full_profile);
404
405  const DetailInputs& inputs =
406      controller()->RequestedFieldsForSection(SECTION_CC);
407  const DetailInput& triggering_input = inputs[0];
408  string16 value = card1.GetRawInfo(triggering_input.type);
409  TestableAutofillDialogView* view = controller()->view()->GetTestableView();
410  view->SetTextContentsOfInput(triggering_input,
411                               value.substr(0, value.size() / 2));
412  view->ActivateInput(triggering_input);
413
414  ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
415  controller()->DidAcceptSuggestion(string16(), 0);
416
417  // All inputs should be filled.
418  AutofillCreditCardWrapper wrapper1(&card1);
419  for (size_t i = 0; i < inputs.size(); ++i) {
420    EXPECT_EQ(wrapper1.GetInfo(inputs[i].type),
421              view->GetTextContentsOfInput(inputs[i]));
422  }
423
424  // Try again with different data. Only expiration date and the triggering
425  // input should be overwritten.
426  value = card2.GetRawInfo(triggering_input.type);
427  view->SetTextContentsOfInput(triggering_input,
428                               value.substr(0, value.size() / 2));
429  view->ActivateInput(triggering_input);
430  ASSERT_EQ(&triggering_input, controller()->input_showing_popup());
431  controller()->DidAcceptSuggestion(string16(), 0);
432
433  AutofillCreditCardWrapper wrapper2(&card2);
434  for (size_t i = 0; i < inputs.size(); ++i) {
435    const DetailInput& input = inputs[i];
436    if (&input == &triggering_input ||
437        input.type == CREDIT_CARD_EXP_MONTH ||
438        input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
439      EXPECT_EQ(wrapper2.GetInfo(input.type),
440                view->GetTextContentsOfInput(input));
441    } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) {
442      EXPECT_TRUE(view->GetTextContentsOfInput(input).empty());
443    } else {
444      EXPECT_EQ(wrapper1.GetInfo(input.type),
445                view->GetTextContentsOfInput(input));
446    }
447  }
448
449  // Now fill from a profile. It should not overwrite any CC info.
450  const DetailInputs& billing_inputs =
451      controller()->RequestedFieldsForSection(SECTION_BILLING);
452  const DetailInput& billing_triggering_input = billing_inputs[0];
453  value = full_profile.GetRawInfo(triggering_input.type);
454  view->SetTextContentsOfInput(billing_triggering_input,
455                               value.substr(0, value.size() / 2));
456  view->ActivateInput(billing_triggering_input);
457
458  ASSERT_EQ(&billing_triggering_input, controller()->input_showing_popup());
459  controller()->DidAcceptSuggestion(string16(), 0);
460
461  for (size_t i = 0; i < inputs.size(); ++i) {
462    const DetailInput& input = inputs[i];
463    if (&input == &triggering_input ||
464        input.type == CREDIT_CARD_EXP_MONTH ||
465        input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
466      EXPECT_EQ(wrapper2.GetInfo(input.type),
467                view->GetTextContentsOfInput(input));
468    } else if (input.type == CREDIT_CARD_VERIFICATION_CODE) {
469      EXPECT_TRUE(view->GetTextContentsOfInput(input).empty());
470    } else {
471      EXPECT_EQ(wrapper1.GetInfo(input.type),
472                view->GetTextContentsOfInput(input));
473    }
474  }
475}
476
477// Tests that credit card number is disabled while editing a Wallet instrument.
478IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, WalletCreditCardDisabled) {
479  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
480  controller()->OnUserNameFetchSuccess("user@example.com");
481
482  scoped_ptr<wallet::WalletItems> wallet_items = wallet::GetTestWalletItems();
483  wallet_items->AddInstrument(wallet::GetTestMaskedInstrument());
484  controller()->OnDidGetWalletItems(wallet_items.Pass());
485
486  // Click "Edit" in the billing section (while using Wallet).
487  controller()->EditClickedForSection(SECTION_CC_BILLING);
488
489  const DetailInputs& edit_inputs =
490      controller()->RequestedFieldsForSection(SECTION_CC_BILLING);
491  size_t i;
492  for (i = 0; i < edit_inputs.size(); ++i) {
493    if (edit_inputs[i].type == CREDIT_CARD_NUMBER) {
494      EXPECT_FALSE(edit_inputs[i].editable);
495      break;
496    }
497  }
498  ASSERT_LT(i, edit_inputs.size());
499
500  // Select "Add new billing info..." while using Wallet.
501  ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC_BILLING);
502  model->ActivatedAt(model->GetItemCount() - 2);
503
504  const DetailInputs& add_inputs =
505      controller()->RequestedFieldsForSection(SECTION_CC_BILLING);
506  for (i = 0; i < add_inputs.size(); ++i) {
507    if (add_inputs[i].type == CREDIT_CARD_NUMBER) {
508      EXPECT_TRUE(add_inputs[i].editable);
509      break;
510    }
511  }
512  ASSERT_LT(i, add_inputs.size());
513}
514
515// Ensure that expired cards trigger invalid suggestions.
516IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, ExpiredCard) {
517  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
518  controller()->DisableWallet(wallet::WalletClient::UNKNOWN_ERROR);
519
520  CreditCard verified_card(test::GetCreditCard());
521  verified_card.set_origin("Chrome settings");
522  ASSERT_TRUE(verified_card.IsVerified());
523  controller()->GetTestingManager()->AddTestingCreditCard(&verified_card);
524
525  CreditCard expired_card(test::GetCreditCard());
526  expired_card.set_origin("Chrome settings");
527  expired_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2007"));
528  ASSERT_TRUE(expired_card.IsVerified());
529  ASSERT_FALSE(
530      autofill::IsValidCreditCardExpirationDate(
531          expired_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR),
532          expired_card.GetRawInfo(CREDIT_CARD_EXP_MONTH),
533          base::Time::Now()));
534  controller()->GetTestingManager()->AddTestingCreditCard(&expired_card);
535
536  ui::MenuModel* model = controller()->MenuModelForSection(SECTION_CC);
537  ASSERT_EQ(4, model->GetItemCount());
538
539  ASSERT_TRUE(model->IsItemCheckedAt(0));
540  EXPECT_FALSE(controller()->IsEditingExistingData(SECTION_CC));
541
542  model->ActivatedAt(1);
543  ASSERT_TRUE(model->IsItemCheckedAt(1));
544  EXPECT_TRUE(controller()->IsEditingExistingData(SECTION_CC));
545}
546
547// Notifications with long message text should not make the dialog bigger.
548IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, LongNotifications) {
549  InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
550
551  const gfx::Size no_notification_size =
552      controller()->view()->GetTestableView()->GetSize();
553  ASSERT_GT(no_notification_size.width(), 0);
554
555  std::vector<DialogNotification> notifications;
556  notifications.push_back(
557      DialogNotification(DialogNotification::DEVELOPER_WARNING, ASCIIToUTF16(
558          "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
559          "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
560          "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
561          "aliquip ex ea commodo consequat. Duis aute irure dolor in "
562          "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
563          "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
564          "culpa qui officia deserunt mollit anim id est laborum.")));
565  controller()->set_notifications(notifications);
566  controller()->view()->UpdateNotificationArea();
567
568  EXPECT_EQ(no_notification_size.width(),
569            controller()->view()->GetTestableView()->GetSize().width());
570}
571#endif  // defined(TOOLKIT_VIEWS)
572
573}  // namespace autofill
574