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) {
/**
* Fills a form with provided field values.
*
* @param String selector A DOM CSS3/XPath selector to the target form to fill
* @param Object vals Field values
* @param Boolean submit Submit the form?
* @param String selector A DOM CSS3/XPath selector to the target form to fill
* @param Object vals Field values
* @param Object options The fill settings (optional)
*/
Casper.prototype.fill = function fill(selector, vals, submit) {
Casper.prototype.fillForm = function fillForm(selector, vals, options) {
"use strict";
var submit, selectorFunction;
this.checkStarted();
submit = submit === true ? submit : false;
if (!utils.isObject(vals)) {
throw new CasperError("Form values must be provided as an object");
}
this.emit('fill', selector, vals, submit);
var fillResults = this.evaluate(function _evaluate(selector, values) {
return __utils__.fill(selector, values);
}, selector, vals);
selectorFunction = options && options.selectorFunction;
submit = options.submit === true ? options.submit : false;
this.emit('fill', selector, vals, options);
var fillResults = this.evaluate(function _evaluate(selector, vals, selectorFunction) {
return __utils__.fill(selector, vals, selectorFunction);
}, selector, vals, selectorFunction);
if (!fillResults) {
throw new CasperError("Unable to fill form");
} else if (fillResults.errors.length > 0) {
......@@ -781,7 +783,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
if (!fs.exists(file.path)) {
throw new CasperError('Cannot upload nonexistent file: ' + file.path);
}
var fileFieldSelector = [selector, 'input[name="' + file.name + '"]'].join(' ');
var fileFieldSelector = selectorFunction.call(this, file.name, selector).fullSelector;
self.page.uploadFile(fileFieldSelector, file.path);
});
})(this);
......@@ -808,6 +810,55 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
}
}, selector);
}
}
/**
* Fills a form with provided field values using the Name attribute.
*
* @param String formSelector A DOM CSS3/XPath selector to the target form to fill
* @param Object vals Field values
* @param Boolean submit Submit the form?
*/
Casper.prototype.fillNames = function fillNames(formSelector, vals, submit) {
"use strict";
return this.fillForm(formSelector, vals, {
submit: submit,
selectorFunction: function _nameSelector(elementName, formSelector) {
return {
fullSelector: [formSelector, '[name="' + elementName + '"]'].join(' '),
elts: (this.findAll ? this.findAll('[name="' + elementName + '"]', formSelector) : null)
};
}
});
};
/**
* Fills a form with provided field values using the Name attribute.
*
* @param String formSelector A DOM CSS3/XPath selector to the target form to fill
* @param Object vals Field values
* @param Boolean submit Submit the form?
*/
Casper.prototype.fill = Casper.prototype.fillNames
/**
* Fills a form with provided field values using CSS3 selectors.
*
* @param String formSelector A DOM CSS3/XPath selector to the target form to fill
* @param Object vals Field values
* @param Boolean submit Submit the form?
*/
Casper.prototype.fillSelectors = function fillSelectors(formSelector, vals, submit) {
"use strict";
return this.fillForm(formSelector, vals, {
submit: submit,
selectorFunction: function _css3Selector(inputSelector, formSelector) {
return {
fullSelector: [formSelector, inputSelector].join(' '),
elts: (this.findAll ? this.findAll(inputSelector, formSelector) : null)
};
}
});
};
/**
......
......@@ -194,19 +194,28 @@
};
/**
* Fills a form with provided field values, and optionnaly submits it.
* Fills a form with provided field values, and optionally submits it.
*
* @param HTMLElement|String form A form element, or a CSS3 selector to a form element
* @param Object vals Field values
* @return Object An object containing setting result for each field, including file uploads
* @param HTMLElement|String form A form element, or a CSS3 selector to a form element
* @param Object vals Field values
* @param Function findFunction A function to be used for getting the selector for the element or a list of matching elements (optional)
* @return Object An object containing setting result for each field, including file uploads
*/
this.fill = function fill(form, vals) {
this.fill = function fill(form, vals, findFunction) {
/*jshint maxcomplexity:8*/
var out = {
errors: [],
fields: [],
files: []
};
findFunction = findFunction || function _nameSelector(elementName, formSelector) {
return {
fullSelector: [formSelector, '[name="' + elementName + '"]'].join(' '),
elts: this.findAll('[name="' + elementName + '"]', formSelector)
};
};
if (!(form instanceof HTMLElement) || typeof form === "string") {
this.log("attempting to fetch form element from selector: '" + form + "'", "info");
try {
......@@ -226,7 +235,7 @@
if (!vals.hasOwnProperty(name)) {
continue;
}
var field = this.findAll('[name="' + name + '"]', form);
var field = findFunction.call(this, name, form).elts;
var value = vals[name];
if (!field || field.length === 0) {
out.errors.push('no field named "' + name + '" in form');
......
......@@ -59,6 +59,64 @@ casper.test.begin('fill() tests', 15, function(test) {
});
});
casper.test.begin('fillSelector() tests', 15, function(test) {
var fpath = fs.pathJoin(phantom.casperPath, 'README.md');
casper.start('tests/site/form.html', function() {
this.fillSelectors('form[action="result.html"]', {
"input[name='email']": 'chuck@norris.com',
"input[name='password']": 'chuck',
"textarea[name='content']": 'Am watching thou',
"input[name='check']": true,
"input[name='choice']": 'no',
"select[name='topic']": 'bar',
"input[name='file']": fpath,
"input[name='checklist[]']": ['1', '3']
}
);
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="email"]').value;
}, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field');
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="password"]').value;
}, 'chuck', 'Casper.fill() can fill an input[type=password] form field');
test.assertEvalEquals(function() {
return __utils__.findOne('textarea[name="content"]').value;
}, 'Am watching thou', 'Casper.fill() can fill a textarea form field');
test.assertEvalEquals(function() {
return __utils__.findOne('select[name="topic"]').value;
}, 'bar', 'Casper.fill() can pick a value from a select form field');
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="check"]').checked;
}, true, 'Casper.fill() can check a form checkbox');
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="choice"][value="no"]').checked;
}, true, 'Casper.fill() can check a form radio button 1/2');
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="choice"][value="yes"]').checked;
}, false, 'Casper.fill() can check a form radio button 2/2');
test.assertEvalEquals(function() {
return __utils__.findOne('input[name="file"]').files.length === 1;
}, true, 'Casper.fill() can select a file to upload');
test.assertEvalEquals(function() {
return (__utils__.findOne('input[name="checklist[]"][value="1"]').checked &&
!__utils__.findOne('input[name="checklist[]"][value="2"]').checked &&
__utils__.findOne('input[name="checklist[]"][value="3"]').checked);
}, true, 'Casper.fill() can fill a list of checkboxes');
});
casper.thenClick('input[type="submit"]', function() {
test.assertUrlMatch(/email=chuck@norris.com/, 'Casper.fill() input[type=email] field was submitted');
test.assertUrlMatch(/password=chuck/, 'Casper.fill() input[type=password] field was submitted');
test.assertUrlMatch(/content=Am\+watching\+thou/, 'Casper.fill() textarea field was submitted');
test.assertUrlMatch(/check=on/, 'Casper.fill() input[type=checkbox] field was submitted');
test.assertUrlMatch(/choice=no/, 'Casper.fill() input[type=radio] field was submitted');
test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
});
casper.run(function() {
test.done();
});
});
casper.test.begin('nonexistent fields', 1, function(test) {
casper.start('tests/site/form.html', function() {
test.assertRaises(this.fill, ['form[action="result.html"]', {
......