form_structure_browsertest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
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 <vector>
6
7#include "base/file_path.h"
8#include "base/path_service.h"
9#include "base/string_util.h"
10#include "base/utf_string_conversions.h"
11#include "chrome/browser/autofill/autofill_manager.h"
12#include "chrome/browser/autofill/form_structure.h"
13#include "chrome/browser/tab_contents/tab_contents.h"
14#include "chrome/browser/ui/browser.h"
15#include "chrome/common/chrome_paths.h"
16#include "chrome/test/in_process_browser_test.h"
17#include "chrome/test/ui_test_utils.h"
18#include "googleurl/src/gurl.h"
19
20namespace {
21
22FilePath GetInputFileDirectory() {
23  FilePath test_data_dir_;
24  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
25  test_data_dir_ = test_data_dir_.AppendASCII("autofill_heuristics")
26                                 .AppendASCII("input");
27  return test_data_dir_;
28}
29
30FilePath GetOutputFileDirectory() {
31  FilePath test_data_dir_;
32  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
33  test_data_dir_ = test_data_dir_.AppendASCII("autofill_heuristics")
34                                 .AppendASCII("output");
35  return test_data_dir_;
36}
37
38// Write |content| to |file|. Returns true on success.
39bool WriteFile(const FilePath& file, const std::string& content) {
40  int write_size = file_util::WriteFile(file, content.c_str(),
41                                        content.length());
42  return write_size == static_cast<int>(content.length());
43}
44
45// Convert |html| to URL format, and return the converted string.
46const std::string ConvertToURLFormat(const std::string& html) {
47  return std::string("data:text/html;charset=utf-8,") + html;
48}
49
50// Convert strings with platform end-of-line characters with spaces.
51const std::string NormalizeText(const std::string& text) {
52  std::string normalized = text;
53  ReplaceSubstringsAfterOffset(&normalized, 0, "\r\n", " ");
54  ReplaceSubstringsAfterOffset(&normalized, 0, "\r", " ");
55  ReplaceSubstringsAfterOffset(&normalized, 0, "\n", " ");
56  return normalized;
57}
58
59}  // namespace
60
61// Test class for verifying proper form structure as determined by AutoFill
62// heuristics. A test inputs each form file(e.g. form_[language_code].html),
63// loads its HTML content with a call to |NavigateToURL|, the |AutoFillManager|
64// associated with the tab contents is queried for the form structures that
65// were loaded and parsed. These form structures are serialized to string form.
66// If this is the first time test is run, a gold test result file is generated
67// in output directory, else the form structures are compared against the
68// existing result file.
69class FormStructureBrowserTest : public InProcessBrowserTest {
70 public:
71  FormStructureBrowserTest() {}
72  virtual ~FormStructureBrowserTest() {}
73
74 protected:
75  // Returns a vector of form structure objects associated with the given
76  // |autofill_manager|.
77  const std::vector<FormStructure*>& GetFormStructures(
78      const AutoFillManager& autofill_manager);
79
80  // Serializes the given form structures in |forms| to string form.
81  const std::string FormStructuresToString(
82      const std::vector<FormStructure*>& forms);
83
84 private:
85  // A helper utility for converting an |AutoFillFieldType| to string form.
86  const std::string AutoFillFieldTypeToString(AutoFillFieldType type);
87
88  DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest);
89};
90
91const std::vector<FormStructure*>& FormStructureBrowserTest::GetFormStructures(
92  const AutoFillManager& autofill_manager) {
93  return autofill_manager.form_structures_.get();
94}
95
96const std::string FormStructureBrowserTest::FormStructuresToString(
97    const std::vector<FormStructure*>& forms) {
98  std::string forms_string;
99  for (std::vector<FormStructure*>::const_iterator iter = forms.begin();
100       iter != forms.end();
101       ++iter) {
102
103    for (std::vector<AutoFillField*>::const_iterator field_iter =
104            (*iter)->begin();
105         field_iter != (*iter)->end();
106         ++field_iter) {
107      // The field list is NULL-terminated.  Exit loop when at the end.
108      if (!*field_iter)
109        break;
110      forms_string += AutoFillFieldTypeToString((*field_iter)->type());
111      forms_string += "\n";
112    }
113  }
114  return forms_string;
115}
116
117const std::string FormStructureBrowserTest::AutoFillFieldTypeToString(
118    AutoFillFieldType type) {
119  switch (type) {
120    case NO_SERVER_DATA:
121      return "NO_SERVER_DATA";
122    case UNKNOWN_TYPE:
123      return "UNKNOWN_TYPE";
124    case EMPTY_TYPE:
125      return "EMPTY_TYPE";
126    case NAME_FIRST:
127      return "NAME_FIRST";
128    case NAME_MIDDLE:
129      return "NAME_MIDDLE";
130    case NAME_LAST:
131      return "NAME_LAST";
132    case NAME_MIDDLE_INITIAL:
133      return "NAME_MIDDLE_INITIAL";
134    case NAME_FULL:
135      return "NAME_FULL";
136    case NAME_SUFFIX:
137      return "NAME_SUFFIX";
138    case EMAIL_ADDRESS:
139      return "EMAIL_ADDRESS";
140    case PHONE_HOME_NUMBER:
141      return "PHONE_HOME_NUMBER";
142    case PHONE_HOME_CITY_CODE:
143      return "PHONE_HOME_CITY_CODE";
144    case PHONE_HOME_COUNTRY_CODE:
145      return "PHONE_HOME_COUNTRY_CODE";
146    case PHONE_HOME_CITY_AND_NUMBER:
147      return "PHONE_HOME_CITY_AND_NUMBER";
148    case PHONE_HOME_WHOLE_NUMBER:
149      return "PHONE_HOME_WHOLE_NUMBER";
150    case PHONE_FAX_NUMBER:
151      return "PHONE_FAX_NUMBER";
152    case PHONE_FAX_CITY_CODE:
153      return "PHONE_FAX_CITY_CODE";
154    case PHONE_FAX_COUNTRY_CODE:
155      return "PHONE_FAX_COUNTRY_CODE";
156    case PHONE_FAX_CITY_AND_NUMBER:
157      return "PHONE_FAX_CITY_AND_NUMBER";
158    case PHONE_FAX_WHOLE_NUMBER:
159      return "PHONE_FAX_WHOLE_NUMBER";
160    case ADDRESS_HOME_LINE1:
161      return "ADDRESS_HOME_LINE1";
162    case ADDRESS_HOME_LINE2:
163      return "ADDRESS_HOME_LINE2";
164    case ADDRESS_HOME_APT_NUM:
165      return "ADDRESS_HOME_APT_NUM";
166    case ADDRESS_HOME_CITY:
167      return "ADDRESS_HOME_CITY";
168    case ADDRESS_HOME_STATE:
169      return "ADDRESS_HOME_STATE";
170    case ADDRESS_HOME_ZIP:
171      return "ADDRESS_HOME_ZIP";
172    case ADDRESS_HOME_COUNTRY:
173      return "ADDRESS_HOME_COUNTRY";
174    case ADDRESS_BILLING_LINE1:
175      return "ADDRESS_BILLING_LINE1";
176    case ADDRESS_BILLING_LINE2:
177      return "ADDRESS_BILLING_LINE2";
178    case ADDRESS_BILLING_APT_NUM:
179      return "ADDRESS_BILLING_APT_NUM";
180    case ADDRESS_BILLING_CITY:
181      return "ADDRESS_BILLING_CITY";
182    case ADDRESS_BILLING_STATE:
183      return "ADDRESS_BILLING_STATE";
184    case ADDRESS_BILLING_ZIP:
185      return "ADDRESS_BILLING_ZIP";
186    case ADDRESS_BILLING_COUNTRY:
187      return "ADDRESS_BILLING_COUNTRY";
188    case CREDIT_CARD_NAME:
189      return "CREDIT_CARD_NAME";
190    case CREDIT_CARD_NUMBER:
191      return "CREDIT_CARD_NUMBER";
192    case CREDIT_CARD_EXP_MONTH:
193      return "CREDIT_CARD_EXP_MONTH";
194    case CREDIT_CARD_EXP_2_DIGIT_YEAR:
195      return "CREDIT_CARD_EXP_2_DIGIT_YEAR";
196    case CREDIT_CARD_EXP_4_DIGIT_YEAR:
197      return "CREDIT_CARD_EXP_4_DIGIT_YEAR";
198    case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
199      return "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR";
200    case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR:
201      return "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR";
202    case CREDIT_CARD_TYPE:
203      return "CREDIT_CARD_TYPE";
204    case CREDIT_CARD_VERIFICATION_CODE:
205      return "CREDIT_CARD_VERIFICATION_CODE";
206    case COMPANY_NAME:
207      return "COMPANY_NAME";
208    default:
209      NOTREACHED() << "Invalid AutoFillFieldType value.";
210  }
211  return std::string();
212}
213
214IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest, HTMLFiles) {
215  FilePath input_file_path = GetInputFileDirectory();
216  file_util::FileEnumerator input_file_enumerator(input_file_path,
217      false, file_util::FileEnumerator::FILES, FILE_PATH_LITERAL("*.html"));
218
219  for (input_file_path = input_file_enumerator.Next();
220       !input_file_path.empty();
221       input_file_path = input_file_enumerator.Next()) {
222    std::string input_file_source;
223
224    ASSERT_TRUE(file_util::ReadFileToString(input_file_path,
225                                            &input_file_source));
226    input_file_source = ConvertToURLFormat(input_file_source);
227
228    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
229    ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
230        browser(), GURL(input_file_source)));
231
232    ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
233                                                       VIEW_ID_TAB_CONTAINER));
234    ASSERT_TRUE(ui_test_utils::IsViewFocused(
235        browser(),
236        VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
237
238    AutoFillManager* autofill_manager =
239        browser()->GetSelectedTabContents()->GetAutoFillManager();
240    ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager);
241    std::vector<FormStructure*> forms = GetFormStructures(*autofill_manager);
242
243    FilePath output_file_directory = GetOutputFileDirectory();
244    FilePath output_file_path = output_file_directory.Append(
245        input_file_path.BaseName().StripTrailingSeparators().ReplaceExtension(
246            FILE_PATH_LITERAL(".out")));
247
248    std::string output_file_source;
249    if (file_util::ReadFileToString(output_file_path, &output_file_source)) {
250      ASSERT_EQ(NormalizeText(output_file_source),
251                NormalizeText(
252                    FormStructureBrowserTest::FormStructuresToString(forms)));
253
254    } else {
255      ASSERT_TRUE(WriteFile(
256          output_file_path,
257          FormStructureBrowserTest::FormStructuresToString(forms)));
258    }
259  }
260}
261