Bug 668820 - Improve how we pass arguments to reflects.js methods. r=Ms2ger

This commit is contained in:
Mounir Lamouri 2011-07-06 00:42:44 +02:00
parent 31a8f9a0d9
commit 5f0c5f1d55
7 changed files with 275 additions and 190 deletions

View File

@ -21,11 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=551670
/** Test for Bug 551670 **/
// .type
reflectLimitedEnumerated(document.createElement("button"),
"type",
[ "submit", "reset", "button" ],
[ "this-is-probably-a-wrong-type", "", "tulip" ],
"submit");
reflectLimitedEnumerated({
element: document.createElement("button"),
attribute: "type",
validValues: [ "submit", "reset", "button" ],
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
defaultValue: "submit",
});
</script>
</pre>

View File

@ -23,16 +23,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=551670
// TODO: maybe make those reflections be tested against all input types.
// .accept
reflectString(document.createElement("input"), "accept",
[ "audio/*", "video/*", "image/*", "image/png",
"application/msword", "appplication/pdf" ]);
reflectString({
element: document.createElement("input"),
attribute: "accept",
otherValues: [ "audio/*", "video/*", "image/*", "image/png",
"application/msword", "appplication/pdf" ],
});
// .alt
reflectString(document.createElement("input"), "alt");
reflectString({
element: document.createElement("input"),
attribute: "alt",
});
// .autocomplete
reflectLimitedEnumerated(document.createElement("input"), "autocomplete",
[ "on", "off" ], [ "", "default", "foo", "tulip" ]);
reflectLimitedEnumerated({
element: document.createElement("input"),
attribute: "autocomplete",
validValues: [ "on", "off" ],
invalidValues: [ "", "default", "foo", "tulip" ],
});
// TODO: autofocus (boolean)
// TODO: defaultChecked (boolean)
@ -44,21 +54,32 @@ reflectLimitedEnumerated(document.createElement("input"), "autocomplete",
// TODO: formAction (URL)
// .formEnctype
reflectLimitedEnumerated(document.createElement("input"), "formEnctype",
[ "application/x-www-form-urlencoded",
"multipart/form-data", "text/plain" ],
[ "", "foo", "tulip", "multipart/foo" ],
"application/x-www-form-urlencoded");
reflectLimitedEnumerated({
element: document.createElement("input"),
attribute: "formEnctype",
validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
"text/plain" ],
invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
defaultValue: "application/x-www-form-urlencoded"
});
// .formMethod
reflectLimitedEnumerated(document.createElement("input"), "formMethod",
[ "get", "post" ], [ "", "foo", "tulip" ], "get");
reflectLimitedEnumerated({
element: document.createElement("input"),
attribute: "formMethod",
validValues: [ "get", "post" ],
invalidValues: [ "", "foo", "tulip" ],
defaultValue: "get"
});
// TODO: formNoValidate (boolean)
// .formTarget
reflectString(document.createElement("input"), "formTarget",
[ "_blank", "_self", "_parent", "_top" ]);
reflectString({
element: document.createElement("input"),
attribute: "formTarget",
otherValues: [ "_blank", "_self", "_parent", "_top" ],
});
// TODO: height (non-negative integer)
// TODO: indeterminate (boolean)
@ -69,16 +90,25 @@ reflectString(document.createElement("input"), "formTarget",
// TODO: multiple (boolean)
// .name
reflectString(document.createElement("input"), "name",
[ "isindex", "_charset_" ]);
reflectString({
element: document.createElement("input"),
attribute: "name",
otherValues: [ "isindex", "_charset_" ],
});
// .pattern
reflectString(document.createElement("input"), "pattern",
[ "[0-9][A-Z]{3}" ]);
reflectString({
element: document.createElement("input"),
attribute: "pattern",
otherValues: [ "[0-9][A-Z]{3}" ],
});
// .placeholder
reflectString(document.createElement("input"), "placeholder",
[ "foo\nbar", "foo\rbar", "foo\r\nbar" ]);
reflectString({
element: document.createElement("input"),
attribute: "placeholder",
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
});
// TODO: readOnly (boolean)
// TODO: required (boolean)
@ -87,15 +117,17 @@ reflectString(document.createElement("input"), "placeholder",
// TODO: step (not implemented)
// .type
reflectLimitedEnumerated(document.createElement("input"),
"type",
[ "hidden", "text", "search", "tel", "url", "email",
"password", "checkbox", "radio", "file", "submit",
"image", "reset", "button" ],
[ "this-is-probably-a-wrong-type", "", "tulip" ],
"text",
[ "datetime", "date", "month", "week", "time",
"datetime-local", "number", "range", "color" ]);
reflectLimitedEnumerated({
element: document.createElement("input"),
attribute: "type",
validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
"checkbox", "radio", "file", "submit", "image", "reset",
"button" ],
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
defaultValue: "text",
unsupportedValues: [ "datetime", "date", "month", "week", "time",
"datetime-local", "number", "range", "color" ]
});
// TODO: defaultValue (reflects @value)
// .value doesn't reflect a content attribute.

View File

@ -8,47 +8,51 @@
* http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
*
* Do not forget to add these line at the beginning of each new reflect* method:
* ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
* is(typeof aElement[aAttr], <type>, aAttr + " IDL attribute should be a <type>");
* ok(attr in element, attr + " should be an IDL attribute of this element");
* is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
*/
/**
* Checks that a given attribute is correctly reflected as a string.
*
* @param aElement Element node to test
* @param aAttr String name of the attribute
* @param aOtherValues Array other values to test in addition of the default ones [optional]
* @param aParameters Object object containing the parameters, which are:
* - element Element node to test
* - attribute String name of the attribute
* - otherValues Array [optional] other values to test in addition of the default ones
*/
function reflectString(aElement, aAttr, aOtherValues)
function reflectString(aParameters)
{
var otherValues = aOtherValues !== undefined ? aOtherValues : [];
var element = aParameters.element;
var attr = aParameters.attribute;
var otherValues = aParameters.otherValues !== undefined
? aParameters.otherValues : [];
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
ok(attr in element, attr + " should be an IDL attribute of this element");
is(typeof element[attr], "string", attr + " IDL attribute should be a string");
// Tests when the attribute isn't set.
is(aElement.getAttribute(aAttr), null,
"When not set, the content attribute should be undefined.");
is(aElement[aAttr], "",
is(element.getAttribute(attr), null,
"When not set, the content attribute should be null.");
is(element[attr], "",
"When not set, the IDL attribute should return the empty string");
/**
* TODO: as long as null stringification doesn't fallow the webidl specs,
* don't add it to the loop below and keep it here.
* TODO: as long as null stringification doesn't follow the WebIDL
* specifications, don't add it to the loop below and keep it here.
*/
aElement.setAttribute(aAttr, null);
todo_is(aElement.getAttribute(aAttr), "null",
element.setAttribute(attr, null);
todo_is(element.getAttribute(attr), "null",
"null should have been stringified to 'null'");
todo_is(aElement[aAttr], "null",
todo_is(element[attr], "null",
"null should have been stringified to 'null'");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = null;
todo_is(aElement.getAttribute(aAttr), "null",
element[attr] = null;
todo_is(element.getAttribute(attr), "null",
"null should have been stringified to 'null'");
todo_is(aElement[aAttr], "null",
todo_is(element[attr], "null",
"null should have been stringified to 'null'");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
// Tests various strings.
var stringsToTest = [
@ -57,7 +61,7 @@ function reflectString(aElement, aAttr, aOtherValues)
[ "null", "null" ],
[ "undefined", "undefined" ],
[ "foo", "foo" ],
[ aAttr, aAttr ],
[ attr, attr ],
// TODO: uncomment this when null stringification will follow the specs.
// [ null, "null" ],
[ undefined, "undefined" ],
@ -80,77 +84,86 @@ function reflectString(aElement, aAttr, aOtherValues)
otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
stringsToTest.forEach(function([v, r]) {
aElement.setAttribute(aAttr, v);
is(aElement[aAttr], r,
element.setAttribute(attr, v);
is(element[attr], r,
"IDL attribute should return the value it has been set to.");
is(aElement.getAttribute(aAttr), r,
is(element.getAttribute(attr), r,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v;
is(aElement[aAttr], r,
element[attr] = v;
is(element[attr], r,
"IDL attribute should return the value it has been set to.");
is(aElement.getAttribute(aAttr), r,
is(element.getAttribute(attr), r,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
});
// Tests after removeAttribute() is called. Should be equivalent with not set.
is(aElement.getAttribute(aAttr), null,
"When not set, the content attribute should be undefined.");
is(aElement[aAttr], "",
is(element.getAttribute(attr), null,
"When not set, the content attribute should be null.");
is(element[attr], "",
"When not set, the IDL attribute should return the empty string");
}
/**
* Checks that a given attribute name for a given element is correctly reflected
* as an unsigned int.
*
* @param aParameters Object object containing the parameters, which are:
* - element Element node to test on
* - attribute String name of the attribute
* - nonZero Boolean whether the attribute should be non-null
* - defaultValue Integer [optional] default value, if different from the default one
*/
function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
function reflectUnsignedInt(aParameters)
{
function checkGetter(aElement, aAttr, aValue)
{
is(aElement[aAttr], aValue, "." + aAttr + " should be equals " + aValue);
is(aElement.getAttribute(aAttr), aValue,
"@" + aAttr + " should be equals " + aValue);
}
var element = aParameters.element;
var attr = aParameters.attribute;
var nonZero = aParameters.nonZero;
var defaultValue = aParameters.defaultValue;
if (!aDefault) {
if (aNonNull) {
aDefault = 1;
if (defaultValue === undefined) {
if (nonZero) {
defaultValue = 1;
} else {
aDefault = 0;
defaultValue = 0;
}
}
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "number", aAttr + " IDL attribute should be a string");
ok(attr in element, attr + " should be an IDL attribute of this element");
is(typeof element[attr], "number", attr + " IDL attribute should be a number");
// Check default value.
is(aElement[aAttr], aDefault, "default value should be " + aDefault);
ok(!aElement.hasAttribute(aAttr), aAttr + " shouldn't be present");
is(element[attr], defaultValue, "default value should be " + defaultValue);
ok(!element.hasAttribute(attr), attr + " shouldn't be present");
var values = [ 1, 3, 42, 2147483647 ];
for each (var value in values) {
aElement[aAttr] = value;
checkGetter(aElement, aAttr, value);
}
element[attr] = value;
is(element[attr], value, "." + attr + " should be equals " + value);
is(element.getAttribute(attr), value,
"@" + attr + " should be equals " + value);
for each (var value in values) {
aElement.setAttribute(aAttr, value);
checkGetter(aElement, aAttr, value);
element.setAttribute(attr, value);
is(element[attr], value, "." + attr + " should be equals " + value);
is(element.getAttribute(attr), value,
"@" + attr + " should be equals " + value);
}
// -3000000000 is equivalent to 1294967296 when using the IDL attribute.
aElement[aAttr] = -3000000000;
checkGetter(aElement, aAttr, 1294967296);
element[attr] = -3000000000;
is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
is(element.getAttribute(attr), 1294967296,
"@" + attr + " should be equals to 1294967296");
// When setting the content atribute, it's a string so it will be unvalid.
aElement.setAttribute(aAttr, -3000000000);
is(aElement.getAttribute(aAttr), -3000000000,
"@" + aAttr + " should be equals to " + -3000000000);
is(aElement[aAttr], aDefault,
"." + aAttr + " should be equals to " + aDefault);
element.setAttribute(attr, -3000000000);
is(element.getAttribute(attr), -3000000000,
"@" + attr + " should be equals to " + -3000000000);
is(element[attr], defaultValue,
"." + attr + " should be equals to " + defaultValue);
var nonValidValues = [
/* invalid value, value in the unsigned int range */
@ -160,148 +173,156 @@ function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
];
for each (var values in nonValidValues) {
aElement[aAttr] = values[0];
is(aElement.getAttribute(aAttr), values[1],
"@" + aAttr + " should be equals to " + values[1]);
is(aElement[aAttr], aDefault,
"." + aAttr + " should be equals to " + aDefault);
element[attr] = values[0];
is(element.getAttribute(attr), values[1],
"@" + attr + " should be equals to " + values[1]);
is(element[attr], defaultValue,
"." + attr + " should be equals to " + defaultValue);
}
for each (var values in nonValidValues) {
aElement.setAttribute(aAttr, values[0]);
is(aElement.getAttribute(aAttr), values[0],
"@" + aAttr + " should be equals to " + values[0]);
is(aElement[aAttr], aDefault,
"." + aAttr + " should be equals to " + aDefault);
element.setAttribute(attr, values[0]);
is(element.getAttribute(attr), values[0],
"@" + attr + " should be equals to " + values[0]);
is(element[attr], defaultValue,
"." + attr + " should be equals to " + defaultValue);
}
// Setting to 0 should throw an error if aNonNull is true.
// Setting to 0 should throw an error if nonZero is true.
var caught = false;
try {
aElement[aAttr] = 0;
element[attr] = 0;
} catch(e) {
caught = true;
is(e.code, DOMException.INDEX_SIZE_ERR, "exception should be INDEX_SIZE_ERR");
}
if (aNonNull) {
if (nonZero) {
ok(caught, "an exception should have been caught");
} else {
ok(!caught, "no exception should have been caught");
}
// If 0 is set in @aAttr, it will be ignored when calling .aAttr.
aElement.setAttribute(aAttr, 0);
is(aElement.getAttribute(aAttr), 0, "@" + aAttr + " should be equals to 0");
if (aNonNull) {
is(aElement[aAttr], aDefault,
"." + aAttr + " should be equals to " + aDefault);
// If 0 is set in @attr, it will be ignored when calling .attr.
element.setAttribute(attr, 0);
is(element.getAttribute(attr), 0, "@" + attr + " should be equals to 0");
if (nonZero) {
is(element[attr], defaultValue,
"." + attr + " should be equals to " + defaultValue);
} else {
is(aElement[aAttr], 0, "." + aAttr + " should be equals to 0");
is(element[attr], 0, "." + attr + " should be equals to 0");
}
}
/**
* @param aElement Element node to test on
* @param aAttr String name of the attribute
* @param aValidValues Array valid values we support
* @param aInvalidValues Array invalid values
* @param aDefaultValue String default value when no valid value is set [optional]
* @param aUnsupportedValues Array valid values we do not support [optional]
* Checks that a given attribute is correctly reflected as limited to known
* values enumerated attribute.
*
* @param aParameters Object object containing the parameters, which are:
* - element Element node to test on
* - attribute String name of the attribute
* - validValues Array valid values we support
* - invalidValues Array invalid values
* - defaultValue String [optional] default value when no valid value is set
* - unsupportedValues Array [optional] valid values we do not support
*/
function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
aDefaultValue, aUnsupportedValues)
function reflectLimitedEnumerated(aParameters)
{
var defaultValue = aDefaultValue !== undefined ? aDefaultValue : "";
var unsupportedValues = aUnsupportedValues !== undefined ? aUnsupportedValues
: [];
var element = aParameters.element;
var attr = aParameters.attribute;
var validValues = aParameters.validValues;
var invalidValues = aParameters.invalidValues;
var defaultValue = aParameters.defaultValue !== undefined
? aParameters.defaultValue : "";
var unsupportedValues = aParameters.unsupportedValues !== undefined
? aParameters.unsupportedValues : [];
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
ok(attr in element, attr + " should be an IDL attribute of this element");
is(typeof element[attr], "string", attr + " IDL attribute should be a string");
// Explicitly check the default value.
aElement.removeAttribute(aAttr);
is(aElement[aAttr], defaultValue,
element.removeAttribute(attr);
is(element[attr], defaultValue,
"When no attribute is set, the value should be the default value.");
// Check valid values.
aValidValues.forEach(function (v) {
aElement.setAttribute(aAttr, v);
is(aElement[aAttr], v,
v + " should be accepted as a valid value for " + aAttr);
is(aElement.getAttribute(aAttr), v,
validValues.forEach(function (v) {
element.setAttribute(attr, v);
is(element[attr], v,
v + " should be accepted as a valid value for " + attr);
is(element.getAttribute(attr), v,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement.setAttribute(aAttr, v.toUpperCase());
is(aElement[aAttr], v,
element.setAttribute(attr, v.toUpperCase());
is(element[attr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
is(element.getAttribute(attr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v;
is(aElement[aAttr], v,
v + " should be accepted as a valid value for " + aAttr);
is(aElement.getAttribute(aAttr), v,
element[attr] = v;
is(element[attr], v,
v + " should be accepted as a valid value for " + attr);
is(element.getAttribute(attr), v,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v.toUpperCase();
is(aElement[aAttr], v,
element[attr] = v.toUpperCase();
is(element[attr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
is(element.getAttribute(attr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
});
// Check invalid values.
aInvalidValues.forEach(function (v) {
aElement.setAttribute(aAttr, v);
is(aElement[aAttr], defaultValue,
invalidValues.forEach(function (v) {
element.setAttribute(attr, v);
is(element[attr], defaultValue,
"When the content attribute is set to an invalid value, the default value should be returned.");
is(aElement.getAttribute(aAttr), v,
is(element.getAttribute(attr), v,
"Content attribute should not have been changed.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v;
is(aElement[aAttr], defaultValue,
element[attr] = v;
is(element[attr], defaultValue,
"When the value is set to an invalid value, the default value should be returned.");
is(aElement.getAttribute(aAttr), v,
is(element.getAttribute(attr), v,
"Content attribute should not have been changed.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
});
// Check valid values we currently do not support.
// Basically, it's like the checks for the valid values but with some todo's.
unsupportedValues.forEach(function (v) {
aElement.setAttribute(aAttr, v);
todo_is(aElement[aAttr], v,
v + " should be accepted as a valid value for " + aAttr);
is(aElement.getAttribute(aAttr), v,
element.setAttribute(attr, v);
todo_is(element[attr], v,
v + " should be accepted as a valid value for " + attr);
is(element.getAttribute(attr), v,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement.setAttribute(aAttr, v.toUpperCase());
todo_is(aElement[aAttr], v,
element.setAttribute(attr, v.toUpperCase());
todo_is(element[attr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
is(element.getAttribute(attr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v;
todo_is(aElement[aAttr], v,
v + " should be accepted as a valid value for " + aAttr);
is(aElement.getAttribute(aAttr), v,
element[attr] = v;
todo_is(element[attr], v,
v + " should be accepted as a valid value for " + attr);
is(element.getAttribute(attr), v,
"Content attribute should return the value it has been set to.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
aElement[aAttr] = v.toUpperCase();
todo_is(aElement[aAttr], v,
element[attr] = v.toUpperCase();
todo_is(element[attr], v,
"Enumerated attributes should be case-insensitive.");
is(aElement.getAttribute(aAttr), v.toUpperCase(),
is(element.getAttribute(attr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
aElement.removeAttribute(aAttr);
element.removeAttribute(attr);
});
}

View File

@ -18,7 +18,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=601061
/** Test for Bug 601061 **/
reflectUnsignedInt(document.createElement("input"), "size", true, 20);
reflectUnsignedInt({
element: document.createElement("input"),
attribute: "size",
nonZero: true,
defaultValue: 20,
});
</script>
</pre>

View File

@ -22,8 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=610212
/** Test for Bug 610212 **/
var canvas = document.createElement('canvas');
reflectUnsignedInt(canvas, "width", false, 300);
reflectUnsignedInt(canvas, "height", false, 150);
reflectUnsignedInt({
element: canvas,
attribute: "width",
nonZero: false,
defaultValue: 300,
});
reflectUnsignedInt({
element: canvas,
attribute: "height",
nonZero: false,
defaultValue: 150,
});
</script>
</pre>

View File

@ -18,9 +18,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=630889
/** Test for Bug 630889 **/
var textarea = document.createElement('textarea');
reflectUnsignedInt(textarea, "rows", true, 2);
reflectUnsignedInt(textarea, "cols", true, 20);
var textarea = document.createElement("textarea");
reflectUnsignedInt({
element: textarea,
attribute: "rows",
nonZero: true,
defaultValue: 2,
});
reflectUnsignedInt({
element: textarea,
attribute: "cols",
nonZero: true,
defaultValue: 20,
});
</script>
</pre>

View File

@ -19,12 +19,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=660663
<pre id="test">
<script type="application/javascript">
/** Test for Bug 660663 **/
reflectLimitedEnumerated(document.createElement("div"),
"dir",
["ltr", "rtl"],
["cheesecake", ""],
undefined, // There is no default value.
["auto"]);
reflectLimitedEnumerated({
element: document.createElement("div"),
attribute: "dir",
validValues: ["ltr", "rtl"],
invalidValues: ["cheesecake", ""],
unsupportedValues: ["auto"]
});
</script>
</pre>
</body>