Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: ios/chrome/browser/autofill/autofill_controller_js_unittest.mm

Issue 2580363002: Upstream Chrome on iOS source code [1/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 #import <UIKit/UIKit.h>
6
7 #include "base/format_macros.h"
8 #include "base/ios/ios_util.h"
9 #include "base/strings/sys_string_conversions.h"
10 #include "components/autofill/core/common/autofill_constants.h"
11 #include "ios/chrome/browser/web/chrome_web_test.h"
12 #import "ios/web/public/test/web_js_test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/gtest_mac.h"
15
16 #if !defined(__has_feature) || !__has_feature(objc_arc)
17 #error "This file requires ARC support."
18 #endif
19
20 // Unit tests for ios/chrome/browser/web/resources/autofill_controller.js
21 namespace {
22
23 // Structure for getting element by name using JavaScripts.
24 struct ElementByName {
25 // The name of the element.
26 const char* element_name;
27 // The index in the elements that have |element_name|.
28 const int index;
29 // The option index if the element is a select, -1 otherwise.
30 const int option_index;
31 };
32
33 // TODO(crbug.com/619982): MobileSafari/iOS10 corrected
34 // HTMLInputElement.maxLength with the specification
35 // ( https://bugs.webkit.org/show_bug.cgi?id=154906 ). Add support for old and
36 // new default maxLength value until we drop iOS 9.
37 NSString* GetDefaultMaxLengthString() {
38 return base::ios::IsRunningOnIOS10OrLater() ? @"-1" : @"524288";
39 }
40 NSNumber* GetDefaultMaxLength() {
41 return base::ios::IsRunningOnIOS10OrLater() ? @-1 : @524288;
42 }
43
44 // Generates the JavaScript that gets an element by name.
45 NSString* GetElementByNameJavaScript(ElementByName element) {
46 NSString* query =
47 [NSString stringWithFormat:@"window.document.getElementsByName('%s')[%d]",
48 element.element_name, element.index];
49 if (element.option_index >= 0) {
50 query =
51 [query stringByAppendingFormat:@".options[%d]", element.option_index];
52 }
53 return query;
54 }
55
56 // Generates an array of JavaScripts that get each element in |elements| by
57 // name.
58 NSArray* GetElementsByNameJavaScripts(const ElementByName elements[],
59 size_t elements_size) {
60 NSMutableArray* array = [NSMutableArray array];
61 for (size_t i = 0; i < elements_size; ++i) {
62 NSString* query = GetElementByNameJavaScript(elements[i]);
63 [array addObject:query];
64 }
65 return array;
66 }
67
68 // clang-format off
69 NSString* kHTMLForTestingElements = @"<html><body>"
70 "<input type=hidden name='gl' value='us'>"
71 "<form name='testform'>"
72 " <input type=hidden name='hl' value='en'>"
73 " <input type='text' name='firstname'>"
74 " <input type='text' name='lastname'>"
75 " <input type='email' name='email'>"
76 " <input type='tel' name='phone'>"
77 " <input type='url' autocomplete='off' name='blog'>"
78 " <input type='number' name='expected number of clicks'>"
79 " <input type='password' autocomplete='off' name='pwd'>"
80 " <input type='checkbox' name='vehicle' value='Bike'>"
81 " <input type='checkbox' name='vehicle' value='Car'>"
82 " <input type='checkbox' name='vehicle' value='Rocket'>"
83 " <input type='radio' name='boolean' value='true'>"
84 " <input type='radio' name='boolean' value='false'>"
85 " <input type='radio' name='boolean' value='other'>"
86 " <label>State:"
87 " <select name='state'>"
88 " <option value='CA'>CA</option>"
89 " <option value='MA'>MA</option>"
90 " </select>"
91 " </label>"
92 " <label>Course:"
93 " <select name='course'>"
94 " <optgroup label='8.01 Physics I: Classical Mechanics'>"
95 " <option value='8.01.1'>Lecture 01: Powers of Ten"
96 " <option value='8.01.2'>Lecture 02: 1D Kinematics"
97 " <option value='8.01.3'>Lecture 03: Vectors"
98 " <optgroup label='8.02 Electricity and Magnestism'>"
99 " <option value='8.02.1'>Lecture 01: What holds our world together?"
100 " <option value='8.02.2'>Lecture 02: Electric Field"
101 " <option value='8.02.3'>Lecture 03: Electric Flux"
102 " </select>"
103 " </label>"
104 " <label>Cars:"
105 " <select name='cars' multiple>"
106 " <option value='volvo'>Volvo</option>"
107 " <option value='saab'>Saab</option>"
108 " <option value='opel'>Opel</option>"
109 " <option value='audi'>Audi</option>"
110 " </select>"
111 " </label>"
112 " <input type='submit' name='submit' value='Submit'>"
113 "</form>"
114 "</body></html>";
115 // clang-format on
116
117 // A bit field mask to extract data from WebFormControlElement. They are from
118 // autofill_controller.js
119 enum ExtractMask {
120 EXTRACT_NONE = 0,
121 EXTRACT_VALUE = 1 << 0, // Extract value from WebFormControlElement.
122 EXTRACT_OPTION_TEXT = 1 << 1, // Extract option text from
123 // WebFormSelectElement. Only valid when
124 // |EXTRACT_VALUE| is set.
125 // This is used for form submission where
126 // human readable value is captured.
127 EXTRACT_OPTIONS = 1 << 2, // Extract options from
128 // WebFormControlElement.
129 };
130
131 const ExtractMask kFormExtractMasks[] = {
132 EXTRACT_NONE, EXTRACT_VALUE, EXTRACT_OPTION_TEXT, EXTRACT_OPTIONS,
133 };
134
135 // Gets the attributes to check for a mask in |kFormExtractMasks|.
136 NSArray* GetFormFieldAttributeListsToCheck(NSUInteger mask) {
137 if (!(mask & EXTRACT_VALUE)) {
138 return @[
139 @"name", @"form_control_type", @"autocomplete_attribute", @"max_length",
140 @"should_autocomplete", @"is_checkable"
141 ];
142 }
143
144 if (mask & EXTRACT_OPTIONS) {
145 return @[
146 @"name", @"form_control_type", @"autocomplete_attribute", @"max_length",
147 @"should_autocomplete", @"is_checkable", @"value", @"option_values",
148 @"option_contents"
149 ];
150 }
151
152 return @[
153 @"name", @"form_control_type", @"autocomplete_attribute", @"max_length",
154 @"should_autocomplete", @"is_checkable", @"value"
155 ];
156 }
157
158 // ***** Clang-formatting is disabled for the following block of testdata *****
159 // clang-format off
160
161 // Getters for form control element testing data. The returned data is
162 // an array consisting of an html fragment followed by an array
163 // of dictionaries containing the expected field attributes for elements in the
164 // given html fragment.
165 NSArray* GetTestFormInputElementWithLabelFromPrevious() {
166 return @[
167 @("* First name: "
168 "<INPUT type='text' name='firstname' value='John'/>"),
169 [NSDictionary dictionaryWithObjectsAndKeys:
170 @"'* First name:'", @"label",
171 @"'firstname'", @"name",
172 @"'text'", @"form_control_type",
173 @"undefined", @"autocomplete_attribute",
174 GetDefaultMaxLengthString(), @"max_length",
175 @"true", @"should_autocomplete",
176 @"false", @"is_checkable",
177 @"'John'", @"value",
178 @"'John'", @"value_option_text",
179 @"undefined", @"option_values",
180 @"undefined", @"option_contents",
181 nil]];
182 }
183
184 NSArray* GetTestFormInputElementWithLabelFromPreviousSpan() {
185 return @[
186 @("* Last name<span>:</span> "
187 "<INPUT type='text' name='lastname' value='John'/>"),
188 [NSDictionary dictionaryWithObjectsAndKeys:
189 @"'* Last name:'", @"label",
190 @"'lastname'", @"name",
191 @"'text'", @"form_control_type",
192 @"undefined", @"autocomplete_attribute",
193 GetDefaultMaxLengthString(), @"max_length",
194 @"true", @"should_autocomplete",
195 @"false", @"is_checkable",
196 @"'John'", @"value",
197 @"'John'", @"value_option_text",
198 @"undefined", @"option_values",
199 @"undefined", @"option_contents",
200 nil]];
201 }
202
203 NSArray* GetTestFormInputElementWithLabelFromPreviousParagraph() {
204 return @[
205 @("<p>* Email:</p> "
206 "<INPUT type='email' name='email' value='john@example.com'/>"),
207 [NSDictionary dictionaryWithObjectsAndKeys:
208 @"'* Email:'", @"label",
209 @"'email'", @"name",
210 @"'email'", @"form_control_type",
211 @"undefined", @"autocomplete_attribute",
212 GetDefaultMaxLengthString(), @"max_length",
213 @"true", @"should_autocomplete",
214 @"false", @"is_checkable",
215 @"'john@example.com'", @"value",
216 @"'john@example.com'", @"value_option_text",
217 @"undefined", @"option_values",
218 @"undefined", @"option_contents",
219 nil]];
220 }
221
222 NSArray* GetTestFormInputElementWithLabelFromPreviousLabel() {
223 return @[
224 @("<label>* Telephone: </label> "
225 "<INPUT type='tel' id='telephone' value='12345678'/>"),
226 [NSDictionary dictionaryWithObjectsAndKeys:
227 @"'* Telephone:'", @"label",
228 @"'telephone'", @"name",
229 @"'tel'", @"form_control_type",
230 @"undefined", @"autocomplete_attribute",
231 GetDefaultMaxLengthString(), @"max_length",
232 @"true", @"should_autocomplete",
233 @"false", @"is_checkable",
234 @"'12345678'", @"value",
235 @"'12345678'", @"value_option_text",
236 @"undefined", @"option_values",
237 @"undefined", @"option_contents",
238 nil]];
239 }
240
241 NSArray* GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored() {
242 return @[
243 @("Other Text <label>* Blog:</label> "
244 "<INPUT type='url' autocomplete='off' value='www.jogh.blog'/>"),
245 [NSDictionary dictionaryWithObjectsAndKeys:
246 @"'* Blog:'", @"label",
247 @"''", @"name",
248 @"'url'", @"form_control_type",
249 @"'off'", @"autocomplete_attribute",
250 GetDefaultMaxLengthString(), @"max_length",
251 @"false", @"should_autocomplete",
252 @"false", @"is_checkable",
253 @"'www.jogh.blog'", @"value",
254 @"'www.jogh.blog'", @"value_option_text",
255 @"undefined", @"option_values",
256 @"undefined", @"option_contents",
257 nil]];
258 }
259
260 NSArray* GetTestFormInputElementWithLabelFromPreviousTextSpanBr() {
261 return @[
262 @("* Expected visits<span>:</span> <br>"
263 "<INPUT type='number' name='expected number of clicks'/>"),
264 [NSDictionary dictionaryWithObjectsAndKeys:
265 @"'* Expected visits:'", @"label",
266 @"'expected number of clicks'", @"name",
267 @"'number'", @"form_control_type",
268 @"undefined", @"autocomplete_attribute",
269 GetDefaultMaxLengthString(), @"max_length",
270 @"true", @"should_autocomplete",
271 @"false", @"is_checkable",
272 @"''", @"value",
273 @"''", @"value_option_text",
274 @"undefined", @"option_values",
275 @"undefined", @"option_contents",
276 nil]];
277 }
278
279 NSArray* GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan() {
280 return @[
281 @("Other <br> * Password<span>:</span> "
282 "<INPUT type='password' autocomplete='off' name='pwd'/>"),
283 [NSDictionary dictionaryWithObjectsAndKeys:
284 @"'* Password:'", @"label",
285 @"'pwd'", @"name",
286 @"'password'", @"form_control_type",
287 @"'off'", @"autocomplete_attribute",
288 GetDefaultMaxLengthString(), @"max_length",
289 @"false", @"should_autocomplete",
290 @"false", @"is_checkable",
291 @"''", @"value",
292 @"''", @"value_option_text",
293 @"undefined", @"option_values",
294 @"undefined", @"option_contents",
295 nil]];
296 }
297
298 NSArray* GetTestFormInputElementWithLabelFromListItem() {
299 return @[
300 @("<LI>"
301 "<LABEL><EM>*</EM> Code:</LABEL>"
302 "<INPUT type='text' id='first code' value='415'/>"
303 "<INPUT type='text' id='middle code' value='555'/>"
304 "<INPUT type='text' id='last code' value='1212'/>"
305 "</LI>"),
306 [NSDictionary dictionaryWithObjectsAndKeys:
307 @"'* Code:'", @"label",
308 @"'first code'", @"name",
309 @"'text'", @"form_control_type",
310 @"undefined", @"autocomplete_attribute",
311 GetDefaultMaxLengthString(), @"max_length",
312 @"true", @"should_autocomplete",
313 @"false", @"is_checkable",
314 @"'415'", @"value",
315 @"'415'", @"value_option_text",
316 @"undefined", @"option_values",
317 @"undefined", @"option_contents",
318 nil],
319 [NSDictionary dictionaryWithObjectsAndKeys:
320 @"'* Code:'", @"label",
321 @"'middle code'", @"name",
322 @"'text'", @"form_control_type",
323 @"undefined", @"autocomplete_attribute",
324 GetDefaultMaxLengthString(), @"max_length",
325 @"true", @"should_autocomplete",
326 @"false", @"is_checkable",
327 @"'555'", @"value",
328 @"'555'", @"value_option_text",
329 @"undefined", @"option_values",
330 @"undefined", @"option_contents",
331 nil],
332 [NSDictionary dictionaryWithObjectsAndKeys:
333 @"'* Code:'", @"label",
334 @"'last code'", @"name",
335 @"'text'", @"form_control_type",
336 @"undefined", @"autocomplete_attribute",
337 GetDefaultMaxLengthString(), @"max_length",
338 @"true", @"should_autocomplete",
339 @"false", @"is_checkable",
340 @"'1212'", @"value",
341 @"'1212'", @"value_option_text",
342 @"undefined", @"option_values",
343 @"undefined", @"option_contents",
344 nil]];
345 }
346
347 NSArray* GetTestFormInputElementWithLabelFromTableColumnTD() {
348 return @[
349 @("<TABLE>"
350 "<TR>"
351 " <TD>* First name:</TD>"
352 " <TD><INPUT type='text' id='tabletdname' value='John'/></TD>"
353 "</TR>"
354 "<TR>"
355 " <TD>Email:</TD>"
356 " <TD><INPUT type='email' id='tabletdemail'"
357 " value='john@example.com'/></TD>"
358 "</TR>"
359 "</TABLE>"),
360 [NSDictionary dictionaryWithObjectsAndKeys:
361 @"'* First name:'", @"label",
362 @"'tabletdname'", @"name",
363 @"'text'", @"form_control_type",
364 @"undefined", @"autocomplete_attribute",
365 GetDefaultMaxLengthString(), @"max_length",
366 @"true", @"should_autocomplete",
367 @"false", @"is_checkable",
368 @"'John'", @"value",
369 @"'John'", @"value_option_text",
370 @"undefined", @"option_values",
371 @"undefined", @"option_contents",
372 nil],
373 [NSDictionary dictionaryWithObjectsAndKeys:
374 @"'Email:'", @"label",
375 @"'tabletdemail'", @"name",
376 @"'email'", @"form_control_type",
377 @"undefined", @"autocomplete_attribute",
378 GetDefaultMaxLengthString(), @"max_length",
379 @"true", @"should_autocomplete",
380 @"false", @"is_checkable",
381 @"'john@example.com'", @"value",
382 @"'john@example.com'", @"value_option_text",
383 @"undefined", @"option_values",
384 @"undefined", @"option_contents",
385 nil]];
386 }
387
388 NSArray* GetTestFormInputElementWithLabelFromTableColumnTH() {
389 return @[
390 @("<TABLE>"
391 "<TR>"
392 " <TH>* First name:</TH>"
393 " <TD><INPUT type='text' name='nameintableth' value='John'/></TD>"
394 "</TR>"
395 "<TR>"
396 " <TD>Email:</TD>"
397 " <TD><INPUT type='email' id='emailtableth'"
398 " value='john@example.com'/></TD>"
399 "</TR>"
400 "</TABLE>"),
401 [NSDictionary dictionaryWithObjectsAndKeys:
402 @"'* First name:'", @"label",
403 @"'nameintableth'", @"name",
404 @"'text'", @"form_control_type",
405 @"undefined", @"autocomplete_attribute",
406 GetDefaultMaxLengthString(), @"max_length",
407 @"true", @"should_autocomplete",
408 @"false", @"is_checkable",
409 @"'John'", @"value",
410 @"'John'", @"value_option_text",
411 @"undefined", @"option_values",
412 @"undefined", @"option_contents",
413 nil],
414 [NSDictionary dictionaryWithObjectsAndKeys:
415 @"'Email:'", @"label",
416 @"'emailtableth'", @"name",
417 @"'email'", @"form_control_type",
418 @"undefined", @"autocomplete_attribute",
419 GetDefaultMaxLengthString(), @"max_length",
420 @"true", @"should_autocomplete",
421 @"false", @"is_checkable",
422 @"'john@example.com'", @"value",
423 @"'john@example.com'", @"value_option_text",
424 @"undefined", @"option_values",
425 @"undefined", @"option_contents",
426 nil]];
427 }
428
429 NSArray* GetTestFormInputElementWithLabelFromTableNested() {
430 return @[
431 @("<TABLE>"
432 "<TR>"
433 " <TD><FONT>* First </FONT><FONT>name:</FONT></TD>"
434 " <TD><INPUT type='text' id='nametablenested' value='John'/></TD>"
435 "</TR>"
436 "</TABLE>"),
437 [NSDictionary dictionaryWithObjectsAndKeys:
438 @"'* First name:'", @"label",
439 @"'nametablenested'", @"name",
440 @"'text'", @"form_control_type",
441 @"undefined", @"autocomplete_attribute",
442 GetDefaultMaxLengthString(), @"max_length",
443 @"true", @"should_autocomplete",
444 @"false", @"is_checkable",
445 @"'John'", @"value",
446 @"'John'", @"value_option_text",
447 @"undefined", @"option_values",
448 @"undefined", @"option_contents",
449 nil]];
450 }
451
452 NSArray* GetTestFormInputElementWithLabelFromTableRow() {
453 return @[
454 @("<TABLE>"
455 "<TR>"
456 " <TD>* <FONT>First </FONT><FONT>name:</FONT></TD>"
457 "</TR>"
458 "<TR>"
459 " <TD><INPUT type='text' name='nametablerow' value='John'/></TD>"
460 "</TR>"
461 "</TABLE>"),
462 [NSDictionary dictionaryWithObjectsAndKeys:
463 @"'* First name:'", @"label",
464 @"'nametablerow'", @"name",
465 @"'text'", @"form_control_type",
466 @"undefined", @"autocomplete_attribute",
467 GetDefaultMaxLengthString(), @"max_length",
468 @"true", @"should_autocomplete",
469 @"false", @"is_checkable",
470 @"'John'", @"value",
471 @"'John'", @"value_option_text",
472 @"undefined", @"option_values",
473 @"undefined", @"option_contents",
474 nil]];
475 }
476
477 NSArray* GetTestFormInputElementWithLabelFromDivTable() {
478 return @[
479 @("<DIV>* First name:<BR>"
480 "<SPAN>"
481 "<INPUT type='text' name='namedivtable' value='John'>"
482 "</SPAN>"
483 "</DIV>"),
484 [NSDictionary dictionaryWithObjectsAndKeys:
485 @"'* First name:'", @"label",
486 @"'namedivtable'", @"name",
487 @"'text'", @"form_control_type",
488 @"undefined", @"autocomplete_attribute",
489 GetDefaultMaxLengthString(), @"max_length",
490 @"true", @"should_autocomplete",
491 @"false", @"is_checkable",
492 @"'John'", @"value",
493 @"'John'", @"value_option_text",
494 @"undefined", @"option_values",
495 @"undefined", @"option_contents",
496 nil]];
497 }
498
499 NSArray* GetTestFormInputElementWithLabelFromDefinitionList() {
500 return @[
501 @("<DL>"
502 " <DT>"
503 " <SPAN>"
504 " *"
505 " </SPAN>"
506 " <SPAN>"
507 " Favorite Sport"
508 " </SPAN>"
509 " </DT>"
510 " <DD>"
511 " <FONT>"
512 " <INPUT type='favorite sport' name='sport' value='Tennis'/>"
513 " </FONT>"
514 " </DD>"
515 " </DL>"),
516 [NSDictionary dictionaryWithObjectsAndKeys:
517 @"'* Favorite Sport'", @"label",
518 @"'sport'", @"name",
519 @"'text'", @"form_control_type",
520 @"undefined", @"autocomplete_attribute",
521 GetDefaultMaxLengthString(), @"max_length",
522 @"true", @"should_autocomplete",
523 @"false", @"is_checkable",
524 @"'Tennis'", @"value",
525 @"'Tennis'", @"value_option_text",
526 @"undefined", @"option_values",
527 @"undefined", @"option_contents",
528 nil]];
529 }
530
531 NSArray* GetTestInputRadio() {
532 return @[
533 @("<input type='radio' name='boolean' value='true'/> True"
534 "<input type='radio' name='boolean' value='false'/> False"),
535 [NSDictionary dictionaryWithObjectsAndKeys:
536 @"'True'", @"label",
537 @"'boolean'", @"name",
538 @"'radio'", @"form_control_type",
539 @"undefined", @"autocomplete_attribute",
540 @"undefined", @"max_length",
541 @"true", @"should_autocomplete",
542 @"true", @"is_checkable",
543 @"'true'", @"value",
544 @"'true'", @"value_option_text",
545 @"undefined", @"option_values",
546 @"undefined", @"option_contents",
547 nil],
548 [NSDictionary dictionaryWithObjectsAndKeys:
549 @"'False'", @"label",
550 @"'boolean'", @"name",
551 @"'radio'", @"form_control_type",
552 @"undefined", @"autocomplete_attribute",
553 @"undefined", @"max_length",
554 @"true", @"should_autocomplete",
555 @"true", @"is_checkable",
556 @"'false'", @"value",
557 @"'false'", @"value_option_text",
558 @"undefined", @"option_values",
559 @"undefined", @"option_contents",
560 nil]];
561 }
562
563 NSArray* GetTestInputCheckbox() {
564 return @[
565 @("<input type='checkbox' name='vehicle' value='Bike'> Bicycle"
566 "<input type='checkbox' name='vehicle' value='Car'> Automobile"
567 "<input type='checkbox' name='vehicle' value='Rocket'> Missile"),
568 [NSDictionary dictionaryWithObjectsAndKeys:
569 @"'Bicycle'", @"label",
570 @"'vehicle'", @"name",
571 @"'checkbox'", @"form_control_type",
572 @"undefined", @"autocomplete_attribute",
573 @"undefined", @"max_length",
574 @"true", @"should_autocomplete",
575 @"true", @"is_checkable",
576 @"'Bike'", @"value",
577 @"'Bike'", @"value_option_text",
578 @"undefined", @"option_values",
579 @"undefined", @"option_contents",
580 nil],
581 [NSDictionary dictionaryWithObjectsAndKeys:
582 @"'Automobile'", @"label",
583 @"'vehicle'", @"name",
584 @"'checkbox'", @"form_control_type",
585 @"undefined", @"autocomplete_attribute",
586 @"undefined", @"max_length",
587 @"true", @"should_autocomplete",
588 @"true", @"is_checkable",
589 @"'Car'", @"value",
590 @"'Car'", @"value_option_text",
591 @"undefined", @"option_values",
592 @"undefined", @"option_contents",
593 nil],
594 [NSDictionary dictionaryWithObjectsAndKeys:
595 @"'Missile'", @"label",
596 @"'vehicle'", @"name",
597 @"'checkbox'", @"form_control_type",
598 @"undefined", @"autocomplete_attribute",
599 @"undefined", @"max_length",
600 @"true", @"should_autocomplete",
601 @"true", @"is_checkable",
602 @"'Rocket'", @"value",
603 @"'Rocket'", @"value_option_text",
604 @"undefined", @"option_values",
605 @"undefined", @"option_contents",
606 nil]];
607 }
608
609 NSArray* GetTestFormSelectElement() {
610 return @[
611 @(" <label>State:"
612 " <select name='state'>"
613 " <option value='CA'>California</option>"
614 " <option value='TX'>Texas</option>"
615 " </select>"
616 " </label>"),
617 [NSDictionary dictionaryWithObjectsAndKeys:
618 @"'State:'", @"label",
619 @"'state'", @"name",
620 @"'select-one'", @"form_control_type",
621 @"undefined", @"autocomplete_attribute",
622 @"undefined", @"max_length",
623 @"true", @"should_autocomplete",
624 @"undefined", @"is_checkable",
625 @"'CA'", @"value",
626 @"'California'", @"value_option_text",
627 @[@"'CA'", @"'TX'"], @"option_values",
628 @[@"'California'", @"'Texas'"], @"option_contents",
629 nil]];
630 }
631
632 NSArray* GetTestFormSelectElementWithOptgroup() {
633 return @[
634 @(" <label>Course:"
635 " <select name='course'>"
636 " <optgroup label='8.01 Physics I: Classical Mechanics'>"
637 " <option value='8.01.1'>Lecture 01: Powers of Ten"
638 " <option value='8.01.2'>Lecture 02: 1D Kinematics"
639 " <option value='8.01.3'>Lecture 03: Vectors"
640 " <optgroup label='8.02 Electricity and Magnestism'>"
641 " <option value='8.02.1'>Lecture 01: What holds world together?"
642 " <option value='8.02.2'>Lecture 02: Electric Field"
643 " <option value='8.02.3'>Lecture 03: Electric Flux"
644 " </select>"
645 " </label>"),
646 [NSDictionary dictionaryWithObjectsAndKeys:
647 @"'Course:'", @"label",
648 @"'course'", @"name",
649 @"'select-one'", @"form_control_type",
650 @"undefined", @"autocomplete_attribute",
651 @"undefined", @"max_length",
652 @"true", @"should_autocomplete",
653 @"undefined", @"is_checkable",
654 @"'8.01.1'", @"value",
655 @"'Lecture 01: Powers of Ten'", @"value_option_text",
656 @[@"'8.01.1'",
657 @"'8.01.2'",
658 @"'8.01.3'",
659 @"'8.02.1'",
660 @"'8.02.2'",
661 @"'8.02.3'"], @"option_values",
662 @[@"'Lecture 01: Powers of Ten'",
663 @"'Lecture 02: 1D Kinematics'",
664 @"'Lecture 03: Vectors'",
665 @"'Lecture 01: What holds world together?'",
666 @"'Lecture 02: Electric Field'",
667 @"'Lecture 03: Electric Flux'"], @"option_contents",
668 nil]];
669 }
670
671 // clang-format on
672
673 // Generates JavaScripts to check a JavaScripts object |results| with the
674 // expected values given in |expected|, which is a dictionary with string
675 // values for all the keys other than @"option_vaues" and @"option_contents";
676 // the values of @"option_vaues" and @"option_contents" are arrays of
677 // strings or undefined. Only attributes in |attributes_to_check| are checked.
678 // A different expected value is chosen in |expected| for different
679 // |extract_mask|.
680 NSString* GenerateElementItemVerifyingJavaScripts(
681 NSString* results,
682 NSUInteger extract_mask,
683 NSDictionary* expected,
684 NSArray* attributes_to_check) {
685 NSMutableArray* verifying_javascripts = [NSMutableArray array];
686
687 for (NSString* attribute in attributes_to_check) {
688 if ([attribute isEqualToString:@"option_values"] ||
689 [attribute isEqualToString:@"option_contents"]) {
690 id expected_value = [expected objectForKey:attribute];
691 if ([expected_value isKindOfClass:[NSString class]]) {
692 [verifying_javascripts
693 addObject:[NSString
694 stringWithFormat:@"%@['%@']===%@", results, attribute,
695 [expected objectForKey:attribute]]];
696 } else {
697 for (NSUInteger i = 0; i < [(NSArray*)expected_value count]; ++i) {
698 [verifying_javascripts
699 addObject:[NSString
700 stringWithFormat:@"%@['%@'][%" PRIuNS "] === %@",
701 results, attribute, i,
702 [expected_value objectAtIndex:i]]];
703 }
704 }
705 } else {
706 NSString* expected_value = [expected objectForKey:attribute];
707 // Option text is used as value for extract_mask 1 << 1
708 if ((extract_mask & 1 << 1) && [attribute isEqualToString:@"value"])
709 expected_value = [expected objectForKey:@"value_option_text"];
710 [verifying_javascripts
711 addObject:[NSString stringWithFormat:@"%@['%@']===%@", results,
712 attribute, expected_value]];
713 }
714 }
715
716 return [verifying_javascripts componentsJoinedByString:@"&&"];
717 }
718
719 // Generates JavaScripts to check a JavaScripts array |results| with the
720 // expected values given in |expected|, which is an array of dictionaries; each
721 // dictionary is the expected values of the corresponding item in |results|.
722 // Only attributes in |attributes_to_check| are checked. A different expected
723 // value is chosen in |expected| for different |extract_mask|.
724 NSString* GenerateTestItemVerifyingJavaScripts(NSString* results,
725 NSUInteger extract_mask,
726 NSArray* expected,
727 NSArray* attributed_to_check) {
728 NSMutableArray* verifying_javascripts = [NSMutableArray array];
729
730 NSUInteger controlCount = 0;
731 for (NSUInteger indexOfTestData = 0; indexOfTestData < [expected count];
732 ++indexOfTestData) {
733 NSArray* expectedData = [expected objectAtIndex:indexOfTestData];
734 for (NSUInteger i = 1; i < [expectedData count]; ++i, ++controlCount) {
735 NSDictionary* expected = [expectedData objectAtIndex:i];
736 NSString* itemVerifyingJavaScripts =
737 GenerateElementItemVerifyingJavaScripts(
738 [NSString stringWithFormat:@"%@['fields'][%" PRIuNS "]", results,
739 controlCount],
740 extract_mask, expected, attributed_to_check);
741 [verifying_javascripts addObject:itemVerifyingJavaScripts];
742 }
743 }
744 return [verifying_javascripts componentsJoinedByString:@"&&"];
745 }
746
747 // Test fixture to test autofill controller.
748 class AutofillControllerJsTest : public web::WebJsTest<ChromeWebTest> {
749 public:
750 AutofillControllerJsTest()
751 : web::WebJsTest<ChromeWebTest>(@[ @"autofill_controller" ]) {}
752
753 protected:
754 // Helper method that EXPECTs |javascript| evaluation on page
755 // |kHTMLForTestingElements| with expectation given by
756 // |elements_with_true_expected|.
757 void TestExecutingBooleanJavaScriptOnElement(
758 NSString* javascript,
759 const ElementByName elements_with_true_expected[],
760 size_t size_elements_with_true_expected);
761
762 // Helper method that EXPECTs
763 // |__gCrWeb.autofill.webFormControlElementToFormField|. This method applies
764 // |__gCrWeb.autofill.webFormControlElementToFormField| on each element in
765 // |test_data| with all possible extract masks and verify the results.
766 void TestWebFormControlElementToFormField(NSArray* test_data,
767 NSString* tag_name);
768
769 // Helper method for testing |javascripts_statement| that evalutate
770 // |attribute_name| of the elements in |test_data| which has tag name
771 // |tag_name|. EXPECTs JavaScript evaluation on
772 // "window.document.getElementsByTagName()"
773 void TestInputElementDataEvaluation(NSString* javascripts_statement,
774 NSString* attribute_name,
775 NSArray* test_data,
776 NSString* tag_name);
777
778 // Helper method that EXPECTs |__gCrWeb.autofill.webFormElementToFormData| on
779 // a form element obtained by |get_form_element_javascripts|. The results
780 // are verified with |verifying_java_scripts|.
781 void TestWebFormElementToFormDataForOneForm(
782 NSString* get_form_element_javascripts,
783 NSUInteger extract_mask,
784 NSString* expected_result,
785 NSString* verifying_javascripts);
786
787 // EXPECTs |__gCrWeb.autofill.webFormElementToFormData| on all the test data.
788 void TestWebFormElementToFormData(NSArray* test_items);
789
790 // EXPECTs |__gCrWeb.autofill.extractNewForms| on |html|.
791 void TestExtractNewForms(NSString* html,
792 BOOL is_origin_window_location,
793 NSArray* expected_items);
794 };
795
796 void AutofillControllerJsTest::TestExecutingBooleanJavaScriptOnElement(
797 NSString* javascript,
798 const ElementByName elements_with_true_expected[],
799 size_t size_elements_with_true_expected) {
800 // Elements in |kHTMLForTestingElements|.
801 const ElementByName elementsByName[] = {
802 {"hl", 0, -1},
803 {"firstname", 0, -1},
804 {"lastname", 0, -1},
805 {"email", 0, -1},
806 {"phone", 0, -1},
807 {"blog", 0, -1},
808 {"expected number of clicks", 0, -1},
809 {"pwd", 0, -1},
810 {"vehicle", 0, -1},
811 {"vehicle", 1, -1},
812 {"vehicle", 2, -1},
813 {"boolean", 0, -1},
814 {"boolean", 1, -1},
815 {"boolean", 2, -1},
816 {"state", 0, -1},
817 {"state", 0, 0},
818 {"state", 0, 1},
819 {"course", 0, -1},
820 {"course", 0, 0},
821 {"course", 0, 1},
822 {"course", 0, 2},
823 {"course", 0, 3},
824 {"course", 0, 4},
825 {"course", 0, 5},
826 {"cars", 0, -1},
827 {"cars", 0, 0},
828 {"cars", 0, 1},
829 {"cars", 0, 2},
830 {"cars", 0, 3},
831 {"submit", 0, -1},
832 };
833
834 LoadHtmlAndInject(kHTMLForTestingElements);
835 ExecuteBooleanJavaScriptOnElementsAndCheck(
836 javascript,
837 GetElementsByNameJavaScripts(elementsByName, arraysize(elementsByName)),
838 GetElementsByNameJavaScripts(elements_with_true_expected,
839 size_elements_with_true_expected));
840 }
841
842 TEST_F(AutofillControllerJsTest, HasTagName) {
843 const ElementByName elements_expecting_true[] = {
844 {"hl", 0, -1},
845 {"firstname", 0, -1},
846 {"lastname", 0, -1},
847 {"email", 0, -1},
848 {"phone", 0, -1},
849 {"blog", 0, -1},
850 {"expected number of clicks", 0, -1},
851 {"pwd", 0, -1},
852 {"vehicle", 0, -1},
853 {"vehicle", 1, -1},
854 {"vehicle", 2, -1},
855 {"boolean", 0, -1},
856 {"boolean", 1, -1},
857 {"boolean", 2, -1},
858 {"submit", 0, -1},
859 };
860
861 TestExecutingBooleanJavaScriptOnElement(
862 @"__gCrWeb.autofill.hasTagName(%@, 'input')", elements_expecting_true,
863 arraysize(elements_expecting_true));
864 }
865
866 TEST_F(AutofillControllerJsTest, CombineAndCollapseWhitespace) {
867 LoadHtmlAndInject(@"<html><body></body></html>");
868
869 EXPECT_NSEQ(@"foobar", ExecuteJavaScriptWithFormat(
870 @"__gCrWeb.autofill.combineAndCollapseWhitespace('"
871 @"foo', 'bar', false)"));
872 EXPECT_NSEQ(@"foo bar", ExecuteJavaScriptWithFormat(
873 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
874 @"'foo', 'bar', true)"));
875 EXPECT_NSEQ(@"foo bar", ExecuteJavaScriptWithFormat(
876 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
877 "'foo ', 'bar', false)"));
878 EXPECT_NSEQ(@"foo bar", ExecuteJavaScriptWithFormat(
879 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
880 "'foo', ' bar', false)"));
881 EXPECT_NSEQ(@"foo bar", ExecuteJavaScriptWithFormat(
882 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
883 "'foo', ' bar', true)"));
884 EXPECT_NSEQ(@"foo bar", ExecuteJavaScriptWithFormat(
885 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
886 "'foo ', ' bar', false)"));
887 EXPECT_NSEQ(@"foobar ", ExecuteJavaScriptWithFormat(
888 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
889 "'foo', 'bar ', false)"));
890 EXPECT_NSEQ(@" foo bar",
891 ExecuteJavaScriptWithFormat(
892 @"__gCrWeb.autofill.combineAndCollapseWhitespace("
893 "' foo', 'bar', true)"));
894 }
895
896 void AutofillControllerJsTest::TestInputElementDataEvaluation(
897 NSString* javascripts_statement,
898 NSString* attribute_name,
899 NSArray* test_data,
900 NSString* tag_name) {
901 NSString* html_fragment = [test_data objectAtIndex:0U];
902 LoadHtmlAndInject(html_fragment);
903
904 for (NSUInteger i = 1; i < [test_data count]; ++i) {
905 NSString* get_element_javascripts = [NSString
906 stringWithFormat:@"window.document.getElementsByTagName('%@')[%" PRIuNS
907 "]",
908 tag_name, i - 1];
909 id actual = ExecuteJavaScriptWithFormat(
910 @"%@(%@) === %@", javascripts_statement, get_element_javascripts,
911 [[test_data objectAtIndex:i] objectForKey:attribute_name]);
912 EXPECT_NSEQ(@YES, actual);
913 }
914 }
915
916 TEST_F(AutofillControllerJsTest, InferLabelFromPrevious) {
917 TestInputElementDataEvaluation(
918 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
919 GetTestFormInputElementWithLabelFromPrevious(), @"input");
920 }
921
922 TEST_F(AutofillControllerJsTest, InferLabelFromPreviousSpan) {
923 TestInputElementDataEvaluation(
924 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
925 GetTestFormInputElementWithLabelFromPreviousSpan(), @"input");
926 }
927
928 TEST_F(AutofillControllerJsTest, InferLabelFromPreviousParagraph) {
929 TestInputElementDataEvaluation(
930 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
931 GetTestFormInputElementWithLabelFromPreviousParagraph(), @"input");
932 }
933
934 TEST_F(AutofillControllerJsTest, InferLabelFromPreviousLabel) {
935 TestInputElementDataEvaluation(
936 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
937 GetTestFormInputElementWithLabelFromPreviousLabel(), @"input");
938 }
939
940 TEST_F(AutofillControllerJsTest, InferLabelFromPreviousLabelOtherIgnored) {
941 TestInputElementDataEvaluation(
942 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
943 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
944 @"input");
945 }
946
947 TEST_F(AutofillControllerJsTest, InferLabelFromPreviousTextBrAndSpan) {
948 TestInputElementDataEvaluation(
949 @"__gCrWeb.autofill.inferLabelFromPrevious", @"label",
950 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(), @"input");
951 }
952
953 TEST_F(AutofillControllerJsTest, InferLabelFromListItem) {
954 TestInputElementDataEvaluation(
955 @"__gCrWeb.autofill.inferLabelFromListItem", @"label",
956 GetTestFormInputElementWithLabelFromListItem(), @"input");
957 }
958
959 TEST_F(AutofillControllerJsTest, InferLabelFromTableColumnTD) {
960 TestInputElementDataEvaluation(
961 @"__gCrWeb.autofill.inferLabelFromTableColumn", @"label",
962 GetTestFormInputElementWithLabelFromTableColumnTD(), @"input");
963 }
964
965 TEST_F(AutofillControllerJsTest, InferLabelFromTableColumnTH) {
966 TestInputElementDataEvaluation(
967 @"__gCrWeb.autofill.inferLabelFromTableColumn", @"label",
968 GetTestFormInputElementWithLabelFromTableColumnTH(), @"input");
969 }
970
971 TEST_F(AutofillControllerJsTest, InferLabelFromTableColumnNested) {
972 TestInputElementDataEvaluation(
973 @"__gCrWeb.autofill.inferLabelFromTableColumn", @"label",
974 GetTestFormInputElementWithLabelFromTableNested(), @"input");
975 }
976
977 TEST_F(AutofillControllerJsTest, InferLabelFromTableRow) {
978 TestInputElementDataEvaluation(
979 @"__gCrWeb.autofill.inferLabelFromTableRow", @"label",
980 GetTestFormInputElementWithLabelFromTableRow(), @"input");
981 }
982
983 TEST_F(AutofillControllerJsTest, InferLabelFromDivTable) {
984 TestInputElementDataEvaluation(
985 @"__gCrWeb.autofill.inferLabelFromDivTable", @"label",
986 GetTestFormInputElementWithLabelFromDivTable(), @"input");
987 }
988
989 TEST_F(AutofillControllerJsTest, InferLabelFromDefinitionList) {
990 TestInputElementDataEvaluation(
991 @"__gCrWeb.autofill.inferLabelFromDefinitionList", @"label",
992 GetTestFormInputElementWithLabelFromDefinitionList(), @"input");
993 }
994
995 TEST_F(AutofillControllerJsTest, InferLabelForElement) {
996 NSArray* testingElements = @[
997 GetTestFormInputElementWithLabelFromPrevious(),
998 GetTestFormInputElementWithLabelFromPreviousSpan(),
999 GetTestFormInputElementWithLabelFromPreviousParagraph(),
1000 GetTestFormInputElementWithLabelFromPreviousLabel(),
1001 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
1002 GetTestFormInputElementWithLabelFromPreviousTextSpanBr(),
1003 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(),
1004 GetTestFormInputElementWithLabelFromListItem(),
1005 GetTestFormInputElementWithLabelFromTableColumnTD(),
1006 GetTestFormInputElementWithLabelFromTableColumnTH(),
1007 GetTestFormInputElementWithLabelFromTableNested(),
1008 GetTestFormInputElementWithLabelFromTableRow(),
1009 GetTestFormInputElementWithLabelFromDivTable(),
1010 GetTestFormInputElementWithLabelFromDefinitionList(), GetTestInputRadio(),
1011 GetTestInputCheckbox()
1012 ];
1013 for (NSArray* testingElement in testingElements) {
1014 TestInputElementDataEvaluation(@"__gCrWeb.autofill.inferLabelForElement",
1015 @"label", testingElement, @"input");
1016 }
1017
1018 TestInputElementDataEvaluation(@"__gCrWeb.autofill.inferLabelForElement",
1019 @"label", GetTestFormSelectElement(),
1020 @"select");
1021
1022 TestInputElementDataEvaluation(
1023 @"__gCrWeb.autofill.inferLabelForElement", @"label",
1024 GetTestFormSelectElementWithOptgroup(), @"select");
1025 }
1026
1027 TEST_F(AutofillControllerJsTest, IsAutofillableElement) {
1028 const ElementByName elements_expecting_true[] = {
1029 {"firstname", 0, -1}, {"lastname", 0, -1},
1030 {"email", 0, -1}, {"phone", 0, -1},
1031 {"blog", 0, -1}, {"expected number of clicks", 0, -1},
1032 {"pwd", 0, -1}, {"vehicle", 0, -1},
1033 {"vehicle", 1, -1}, {"vehicle", 2, -1},
1034 {"boolean", 0, -1}, {"boolean", 1, -1},
1035 {"boolean", 2, -1}, {"state", 0, -1},
1036 {"course", 0, -1},
1037 };
1038
1039 TestExecutingBooleanJavaScriptOnElement(
1040 @"__gCrWeb.autofill.isAutofillableElement(%@)", elements_expecting_true,
1041 arraysize(elements_expecting_true));
1042 }
1043
1044 TEST_F(AutofillControllerJsTest, GetOptionStringsFromElement) {
1045 ElementByName testing_elements[] = {
1046 {"state", 0, -1}, {"course", 0, -1}, {"cars", 0, -1}};
1047
1048 LoadHtmlAndInject(kHTMLForTestingElements);
1049 ExecuteJavaScriptOnElementsAndCheck(
1050 @"var field = {};"
1051 "__gCrWeb.autofill.getOptionStringsFromElement(%@, field);"
1052 "__gCrWeb.stringify(field);",
1053 GetElementsByNameJavaScripts(testing_elements,
1054 arraysize(testing_elements)),
1055 @[
1056 @("{\"option_values\":[\"CA\",\"MA\"],"
1057 "\"option_contents\":[\"CA\",\"MA\"]}"),
1058 @("{\"option_values\":["
1059 "\"8.01.1\",\"8.01.2\",\"8.01.3\","
1060 "\"8.02.1\",\"8.02.2\",\"8.02.3\"],"
1061 "\"option_contents\":["
1062 "\"Lecture 01: Powers of Ten\","
1063 "\"Lecture 02: 1D Kinematics\","
1064 "\"Lecture 03: Vectors\","
1065 "\"Lecture 01: What holds our world together?\","
1066 "\"Lecture 02: Electric Field\","
1067 "\"Lecture 03: Electric Flux\""
1068 "]}"),
1069 @("{\"option_values\":[\"volvo\",\"saab\",\"opel\",\"audi\"],"
1070 "\"option_contents\":[\"Volvo\",\"Saab\",\"Opel\",\"Audi\"]}")
1071 ]);
1072 }
1073
1074 TEST_F(AutofillControllerJsTest, FillFormField) {
1075 LoadHtmlAndInject(kHTMLForTestingElements);
1076
1077 // Test text and select elements of which the value should be changed.
1078 const ElementByName elements[] = {
1079 {"firstname", 0, -1}, {"state", 0, -1},
1080 };
1081 NSArray* values = @[
1082 @"new name",
1083 @"MA",
1084 ];
1085 for (size_t i = 0; i < arraysize(elements); ++i) {
1086 NSString* get_element_javascript = GetElementByNameJavaScript(elements[i]);
1087 NSString* new_value = [values objectAtIndex:i];
1088 EXPECT_NSEQ(new_value,
1089 ExecuteJavaScriptWithFormat(
1090 @"var element=%@;var data={'value':'%@'};"
1091 @"__gCrWeb.autofill.fillFormField(data, element);"
1092 @"element.value",
1093 get_element_javascript, new_value));
1094 }
1095
1096 // Test clickable elements, of which 'checked' should be updated.
1097 ElementByName checkable_elements[] = {
1098 {"vehicle", 0, -1}, {"vehicle", 1, -1}, {"vehicle", 2, -1},
1099 {"boolean", 0, -1}, {"boolean", 1, -1}, {"boolean", 2, -1},
1100 };
1101 const bool final_is_checked_values[] = {
1102 true, false, true, false, true, true,
1103 };
1104 for (size_t i = 0; i < arraysize(checkable_elements); ++i) {
1105 NSString* get_element_javascript =
1106 GetElementByNameJavaScript(checkable_elements[i]);
1107 bool is_checked = final_is_checked_values[i];
1108
1109 EXPECT_NSEQ(
1110 @(is_checked),
1111 ExecuteJavaScriptWithFormat(
1112 @"var element=%@; var value=element.value; "
1113 @"var data={'value':value,'is_checked':%@};"
1114 @"__gCrWeb.autofill.fillFormField(data, element); element.checked",
1115 get_element_javascript, is_checked ? @"true" : @"false"));
1116 }
1117
1118 // Test elements of which the value should not be changed.
1119 ElementByName unchanged_elements[] = {
1120 {"hl", 0, -1}, // hidden element
1121 {"state", 0, 0}, // option element
1122 {"state", 0, 1}, // option element
1123 };
1124 for (size_t i = 0; i < arraysize(unchanged_elements); ++i) {
1125 NSString* get_element_javascript =
1126 GetElementByNameJavaScript(unchanged_elements[i]);
1127 NSString* actual = ExecuteJavaScriptWithFormat(
1128 @"var element=%@;"
1129 @"var oldValue=element.value; var data={'value':'new'};"
1130 @"__gCrWeb.autofill.fillFormField(data, element);"
1131 @"element.value === oldValue",
1132 get_element_javascript);
1133 EXPECT_NSEQ(@YES, actual);
1134 }
1135 }
1136
1137 TEST_F(AutofillControllerJsTest, IsTextInput) {
1138 const ElementByName elements_expecting_true[] = {
1139 {"firstname", 0, -1}, {"lastname", 0, -1},
1140 {"email", 0, -1}, {"phone", 0, -1},
1141 {"blog", 0, -1}, {"expected number of clicks", 0, -1},
1142 {"pwd", 0, -1},
1143 };
1144
1145 TestExecutingBooleanJavaScriptOnElement(@"__gCrWeb.autofill.isTextInput(%@)",
1146 elements_expecting_true,
1147 arraysize(elements_expecting_true));
1148 }
1149
1150 TEST_F(AutofillControllerJsTest, IsSelectElement) {
1151 const ElementByName elements_expecting_true[] = {
1152 {"state", 0, -1}, {"course", 0, -1},
1153 };
1154
1155 TestExecutingBooleanJavaScriptOnElement(
1156 @"__gCrWeb.autofill.isSelectElement(%@)", elements_expecting_true,
1157 arraysize(elements_expecting_true));
1158 }
1159
1160 TEST_F(AutofillControllerJsTest, IsCheckableElement) {
1161 const ElementByName elements_expecting_true[] = {
1162 {"vehicle", 0, -1}, {"vehicle", 1, -1}, {"vehicle", 2, -1},
1163 {"boolean", 0, -1}, {"boolean", 1, -1}, {"boolean", 2, -1},
1164 };
1165
1166 TestExecutingBooleanJavaScriptOnElement(
1167 @"__gCrWeb.autofill.isCheckableElement(%@)", elements_expecting_true,
1168 arraysize(elements_expecting_true));
1169 }
1170
1171 TEST_F(AutofillControllerJsTest, IsAutofillableInputElement) {
1172 const ElementByName elements_expecting_true[] = {
1173 {"firstname", 0, -1}, {"lastname", 0, -1},
1174 {"email", 0, -1}, {"phone", 0, -1},
1175 {"blog", 0, -1}, {"expected number of clicks", 0, -1},
1176 {"pwd", 0, -1}, {"vehicle", 0, -1},
1177 {"vehicle", 1, -1}, {"vehicle", 2, -1},
1178 {"boolean", 0, -1}, {"boolean", 1, -1},
1179 {"boolean", 2, -1},
1180 };
1181
1182 TestExecutingBooleanJavaScriptOnElement(
1183 @"__gCrWeb.autofill.isAutofillableInputElement(%@)",
1184 elements_expecting_true, arraysize(elements_expecting_true));
1185 }
1186
1187 TEST_F(AutofillControllerJsTest, ExtractAutofillableElements) {
1188 LoadHtmlAndInject(kHTMLForTestingElements);
1189 ElementByName expected_elements[] = {
1190 {"firstname", 0, -1}, {"lastname", 0, -1},
1191 {"email", 0, -1}, {"phone", 0, -1},
1192 {"blog", 0, -1}, {"expected number of clicks", 0, -1},
1193 {"pwd", 0, -1}, {"vehicle", 0, -1},
1194 {"vehicle", 1, -1}, {"vehicle", 2, -1},
1195 {"boolean", 0, -1}, {"boolean", 1, -1},
1196 {"boolean", 2, -1}, {"state", 0, -1},
1197 };
1198 NSArray* expected = GetElementsByNameJavaScripts(
1199 expected_elements, arraysize(expected_elements));
1200
1201 NSString* parameter = @"window.document.getElementsByTagName('form')[0]";
1202 for (NSUInteger index = 0; index < [expected count]; index++) {
1203 EXPECT_NSEQ(@YES,
1204 ExecuteJavaScriptWithFormat(
1205 @"var controlElements="
1206 "__gCrWeb.autofill.extractAutofillableElementsInForm(%@);"
1207 "controlElements[%" PRIuNS "] === %@",
1208 parameter, index, expected[index]));
1209 }
1210 }
1211
1212 void AutofillControllerJsTest::TestWebFormControlElementToFormField(
1213 NSArray* test_data,
1214 NSString* tag_name) {
1215 LoadHtmlAndInject([test_data firstObject]);
1216
1217 for (NSUInteger i = 0; i < arraysize(kFormExtractMasks); ++i) {
1218 ExtractMask extract_mask = kFormExtractMasks[i];
1219 NSArray* attributes_to_check =
1220 GetFormFieldAttributeListsToCheck(extract_mask);
1221
1222 for (NSUInteger i = 1; i < [test_data count]; ++i) {
1223 NSString* get_element_to_test =
1224 [NSString stringWithFormat:@"var element = "
1225 "window.document.getElementsByTagName('%"
1226 "@')[%" PRIuNS "]",
1227 tag_name, i - 1];
1228 NSDictionary* expected = [test_data objectAtIndex:i];
1229 // Generates JavaScripts to verify the results. Parameter |results| is
1230 // @"field" as in the evaluation JavaScripts the results are returned in
1231 // |field|.
1232 NSString* verifying_javascripts = GenerateElementItemVerifyingJavaScripts(
1233 @"field", extract_mask, expected, attributes_to_check);
1234 EXPECT_NSEQ(@YES,
1235 ExecuteJavaScriptWithFormat(
1236 @"%@; var field = {};"
1237 "__gCrWeb.autofill.webFormControlElementToFormField("
1238 " element, %u, field);"
1239 "%@",
1240 get_element_to_test, extract_mask, verifying_javascripts))
1241 << base::SysNSStringToUTF8([NSString
1242 stringWithFormat:
1243 @"webFormControlElementToFormField actual results are: "
1244 @"%@, \n"
1245 "expected to be verified by %@",
1246 ExecuteJavaScriptWithFormat(
1247 @"%@; var field = {};"
1248 "__gCrWeb.autofill.webFormControlElementToFormField("
1249 " element, %u, field);__gCrWeb.stringify(field);",
1250 get_element_to_test, extract_mask),
1251 verifying_javascripts]);
1252 }
1253 }
1254 }
1255
1256 TEST_F(AutofillControllerJsTest, WebFormControlElementToFormField) {
1257 NSArray* test_input_elements = @[
1258 GetTestFormInputElementWithLabelFromPrevious(),
1259 GetTestFormInputElementWithLabelFromPreviousSpan(),
1260 GetTestFormInputElementWithLabelFromPreviousParagraph(),
1261 GetTestFormInputElementWithLabelFromPreviousLabel(),
1262 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
1263 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(),
1264 GetTestFormInputElementWithLabelFromPreviousTextSpanBr(),
1265 GetTestFormInputElementWithLabelFromListItem(),
1266 GetTestFormInputElementWithLabelFromTableColumnTD(),
1267 GetTestFormInputElementWithLabelFromTableColumnTH(),
1268 GetTestFormInputElementWithLabelFromTableNested(),
1269 GetTestFormInputElementWithLabelFromTableRow(),
1270 GetTestFormInputElementWithLabelFromDivTable(),
1271 GetTestFormInputElementWithLabelFromDefinitionList(), GetTestInputRadio(),
1272 GetTestInputCheckbox()
1273 ];
1274 for (NSArray* test_element in test_input_elements) {
1275 TestWebFormControlElementToFormField(test_element, @"input");
1276 }
1277
1278 TestWebFormControlElementToFormField(GetTestFormSelectElement(), @"select");
1279 TestWebFormControlElementToFormField(GetTestFormSelectElementWithOptgroup(),
1280 @"select");
1281 }
1282
1283 void AutofillControllerJsTest::TestWebFormElementToFormDataForOneForm(
1284 NSString* get_form_element_javascripts,
1285 NSUInteger extract_mask,
1286 NSString* expected_result,
1287 NSString* verifying_javascripts) {
1288 NSString* actual = ExecuteJavaScriptWithFormat(
1289 @"var form={}; var field={};"
1290 "(__gCrWeb.autofill.webFormElementToFormData("
1291 "window, %@, null, %" PRIuNS ", form, field) === %@) && %@",
1292 get_form_element_javascripts, extract_mask, expected_result,
1293 verifying_javascripts);
1294
1295 EXPECT_NSEQ(@YES, actual) << base::SysNSStringToUTF8([NSString
1296 stringWithFormat:@"Actual:\n%@; expected to be verifyied by\n%@",
1297 ExecuteJavaScriptWithFormat(
1298 @"var form={};"
1299 "__gCrWeb.autofill."
1300 "webFormElementToFormData(window, %@, null,"
1301 "%" PRIuNS ", form, null);"
1302 "__gCrWeb.stringify(form);",
1303 get_form_element_javascripts, extract_mask),
1304 verifying_javascripts]);
1305 }
1306
1307 void AutofillControllerJsTest::TestWebFormElementToFormData(
1308 NSArray* test_items) {
1309 NSString* form_html_fragment =
1310 @"<form name='TestForm' action='http://cnn.com' method='post'>";
1311 for (NSUInteger i = 0; i < [test_items count]; ++i) {
1312 form_html_fragment = [form_html_fragment
1313 stringByAppendingString:[[test_items objectAtIndex:i]
1314 objectAtIndex:0U]];
1315 }
1316 form_html_fragment = [form_html_fragment stringByAppendingString:@"</form>"];
1317 LoadHtmlAndInject(form_html_fragment);
1318
1319 NSString* parameter = @"document.getElementsByTagName('form')[0]";
1320 for (NSUInteger extract_index = 0;
1321 extract_index < arraysize(kFormExtractMasks); ++extract_index) {
1322 NSString* expected_result = @"true";
1323 // We don't verify 'action' here as action is generated as a complete url
1324 // and here data url is used.
1325 NSMutableArray* verifying_javascripts = [NSMutableArray
1326 arrayWithObjects:@"form['name'] === 'TestForm'",
1327 @"form['method'] === 'post'",
1328 @"form['origin'] === window.location.href", nil];
1329 ExtractMask extract_mask = kFormExtractMasks[extract_index];
1330 [verifying_javascripts
1331 addObject:GenerateTestItemVerifyingJavaScripts(
1332 @"form", extract_mask, test_items,
1333 GetFormFieldAttributeListsToCheck(extract_mask))];
1334 TestWebFormElementToFormDataForOneForm(
1335 parameter, extract_mask, expected_result,
1336 [verifying_javascripts componentsJoinedByString:@"&&"]);
1337 }
1338 }
1339
1340 TEST_F(AutofillControllerJsTest, WebFormElementToFormData) {
1341 NSArray* test_elements = @[
1342 GetTestFormInputElementWithLabelFromPrevious(),
1343 GetTestFormInputElementWithLabelFromPreviousSpan(),
1344 GetTestFormInputElementWithLabelFromPreviousParagraph(),
1345 GetTestFormInputElementWithLabelFromPreviousLabel(),
1346 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
1347 GetTestFormInputElementWithLabelFromPreviousTextSpanBr(),
1348 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(),
1349 GetTestFormInputElementWithLabelFromListItem(),
1350 GetTestFormInputElementWithLabelFromTableColumnTD(),
1351 GetTestFormInputElementWithLabelFromTableColumnTH(),
1352 GetTestFormInputElementWithLabelFromTableNested(),
1353 GetTestFormInputElementWithLabelFromTableRow(),
1354 GetTestFormInputElementWithLabelFromDivTable(),
1355 GetTestFormInputElementWithLabelFromDefinitionList(), GetTestInputRadio(),
1356 GetTestInputCheckbox(), GetTestFormSelectElement(),
1357 GetTestFormSelectElementWithOptgroup()
1358 ];
1359 // Test a form that has a signle item in the array.
1360 for (NSArray* testElement in test_elements) {
1361 TestWebFormElementToFormData(@[ testElement ]);
1362 }
1363
1364 // Also test a form that has all the above items.
1365 TestWebFormElementToFormData(test_elements);
1366 }
1367
1368 TEST_F(AutofillControllerJsTest,
1369 DISABLED_WebFormElementToFormDataTooManyFields) {
1370 NSString* html_fragment =
1371 @"<FORM name='Test' action='http://c.com' method='post'>";
1372 // In autofill_controller.js, the maximum number of parsable element is 100
1373 // (__gCrWeb.autofill.MAX_PARSEABE_FIELDS = 100). Here an HTML page with 101
1374 // elements is generated for testing.
1375 for (NSUInteger index = 0; index < 101; ++index) {
1376 html_fragment =
1377 [html_fragment stringByAppendingFormat:@"<INPUT type='text'/>"];
1378 }
1379 html_fragment = [html_fragment stringByAppendingFormat:@"</FORM>"];
1380
1381 LoadHtmlAndInject(html_fragment);
1382 TestWebFormElementToFormDataForOneForm(
1383 @"document.getElementsByTagName('form')[0]", 1, @"false", @"true");
1384 }
1385
1386 TEST_F(AutofillControllerJsTest, WebFormElementToFormEmpty) {
1387 NSString* html_fragment =
1388 @"<FORM name='Test' action='http://c.com' method='post'>";
1389 html_fragment = [html_fragment stringByAppendingFormat:@"</FORM>"];
1390
1391 LoadHtmlAndInject(html_fragment);
1392 TestWebFormElementToFormDataForOneForm(
1393 @"document.getElementsByTagName('form')[0]", 1, @"false", @"true");
1394 }
1395
1396 void AutofillControllerJsTest::TestExtractNewForms(
1397 NSString* html,
1398 BOOL is_origin_window_location,
1399 NSArray* expected_items) {
1400 LoadHtmlAndInject(html);
1401 // Generates verifying javascripts.
1402 NSMutableArray* verifying_javascripts = [NSMutableArray array];
1403 for (NSUInteger i = 0U; i < [expected_items count]; ++i) {
1404 [verifying_javascripts
1405 addObject:[NSString stringWithFormat:@"forms[%" PRIuNS
1406 "]['name'] === 'TestForm'",
1407 i]];
1408 [verifying_javascripts
1409 addObject:[NSString stringWithFormat:@"forms[%" PRIuNS
1410 "]['method'] === 'post'",
1411 i]];
1412 if (is_origin_window_location) {
1413 [verifying_javascripts
1414 addObject:[NSString stringWithFormat:
1415 @"forms[%" PRIuNS
1416 "]['origin'] === window.location.href",
1417 i]];
1418 }
1419 // This is the extract mask used by
1420 // __gCrWeb.autofill.extractNewForms.
1421 NSUInteger extract_mask = EXTRACT_VALUE | EXTRACT_OPTIONS;
1422 [verifying_javascripts
1423 addObject:GenerateTestItemVerifyingJavaScripts(
1424 [NSString stringWithFormat:@"forms[%" PRIuNS "]", i],
1425 extract_mask, [expected_items objectAtIndex:i],
1426 // The relevant attributes for the extract mask
1427 GetFormFieldAttributeListsToCheck(extract_mask))];
1428 }
1429
1430 NSString* actual = ExecuteJavaScriptWithFormat(
1431 @"var forms = __gCrWeb.autofill.extractNewForms(%" PRIuS "); %@",
1432 autofill::kRequiredFieldsForPredictionRoutines,
1433 [verifying_javascripts componentsJoinedByString:@"&&"]);
1434
1435 EXPECT_NSEQ(@YES, actual) << base::SysNSStringToUTF8([NSString
1436 stringWithFormat:@"actually forms = %@, "
1437 "but it is expected to be verified by %@",
1438 ExecuteJavaScriptWithFormat(
1439 @"var forms = __gCrWeb.autofill.extractNewForms("
1440 "%" PRIuS "); __gCrWeb.stringify(forms)",
1441 autofill::kRequiredFieldsForPredictionRoutines),
1442 verifying_javascripts]);
1443 }
1444
1445 TEST_F(AutofillControllerJsTest, ExtractFormsAndFormElements) {
1446 NSArray* testFirstFormItems = @[
1447 GetTestFormInputElementWithLabelFromPrevious(),
1448 GetTestFormInputElementWithLabelFromPreviousSpan(),
1449 GetTestFormInputElementWithLabelFromPreviousParagraph(),
1450 GetTestFormInputElementWithLabelFromPreviousLabel(),
1451 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
1452 GetTestFormInputElementWithLabelFromPreviousTextSpanBr(),
1453 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(),
1454 GetTestFormInputElementWithLabelFromListItem(),
1455 GetTestFormInputElementWithLabelFromTableColumnTD(),
1456 GetTestFormInputElementWithLabelFromTableColumnTH(),
1457 GetTestFormInputElementWithLabelFromTableNested(),
1458 GetTestFormInputElementWithLabelFromTableRow(),
1459 GetTestFormInputElementWithLabelFromDivTable(),
1460 GetTestFormInputElementWithLabelFromDefinitionList(), GetTestInputRadio(),
1461 GetTestInputCheckbox()
1462 ];
1463 NSArray* testSecondFormItems = @[
1464 GetTestFormInputElementWithLabelFromDivTable(), GetTestFormSelectElement(),
1465 GetTestFormSelectElementWithOptgroup()
1466 ];
1467 NSArray* test_forms = @[ testFirstFormItems, testSecondFormItems ];
1468
1469 NSString* html = @"<html><body>";
1470 for (NSArray* testFormItems in test_forms) {
1471 html = [html
1472 stringByAppendingString:
1473 @"<form name='TestForm' action='http://c.com' method='post'>"];
1474 for (NSArray* testItem in testFormItems) {
1475 html = [html stringByAppendingString:[testItem objectAtIndex:0U]];
1476 }
1477 html = [html stringByAppendingFormat:@"</form>"];
1478 }
1479 html = [html stringByAppendingFormat:@"</body></html>"];
1480 TestExtractNewForms(html, true, test_forms);
1481 }
1482
1483 TEST_F(AutofillControllerJsTest, ExtractFormsAndFormElementsNestedFrame) {
1484 NSArray* testFirstFormItems = @[
1485 GetTestFormInputElementWithLabelFromPrevious(),
1486 GetTestFormInputElementWithLabelFromPreviousSpan(),
1487 GetTestFormInputElementWithLabelFromPreviousParagraph(),
1488 GetTestFormInputElementWithLabelFromPreviousLabel(),
1489 GetTestFormInputElementWithLabelFromPreviousLabelOtherIgnored(),
1490 GetTestFormInputElementWithLabelFromPreviousTextSpanBr(),
1491 GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan(),
1492 GetTestFormInputElementWithLabelFromListItem(),
1493 GetTestFormInputElementWithLabelFromTableColumnTD(),
1494 GetTestFormInputElementWithLabelFromTableColumnTH(),
1495 GetTestFormInputElementWithLabelFromTableNested(),
1496 GetTestFormInputElementWithLabelFromTableRow(),
1497 GetTestFormInputElementWithLabelFromDivTable(),
1498 GetTestFormInputElementWithLabelFromDefinitionList(), GetTestInputRadio(),
1499 GetTestInputCheckbox()
1500 ];
1501 NSArray* testSecondFormItems = @[
1502 GetTestFormInputElementWithLabelFromDivTable(), GetTestFormSelectElement(),
1503 GetTestFormSelectElementWithOptgroup()
1504 ];
1505 NSArray* test_forms = @[ testFirstFormItems, testSecondFormItems ];
1506
1507 // Test an html that has nested frames.
1508 NSString* nested_frame_html_fragment = @"<html><body>";
1509 for (NSUInteger i = 0; i < [test_forms count]; ++i) {
1510 NSArray* test_elements = [test_forms objectAtIndex:i];
1511 NSString* form_string =
1512 @"<form name='TestForm' action='http://c.com' method='post'>";
1513 for (NSUInteger j = 0; j < [test_elements count]; ++j) {
1514 form_string =
1515 [form_string stringByAppendingString:[[test_elements objectAtIndex:j]
1516 objectAtIndex:0U]];
1517 }
1518 form_string = [form_string stringByAppendingFormat:@"</form>"];
1519
1520 if (i == 0) {
1521 nested_frame_html_fragment =
1522 [nested_frame_html_fragment stringByAppendingString:form_string];
1523 } else {
1524 nested_frame_html_fragment = [nested_frame_html_fragment
1525 stringByAppendingString:
1526 [NSString stringWithFormat:@"<iframe srcdoc=\"%@\"></iframe>",
1527 form_string]];
1528 }
1529 }
1530 nested_frame_html_fragment =
1531 [nested_frame_html_fragment stringByAppendingString:@"</body></html>"];
1532 TestExtractNewForms(nested_frame_html_fragment, false, test_forms);
1533 }
1534
1535 TEST_F(AutofillControllerJsTest,
1536 ExtractFormsAndFormElementsWithFormAssociatedElementsOutOfForm) {
1537 NSString* html = @"<html><body>"
1538 "<form id='testform'></form>"
1539 "1 <input type='text' name='name1' form='testform'></input>"
1540 "2 <input type='text' name='name2' form='testform'></input>"
1541 "3 <input type='text' name='name3' form='testform'></input>"
1542 "4 <input type='text' name='name4' form='testform'></input>"
1543 "</body></html>";
1544 LoadHtmlAndInject(html);
1545
1546 NSString* verifying_javascript = @"forms[0]['fields'][0]['name']==='name1' &&"
1547 @"forms[0]['fields'][0]['label']==='1' &&"
1548 @"forms[0]['fields'][1]['name']==='name2' &&"
1549 @"forms[0]['fields'][1]['label']==='2' &&"
1550 @"forms[0]['fields'][2]['name']==='name3' &&"
1551 @"forms[0]['fields'][2]['label']==='3' &&"
1552 @"forms[0]['fields'][3]['name']==='name4' &&"
1553 @"forms[0]['fields'][3]['label']==='4'";
1554 EXPECT_NSEQ(@YES, ExecuteJavaScriptWithFormat(
1555 @"var forms = "
1556 "__gCrWeb.autofill.extractNewForms(1); %@",
1557 verifying_javascript));
1558 }
1559
1560 TEST_F(AutofillControllerJsTest, ExtractForms) {
1561 NSString* html = @"<html><body>";
1562 html =
1563 [html stringByAppendingString:
1564 @"<form name='TestForm' action='http://c.com' method='post'>"];
1565 html = [html
1566 stringByAppendingString:[GetTestFormInputElementWithLabelFromPrevious()
1567 objectAtIndex:0U]];
1568 html =
1569 [html stringByAppendingString:[GetTestInputCheckbox() objectAtIndex:0U]];
1570 html = [html stringByAppendingString:
1571 [GetTestFormInputElementWithLabelFromTableColumnTH()
1572 objectAtIndex:0U]];
1573 html = [html stringByAppendingString:
1574 [GetTestFormInputElementWithLabelFromPreviousTextBrAndSpan()
1575 objectAtIndex:0U]];
1576 html = [html
1577 stringByAppendingString:[GetTestFormSelectElement() objectAtIndex:0U]];
1578 html = [html stringByAppendingFormat:@"</form>"];
1579 html = [html stringByAppendingFormat:@"</body></html>"];
1580
1581 LoadHtmlAndInject(html);
1582
1583 NSDictionary* expected = @{
1584 @"name" : @"TestForm",
1585 @"method" : @"post",
1586 @"fields" : @[
1587 @{
1588 @"name" : @"firstname",
1589 @"form_control_type" : @"text",
1590 @"max_length" : GetDefaultMaxLength(),
1591 @"should_autocomplete" : @true,
1592 @"is_checkable" : @false,
1593 @"is_focusable" : @true,
1594 @"value" : @"John",
1595 @"label" : @"* First name:"
1596 },
1597 @{
1598 @"name" : @"vehicle",
1599 @"form_control_type" : @"checkbox",
1600 @"should_autocomplete" : @true,
1601 @"is_checkable" : @true,
1602 @"is_focusable" : @true,
1603 @"value" : @"Bike",
1604 @"label" : @"Bicycle"
1605 },
1606 @{
1607 @"name" : @"vehicle",
1608 @"form_control_type" : @"checkbox",
1609 @"should_autocomplete" : @true,
1610 @"is_checkable" : @true,
1611 @"is_focusable" : @true,
1612 @"value" : @"Car",
1613 @"label" : @"Automobile"
1614 },
1615 @{
1616 @"name" : @"vehicle",
1617 @"form_control_type" : @"checkbox",
1618 @"should_autocomplete" : @true,
1619 @"is_checkable" : @true,
1620 @"is_focusable" : @true,
1621 @"value" : @"Rocket",
1622 @"label" : @"Missile"
1623 },
1624 @{
1625 @"name" : @"nameintableth",
1626 @"form_control_type" : @"text",
1627 @"max_length" : GetDefaultMaxLength(),
1628 @"should_autocomplete" : @true,
1629 @"is_checkable" : @false,
1630 @"is_focusable" : @true,
1631 @"value" : @"John",
1632 @"label" : @"* First name:"
1633 },
1634 @{
1635 @"name" : @"emailtableth",
1636 @"form_control_type" : @"email",
1637 @"max_length" : GetDefaultMaxLength(),
1638 @"should_autocomplete" : @true,
1639 @"is_checkable" : @false,
1640 @"is_focusable" : @true,
1641 @"value" : @"john@example.com",
1642 @"label" : @"Email:"
1643 },
1644 @{
1645 @"name" : @"pwd",
1646 @"form_control_type" : @"password",
1647 @"autocomplete_attribute" : @"off",
1648 @"max_length" : GetDefaultMaxLength(),
1649 @"should_autocomplete" : @false,
1650 @"is_checkable" : @false,
1651 @"is_focusable" : @true,
1652 @"value" : @"",
1653 @"label" : @"* Password:"
1654 },
1655 @{
1656 @"name" : @"state",
1657 @"form_control_type" : @"select-one",
1658 @"is_focusable" : @1,
1659 @"option_values" : @[ @"CA", @"TX" ],
1660 @"option_contents" : @[ @"California", @"Texas" ],
1661 @"should_autocomplete" : @1,
1662 @"value" : @"CA",
1663 @"label" : @"State:"
1664 }
1665 ]
1666 };
1667
1668 NSString* result = ExecuteJavaScriptWithFormat(
1669 @"__gCrWeb.autofill.extractForms(%zu)",
1670 autofill::kRequiredFieldsForPredictionRoutines);
1671 NSDictionary* resultDict = [NSJSONSerialization
1672 JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
1673 options:0
1674 error:nil];
1675 ASSERT_NSNE(nil, resultDict);
1676
1677 NSDictionary* forms = [resultDict[@"forms"] objectAtIndex:0];
1678 [expected enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
1679 EXPECT_NSEQ(forms[key], obj);
1680 }];
1681
1682 // Test with Object.prototype.toJSON override.
1683 result = ExecuteJavaScriptWithFormat(
1684 @"Object.prototype.toJSON=function(){return 'abcde';};"
1685 "__gCrWeb.autofill.extractForms(%zu)",
1686 autofill::kRequiredFieldsForPredictionRoutines);
1687 resultDict = [NSJSONSerialization
1688 JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
1689 options:0
1690 error:nil];
1691 ASSERT_NSNE(nil, resultDict);
1692
1693 forms = [resultDict[@"forms"] objectAtIndex:0];
1694 [expected enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
1695 EXPECT_NSEQ(forms[key], obj);
1696 }];
1697
1698 // Test with Array.prototype.toJSON override.
1699 result = ExecuteJavaScriptWithFormat(
1700 @"Array.prototype.toJSON=function(){return 'abcde';};"
1701 "__gCrWeb.autofill.extractForms(%zu)",
1702 autofill::kRequiredFieldsForPredictionRoutines);
1703 resultDict = [NSJSONSerialization
1704 JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
1705 options:0
1706 error:nil];
1707 ASSERT_NSNE(nil, resultDict);
1708
1709 forms = [resultDict[@"forms"] objectAtIndex:0];
1710 [expected enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL* stop) {
1711 EXPECT_NSEQ(forms[key], obj);
1712 }];
1713 }
1714
1715 TEST_F(AutofillControllerJsTest, FillActiveFormField) {
1716 LoadHtmlAndInject(kHTMLForTestingElements);
1717
1718 NSString* newValue = @"new value";
1719 EXPECT_NSEQ(newValue,
1720 ExecuteJavaScriptWithFormat(
1721 @"var element=document.getElementsByName('lastname')[0];"
1722 "element.focus();"
1723 "var data={\"name\":\"lastname\",\"value\":\"%@\"};"
1724 "__gCrWeb.autofill.fillActiveFormField(data);"
1725 "element.value",
1726 newValue));
1727
1728 EXPECT_NSEQ(@YES, ExecuteJavaScriptWithFormat(
1729 @"var element=document.getElementsByName('gl')[0];"
1730 "element.focus();"
1731 "var oldValue = element.value;"
1732 "var data={\"name\":\"lastname\",\"value\":\"%@\"};"
1733 "__gCrWeb.autofill.fillActiveFormField(data);"
1734 "element.value === oldValue",
1735 newValue))
1736 << "A non-form element's value should changed.";
1737 }
1738
1739 // iOS version of FormAutofillTest.FormCache_ExtractNewForms from
1740 // chrome/renderer/autofill/form_autofill_browsertest.cc
1741 TEST_F(AutofillControllerJsTest, ExtractNewForms) {
1742 NSArray* testCases = @[
1743 // An empty form should not be extracted
1744 @{
1745 @"html" : @"<FORM name='TestForm' action='http://buh.com' method='post'>"
1746 "</FORM>",
1747 @"expected_forms" : @0
1748 },
1749 // A form with less than three fields with no autocomplete type(s) should
1750 // not be extracted.
1751 @{
1752 @"html" : @"<FORM name='TestForm' action='http://buh.com' method='post'>"
1753 " <INPUT type='name' id='firstname'/>"
1754 "</FORM>",
1755 @"expected_forms" : @0
1756 },
1757 // A form with less than three fields with at least one autocomplete type
1758 // should be extracted.
1759 @{
1760 @"html" : @"<FORM name='TestForm' action='http://buh.com' method='post'>"
1761 " <INPUT type='name' id='firstname'"
1762 " autocomplete='given-name'/>"
1763 "</FORM>",
1764 @"expected_forms" : @1
1765 },
1766 // A form with three or more fields should be extracted.
1767 @{
1768 @"html" : @"<FORM name='TestForm' action='http://buh.com' method='post'>"
1769 " <INPUT type='text' id='firstname'/>"
1770 " <INPUT type='text' id='lastname'/>"
1771 " <INPUT type='text' id='email'/>"
1772 " <INPUT type='submit' value='Send'/>"
1773 "</FORM>",
1774 @"expected_forms" : @1
1775 }
1776 ];
1777
1778 for (NSDictionary* testCase in testCases) {
1779 LoadHtmlAndInject(testCase[@"html"]);
1780
1781 NSString* result =
1782 ExecuteJavaScriptWithFormat(@"__gCrWeb.autofill.extractForms(%zu)",
1783 autofill::kRequiredFieldsForUpload);
1784 NSDictionary* resultDict = [NSJSONSerialization
1785 JSONObjectWithData:[result dataUsingEncoding:NSUTF8StringEncoding]
1786 options:0
1787 error:nil];
1788 ASSERT_NSNE(nil, resultDict);
1789 NSUInteger expectedCount =
1790 [testCase[@"expected_forms"] unsignedIntegerValue];
1791 EXPECT_EQ(expectedCount, [resultDict[@"forms"] count])
1792 << base::SysNSStringToUTF8(testCase[@"html"]);
1793 }
1794 }
1795
1796 } // namespace
OLDNEW
« no previous file with comments | « ios/chrome/browser/autofill/autofill_controller.mm ('k') | ios/chrome/browser/autofill/autofill_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698