Merge remote-tracking branch 'MattCBowman/307-fillNames-fillSelectors' into pr-307
Showing
3 changed files
with
132 additions
and
14 deletions
... | @@ -748,19 +748,21 @@ Casper.prototype.fetchText = function fetchText(selector) { | ... | @@ -748,19 +748,21 @@ Casper.prototype.fetchText = function fetchText(selector) { |
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 | * @param Function findFunction A function to be used for getting the selector for the element or a list of matching elements (optional) | ||
201 | * @return Object An object containing setting result for each field, including file uploads | 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"]', { | ... | ... |
-
Please register or sign in to post a comment