Commit e042ce6d e042ce6daa14836fab09fbe5356c87b28dfec377 by Nicolas Perriault

Merge remote-tracking branch 'MattCBowman/307-fillNames-fillSelectors' into pr-307

2 parents 8d6b2abc 2a910f06
...@@ -746,21 +746,23 @@ Casper.prototype.fetchText = function fetchText(selector) { ...@@ -746,21 +746,23 @@ Casper.prototype.fetchText = function fetchText(selector) {
746 /** 746 /**
747 * Fills a form with provided field values. 747 * Fills a form with provided field values.
748 * 748 *
749 * @param String selector A DOM CSS3/XPath selector to the target form to fill 749 * @param String selector A DOM CSS3/XPath selector to the target form to fill
750 * @param Object vals Field values 750 * @param Object vals Field values
751 * @param Boolean submit Submit the form? 751 * @param Object options The fill settings (optional)
752 */ 752 */
753 Casper.prototype.fill = function fill(selector, vals, submit) { 753 Casper.prototype.fillForm = function fillForm(selector, vals, options) {
754 "use strict"; 754 "use strict";
755 var submit, selectorFunction;
755 this.checkStarted(); 756 this.checkStarted();
756 submit = submit === true ? submit : false; 757
757 if (!utils.isObject(vals)) { 758 selectorFunction = options && options.selectorFunction;
758 throw new CasperError("Form values must be provided as an object"); 759 submit = options.submit === true ? options.submit : false;
759 } 760
760 this.emit('fill', selector, vals, submit); 761 this.emit('fill', selector, vals, options);
761 var fillResults = this.evaluate(function _evaluate(selector, values) { 762
762 return __utils__.fill(selector, values); 763 var fillResults = this.evaluate(function _evaluate(selector, vals, selectorFunction) {
763 }, selector, vals); 764 return __utils__.fill(selector, vals, selectorFunction);
765 }, selector, vals, selectorFunction);
764 if (!fillResults) { 766 if (!fillResults) {
765 throw new CasperError("Unable to fill form"); 767 throw new CasperError("Unable to fill form");
766 } else if (fillResults.errors.length > 0) { 768 } else if (fillResults.errors.length > 0) {
...@@ -781,7 +783,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) { ...@@ -781,7 +783,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
781 if (!fs.exists(file.path)) { 783 if (!fs.exists(file.path)) {
782 throw new CasperError('Cannot upload nonexistent file: ' + file.path); 784 throw new CasperError('Cannot upload nonexistent file: ' + file.path);
783 } 785 }
784 var fileFieldSelector = [selector, 'input[name="' + file.name + '"]'].join(' '); 786 var fileFieldSelector = selectorFunction.call(this, file.name, selector).fullSelector;
785 self.page.uploadFile(fileFieldSelector, file.path); 787 self.page.uploadFile(fileFieldSelector, file.path);
786 }); 788 });
787 })(this); 789 })(this);
...@@ -808,6 +810,55 @@ Casper.prototype.fill = function fill(selector, vals, submit) { ...@@ -808,6 +810,55 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
808 } 810 }
809 }, selector); 811 }, selector);
810 } 812 }
813 }
814
815 /**
816 * Fills a form with provided field values using the Name attribute.
817 *
818 * @param String formSelector A DOM CSS3/XPath selector to the target form to fill
819 * @param Object vals Field values
820 * @param Boolean submit Submit the form?
821 */
822 Casper.prototype.fillNames = function fillNames(formSelector, vals, submit) {
823 "use strict";
824 return this.fillForm(formSelector, vals, {
825 submit: submit,
826 selectorFunction: function _nameSelector(elementName, formSelector) {
827 return {
828 fullSelector: [formSelector, '[name="' + elementName + '"]'].join(' '),
829 elts: (this.findAll ? this.findAll('[name="' + elementName + '"]', formSelector) : null)
830 };
831 }
832 });
833 };
834
835 /**
836 * Fills a form with provided field values using the Name attribute.
837 *
838 * @param String formSelector A DOM CSS3/XPath selector to the target form to fill
839 * @param Object vals Field values
840 * @param Boolean submit Submit the form?
841 */
842 Casper.prototype.fill = Casper.prototype.fillNames
843
844 /**
845 * Fills a form with provided field values using CSS3 selectors.
846 *
847 * @param String formSelector A DOM CSS3/XPath selector to the target form to fill
848 * @param Object vals Field values
849 * @param Boolean submit Submit the form?
850 */
851 Casper.prototype.fillSelectors = function fillSelectors(formSelector, vals, submit) {
852 "use strict";
853 return this.fillForm(formSelector, vals, {
854 submit: submit,
855 selectorFunction: function _css3Selector(inputSelector, formSelector) {
856 return {
857 fullSelector: [formSelector, inputSelector].join(' '),
858 elts: (this.findAll ? this.findAll(inputSelector, formSelector) : null)
859 };
860 }
861 });
811 }; 862 };
812 863
813 /** 864 /**
......
...@@ -194,19 +194,28 @@ ...@@ -194,19 +194,28 @@
194 }; 194 };
195 195
196 /** 196 /**
197 * Fills a form with provided field values, and optionnaly submits it. 197 * Fills a form with provided field values, and optionally submits it.
198 * 198 *
199 * @param HTMLElement|String form A form element, or a CSS3 selector to a form element 199 * @param HTMLElement|String form A form element, or a CSS3 selector to a form element
200 * @param Object vals Field values 200 * @param Object vals Field values
201 * @return Object An object containing setting result for each field, including file uploads 201 * @param Function findFunction A function to be used for getting the selector for the element or a list of matching elements (optional)
202 * @return Object An object containing setting result for each field, including file uploads
202 */ 203 */
203 this.fill = function fill(form, vals) { 204 this.fill = function fill(form, vals, findFunction) {
204 /*jshint maxcomplexity:8*/ 205 /*jshint maxcomplexity:8*/
205 var out = { 206 var out = {
206 errors: [], 207 errors: [],
207 fields: [], 208 fields: [],
208 files: [] 209 files: []
209 }; 210 };
211
212 findFunction = findFunction || function _nameSelector(elementName, formSelector) {
213 return {
214 fullSelector: [formSelector, '[name="' + elementName + '"]'].join(' '),
215 elts: this.findAll('[name="' + elementName + '"]', formSelector)
216 };
217 };
218
210 if (!(form instanceof HTMLElement) || typeof form === "string") { 219 if (!(form instanceof HTMLElement) || typeof form === "string") {
211 this.log("attempting to fetch form element from selector: '" + form + "'", "info"); 220 this.log("attempting to fetch form element from selector: '" + form + "'", "info");
212 try { 221 try {
...@@ -226,7 +235,7 @@ ...@@ -226,7 +235,7 @@
226 if (!vals.hasOwnProperty(name)) { 235 if (!vals.hasOwnProperty(name)) {
227 continue; 236 continue;
228 } 237 }
229 var field = this.findAll('[name="' + name + '"]', form); 238 var field = findFunction.call(this, name, form).elts;
230 var value = vals[name]; 239 var value = vals[name];
231 if (!field || field.length === 0) { 240 if (!field || field.length === 0) {
232 out.errors.push('no field named "' + name + '" in form'); 241 out.errors.push('no field named "' + name + '" in form');
......
...@@ -59,6 +59,64 @@ casper.test.begin('fill() tests', 15, function(test) { ...@@ -59,6 +59,64 @@ casper.test.begin('fill() tests', 15, function(test) {
59 }); 59 });
60 }); 60 });
61 61
62 casper.test.begin('fillSelector() tests', 15, function(test) {
63 var fpath = fs.pathJoin(phantom.casperPath, 'README.md');
64
65 casper.start('tests/site/form.html', function() {
66 this.fillSelectors('form[action="result.html"]', {
67 "input[name='email']": 'chuck@norris.com',
68 "input[name='password']": 'chuck',
69 "textarea[name='content']": 'Am watching thou',
70 "input[name='check']": true,
71 "input[name='choice']": 'no',
72 "select[name='topic']": 'bar',
73 "input[name='file']": fpath,
74 "input[name='checklist[]']": ['1', '3']
75 }
76 );
77 test.assertEvalEquals(function() {
78 return __utils__.findOne('input[name="email"]').value;
79 }, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field');
80 test.assertEvalEquals(function() {
81 return __utils__.findOne('input[name="password"]').value;
82 }, 'chuck', 'Casper.fill() can fill an input[type=password] form field');
83 test.assertEvalEquals(function() {
84 return __utils__.findOne('textarea[name="content"]').value;
85 }, 'Am watching thou', 'Casper.fill() can fill a textarea form field');
86 test.assertEvalEquals(function() {
87 return __utils__.findOne('select[name="topic"]').value;
88 }, 'bar', 'Casper.fill() can pick a value from a select form field');
89 test.assertEvalEquals(function() {
90 return __utils__.findOne('input[name="check"]').checked;
91 }, true, 'Casper.fill() can check a form checkbox');
92 test.assertEvalEquals(function() {
93 return __utils__.findOne('input[name="choice"][value="no"]').checked;
94 }, true, 'Casper.fill() can check a form radio button 1/2');
95 test.assertEvalEquals(function() {
96 return __utils__.findOne('input[name="choice"][value="yes"]').checked;
97 }, false, 'Casper.fill() can check a form radio button 2/2');
98 test.assertEvalEquals(function() {
99 return __utils__.findOne('input[name="file"]').files.length === 1;
100 }, true, 'Casper.fill() can select a file to upload');
101 test.assertEvalEquals(function() {
102 return (__utils__.findOne('input[name="checklist[]"][value="1"]').checked &&
103 !__utils__.findOne('input[name="checklist[]"][value="2"]').checked &&
104 __utils__.findOne('input[name="checklist[]"][value="3"]').checked);
105 }, true, 'Casper.fill() can fill a list of checkboxes');
106 });
107 casper.thenClick('input[type="submit"]', function() {
108 test.assertUrlMatch(/email=chuck@norris.com/, 'Casper.fill() input[type=email] field was submitted');
109 test.assertUrlMatch(/password=chuck/, 'Casper.fill() input[type=password] field was submitted');
110 test.assertUrlMatch(/content=Am\+watching\+thou/, 'Casper.fill() textarea field was submitted');
111 test.assertUrlMatch(/check=on/, 'Casper.fill() input[type=checkbox] field was submitted');
112 test.assertUrlMatch(/choice=no/, 'Casper.fill() input[type=radio] field was submitted');
113 test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
114 });
115 casper.run(function() {
116 test.done();
117 });
118 });
119
62 casper.test.begin('nonexistent fields', 1, function(test) { 120 casper.test.begin('nonexistent fields', 1, function(test) {
63 casper.start('tests/site/form.html', function() { 121 casper.start('tests/site/form.html', function() {
64 test.assertRaises(this.fill, ['form[action="result.html"]', { 122 test.assertRaises(this.fill, ['form[action="result.html"]', {
......