michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /** michael@0: * reflect.js is a collection of methods to test HTML attribute reflection. michael@0: * Each of attribute is reflected differently, depending on various parameters, michael@0: * see: michael@0: * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes michael@0: * michael@0: * Do not forget to add these line at the beginning of each new reflect* method: michael@0: * ok(attr in element, attr + " should be an IDL attribute of this element"); michael@0: * is(typeof element[attr], , attr + " IDL attribute should be a "); michael@0: */ michael@0: michael@0: /** michael@0: * Checks that a given attribute is correctly reflected as a string. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test michael@0: * - attribute String name of the attribute michael@0: * OR michael@0: * attribute Object object containing two attributes, 'content' and 'idl' michael@0: * - otherValues Array [optional] other values to test in addition of the default ones michael@0: * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString" michael@0: */ michael@0: function reflectString(aParameters) michael@0: { michael@0: var element = aParameters.element; michael@0: var contentAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.content; michael@0: var idlAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.idl; michael@0: var otherValues = aParameters.otherValues !== undefined michael@0: ? aParameters.otherValues : []; michael@0: var treatNullAs = aParameters.extendedAttributes ? michael@0: aParameters.extendedAttributes.TreatNullAs : null; michael@0: michael@0: ok(idlAttr in element, michael@0: idlAttr + " should be an IDL attribute of this element"); michael@0: is(typeof element[idlAttr], "string", michael@0: "'" + idlAttr + "' IDL attribute should be a string"); michael@0: michael@0: // Tests when the attribute isn't set. michael@0: is(element.getAttribute(contentAttr), null, michael@0: "When not set, the content attribute should be null."); michael@0: is(element[idlAttr], "", michael@0: "When not set, the IDL attribute should return the empty string"); michael@0: michael@0: /** michael@0: * TODO: as long as null stringification doesn't follow the WebIDL michael@0: * specifications, don't add it to the loop below and keep it here. michael@0: */ michael@0: element.setAttribute(contentAttr, null); michael@0: is(element.getAttribute(contentAttr), "null", michael@0: "null should have been stringified to 'null' for '" + contentAttr + "'"); michael@0: is(element[idlAttr], "null", michael@0: "null should have been stringified to 'null' for '" + idlAttr + "'"); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = null; michael@0: if (treatNullAs == "EmptyString") { michael@0: is(element.getAttribute(contentAttr), "", michael@0: "null should have been stringified to '' for '" + contentAttr + "'"); michael@0: is(element[idlAttr], "", michael@0: "null should have been stringified to '' for '" + idlAttr + "'"); michael@0: } else { michael@0: is(element.getAttribute(contentAttr), "null", michael@0: "null should have been stringified to 'null' for '" + contentAttr + "'"); michael@0: is(element[idlAttr], "null", michael@0: "null should have been stringified to 'null' for '" + contentAttr + "'"); michael@0: } michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: // Tests various strings. michael@0: var stringsToTest = [ michael@0: // [ test value, expected result ] michael@0: [ "", "" ], michael@0: [ "null", "null" ], michael@0: [ "undefined", "undefined" ], michael@0: [ "foo", "foo" ], michael@0: [ contentAttr, contentAttr ], michael@0: [ idlAttr, idlAttr ], michael@0: // TODO: uncomment this when null stringification will follow the specs. michael@0: // [ null, "null" ], michael@0: [ undefined, "undefined" ], michael@0: [ true, "true" ], michael@0: [ false, "false" ], michael@0: [ 42, "42" ], michael@0: // ES5, verse 8.12.8. michael@0: [ { toString: function() { return "foo" } }, michael@0: "foo" ], michael@0: [ { valueOf: function() { return "foo" } }, michael@0: "[object Object]" ], michael@0: [ { valueOf: function() { return "quux" }, michael@0: toString: undefined }, michael@0: "quux" ], michael@0: [ { valueOf: function() { return "foo" }, michael@0: toString: function() { return "bar" } }, michael@0: "bar" ] michael@0: ]; michael@0: michael@0: otherValues.forEach(function(v) { stringsToTest.push([v, v]) }); michael@0: michael@0: stringsToTest.forEach(function([v, r]) { michael@0: element.setAttribute(contentAttr, v); michael@0: is(element[idlAttr], r, michael@0: "IDL attribute '" + idlAttr + "' should return the value it has been set to."); michael@0: is(element.getAttribute(contentAttr), r, michael@0: "Content attribute '" + contentAttr + "'should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v; michael@0: is(element[idlAttr], r, michael@0: "IDL attribute '" + idlAttr + "' should return the value it has been set to."); michael@0: is(element.getAttribute(contentAttr), r, michael@0: "Content attribute '" + contentAttr + "' should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: }); michael@0: michael@0: // Tests after removeAttribute() is called. Should be equivalent with not set. michael@0: is(element.getAttribute(contentAttr), null, michael@0: "When not set, the content attribute should be null."); michael@0: is(element[idlAttr], "", michael@0: "When not set, the IDL attribute should return the empty string"); michael@0: } michael@0: michael@0: /** michael@0: * Checks that a given attribute name for a given element is correctly reflected michael@0: * as an unsigned int. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test on michael@0: * - attribute String name of the attribute michael@0: * - nonZero Boolean whether the attribute should be non-null michael@0: * - defaultValue Integer [optional] default value, if different from the default one michael@0: */ michael@0: function reflectUnsignedInt(aParameters) michael@0: { michael@0: var element = aParameters.element; michael@0: var attr = aParameters.attribute; michael@0: var nonZero = aParameters.nonZero; michael@0: var defaultValue = aParameters.defaultValue; michael@0: michael@0: if (defaultValue === undefined) { michael@0: if (nonZero) { michael@0: defaultValue = 1; michael@0: } else { michael@0: defaultValue = 0; michael@0: } michael@0: } michael@0: michael@0: ok(attr in element, attr + " should be an IDL attribute of this element"); michael@0: is(typeof element[attr], "number", attr + " IDL attribute should be a number"); michael@0: michael@0: // Check default value. michael@0: is(element[attr], defaultValue, "default value should be " + defaultValue); michael@0: ok(!element.hasAttribute(attr), attr + " shouldn't be present"); michael@0: michael@0: var values = [ 1, 3, 42, 2147483647 ]; michael@0: michael@0: for (var value of values) { michael@0: element[attr] = value; michael@0: is(element[attr], value, "." + attr + " should be equals " + value); michael@0: is(element.getAttribute(attr), String(value), michael@0: "@" + attr + " should be equals " + value); michael@0: michael@0: element.setAttribute(attr, value); michael@0: is(element[attr], value, "." + attr + " should be equals " + value); michael@0: is(element.getAttribute(attr), String(value), michael@0: "@" + attr + " should be equals " + value); michael@0: } michael@0: michael@0: // -3000000000 is equivalent to 1294967296 when using the IDL attribute. michael@0: element[attr] = -3000000000; michael@0: is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296"); michael@0: is(element.getAttribute(attr), "1294967296", michael@0: "@" + attr + " should be equals to 1294967296"); michael@0: michael@0: // When setting the content atribute, it's a string so it will be unvalid. michael@0: element.setAttribute(attr, -3000000000); michael@0: is(element.getAttribute(attr), "-3000000000", michael@0: "@" + attr + " should be equals to " + -3000000000); michael@0: is(element[attr], defaultValue, michael@0: "." + attr + " should be equals to " + defaultValue); michael@0: michael@0: var nonValidValues = [ michael@0: /* invalid value, value in the unsigned int range */ michael@0: [ -2147483648, 2147483648 ], michael@0: [ -1, 4294967295 ], michael@0: [ 3147483647, 3147483647 ], michael@0: ]; michael@0: michael@0: for (var values of nonValidValues) { michael@0: element[attr] = values[0]; michael@0: is(element.getAttribute(attr), String(values[1]), michael@0: "@" + attr + " should be equals to " + values[1]); michael@0: is(element[attr], defaultValue, michael@0: "." + attr + " should be equals to " + defaultValue); michael@0: } michael@0: michael@0: for (var values of nonValidValues) { michael@0: element.setAttribute(attr, values[0]); michael@0: is(element.getAttribute(attr), String(values[0]), michael@0: "@" + attr + " should be equals to " + values[0]); michael@0: is(element[attr], defaultValue, michael@0: "." + attr + " should be equals to " + defaultValue); michael@0: } michael@0: michael@0: // Setting to 0 should throw an error if nonZero is true. michael@0: var caught = false; michael@0: try { michael@0: element[attr] = 0; michael@0: } catch(e) { michael@0: caught = true; michael@0: is(e.name, "IndexSizeError", "exception should be IndexSizeError"); michael@0: is(e.code, DOMException.INDEX_SIZE_ERR, "exception code should be INDEX_SIZE_ERR"); michael@0: } michael@0: michael@0: if (nonZero) { michael@0: ok(caught, "an exception should have been caught"); michael@0: } else { michael@0: ok(!caught, "no exception should have been caught"); michael@0: } michael@0: michael@0: // If 0 is set in @attr, it will be ignored when calling .attr. michael@0: element.setAttribute(attr, "0"); michael@0: is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0"); michael@0: if (nonZero) { michael@0: is(element[attr], defaultValue, michael@0: "." + attr + " should be equals to " + defaultValue); michael@0: } else { michael@0: is(element[attr], 0, "." + attr + " should be equals to 0"); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Checks that a given attribute is correctly reflected as limited to known michael@0: * values enumerated attribute. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test on michael@0: * - attribute String name of the attribute michael@0: * OR michael@0: * attribute Object object containing two attributes, 'content' and 'idl' michael@0: * - validValues Array valid values we support michael@0: * - invalidValues Array invalid values michael@0: * - defaultValue String [optional] default value when no valid value is set michael@0: * OR michael@0: * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing' michael@0: * - unsupportedValues Array [optional] valid values we do not support michael@0: */ michael@0: function reflectLimitedEnumerated(aParameters) michael@0: { michael@0: var element = aParameters.element; michael@0: var contentAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.content; michael@0: var idlAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.idl; michael@0: var validValues = aParameters.validValues; michael@0: var invalidValues = aParameters.invalidValues; michael@0: var defaultValueInvalid = aParameters.defaultValue === undefined michael@0: ? "" : typeof aParameters.defaultValue === "string" michael@0: ? aParameters.defaultValue : aParameters.defaultValue.invalid michael@0: var defaultValueMissing = aParameters.defaultValue === undefined michael@0: ? "" : typeof aParameters.defaultValue === "string" michael@0: ? aParameters.defaultValue : aParameters.defaultValue.missing michael@0: var unsupportedValues = aParameters.unsupportedValues !== undefined michael@0: ? aParameters.unsupportedValues : []; michael@0: michael@0: ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element"); michael@0: is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"); michael@0: michael@0: // Explicitly check the default value. michael@0: element.removeAttribute(contentAttr); michael@0: is(element[idlAttr], defaultValueMissing, michael@0: "When no attribute is set, the value should be the default value."); michael@0: michael@0: // Check valid values. michael@0: validValues.forEach(function (v) { michael@0: element.setAttribute(contentAttr, v); michael@0: is(element[idlAttr], v, michael@0: v + " should be accepted as a valid value for " + idlAttr); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element.setAttribute(contentAttr, v.toUpperCase()); michael@0: is(element[idlAttr], v, michael@0: "Enumerated attributes should be case-insensitive."); michael@0: is(element.getAttribute(contentAttr), v.toUpperCase(), michael@0: "Content attribute should not be lower-cased."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v; michael@0: is(element[idlAttr], v, michael@0: v + " should be accepted as a valid value for " + idlAttr); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v.toUpperCase(); michael@0: is(element[idlAttr], v, michael@0: "Enumerated attributes should be case-insensitive."); michael@0: is(element.getAttribute(contentAttr), v.toUpperCase(), michael@0: "Content attribute should not be lower-cased."); michael@0: element.removeAttribute(contentAttr); michael@0: }); michael@0: michael@0: // Check invalid values. michael@0: invalidValues.forEach(function (v) { michael@0: element.setAttribute(contentAttr, v); michael@0: is(element[idlAttr], defaultValueInvalid, michael@0: "When the content attribute is set to an invalid value, the default value should be returned."); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should not have been changed."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v; michael@0: is(element[idlAttr], defaultValueInvalid, michael@0: "When the value is set to an invalid value, the default value should be returned."); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should not have been changed."); michael@0: element.removeAttribute(contentAttr); michael@0: }); michael@0: michael@0: // Check valid values we currently do not support. michael@0: // Basically, it's like the checks for the valid values but with some todo's. michael@0: unsupportedValues.forEach(function (v) { michael@0: element.setAttribute(contentAttr, v); michael@0: todo_is(element[idlAttr], v, michael@0: v + " should be accepted as a valid value for " + idlAttr); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element.setAttribute(contentAttr, v.toUpperCase()); michael@0: todo_is(element[idlAttr], v, michael@0: "Enumerated attributes should be case-insensitive."); michael@0: is(element.getAttribute(contentAttr), v.toUpperCase(), michael@0: "Content attribute should not be lower-cased."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v; michael@0: todo_is(element[idlAttr], v, michael@0: v + " should be accepted as a valid value for " + idlAttr); michael@0: is(element.getAttribute(contentAttr), v, michael@0: "Content attribute should return the value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v.toUpperCase(); michael@0: todo_is(element[idlAttr], v, michael@0: "Enumerated attributes should be case-insensitive."); michael@0: is(element.getAttribute(contentAttr), v.toUpperCase(), michael@0: "Content attribute should not be lower-cased."); michael@0: element.removeAttribute(contentAttr); michael@0: }); michael@0: } michael@0: michael@0: /** michael@0: * Checks that a given attribute is correctly reflected as a boolean. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test on michael@0: * - attribute String name of the attribute michael@0: * OR michael@0: * attribute Object object containing two attributes, 'content' and 'idl' michael@0: */ michael@0: function reflectBoolean(aParameters) michael@0: { michael@0: var element = aParameters.element; michael@0: var contentAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.content; michael@0: var idlAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.idl; michael@0: michael@0: ok(idlAttr in element, michael@0: idlAttr + " should be an IDL attribute of this element"); michael@0: is(typeof element[idlAttr], "boolean", michael@0: idlAttr + " IDL attribute should be a boolean"); michael@0: michael@0: // Tests when the attribute isn't set. michael@0: is(element.getAttribute(contentAttr), null, michael@0: "When not set, the content attribute should be null."); michael@0: is(element[idlAttr], false, michael@0: "When not set, the IDL attribute should return false"); michael@0: michael@0: /** michael@0: * Test various values. michael@0: * Each value to test is actually an object containing a 'value' property michael@0: * containing the value to actually test, a 'stringified' property containing michael@0: * the stringified value and a 'result' property containing the expected michael@0: * result when the value is set to the IDL attribute. michael@0: */ michael@0: var valuesToTest = [ michael@0: { value: true, stringified: "true", result: true }, michael@0: { value: false, stringified: "false", result: false }, michael@0: { value: "true", stringified: "true", result: true }, michael@0: { value: "false", stringified: "false", result: true }, michael@0: { value: "foo", stringified: "foo", result: true }, michael@0: { value: idlAttr, stringified: idlAttr, result: true }, michael@0: { value: contentAttr, stringified: contentAttr, result: true }, michael@0: { value: "null", stringified: "null", result: true }, michael@0: { value: "undefined", stringified: "undefined", result: true }, michael@0: { value: "", stringified: "", result: false }, michael@0: { value: undefined, stringified: "undefined", result: false }, michael@0: { value: null, stringified: "null", result: false }, michael@0: { value: +0, stringified: "0", result: false }, michael@0: { value: -0, stringified: "0", result: false }, michael@0: { value: NaN, stringified: "NaN", result: false }, michael@0: { value: 42, stringified: "42", result: true }, michael@0: { value: Infinity, stringified: "Infinity", result: true }, michael@0: { value: -Infinity, stringified: "-Infinity", result: true }, michael@0: // ES5, verse 9.2. michael@0: { value: { toString: function() { return "foo" } }, stringified: "foo", michael@0: result: true }, michael@0: { value: { valueOf: function() { return "foo" } }, michael@0: stringified: "[object Object]", result: true }, michael@0: { value: { valueOf: function() { return "quux" }, toString: undefined }, michael@0: stringified: "quux", result: true }, michael@0: { value: { valueOf: function() { return "foo" }, michael@0: toString: function() { return "bar" } }, stringified: "bar", michael@0: result: true }, michael@0: { value: { valueOf: function() { return false } }, michael@0: stringified: "[object Object]", result: true }, michael@0: { value: { foo: false, bar: false }, stringified: "[object Object]", michael@0: result: true }, michael@0: { value: { }, stringified: "[object Object]", result: true }, michael@0: ]; michael@0: michael@0: valuesToTest.forEach(function(v) { michael@0: element.setAttribute(contentAttr, v.value); michael@0: is(element[idlAttr], true, michael@0: "IDL attribute should return always return 'true' if the content attribute has been set"); michael@0: is(element.getAttribute(contentAttr), v.stringified, michael@0: "Content attribute should return the stringified value it has been set to."); michael@0: element.removeAttribute(contentAttr); michael@0: michael@0: element[idlAttr] = v.value; michael@0: is(element[idlAttr], v.result, "IDL attribute should return " + v.result); michael@0: is(element.getAttribute(contentAttr), v.result ? "" : null, michael@0: v.result ? "Content attribute should return the empty string." michael@0: : "Content attribute should return null."); michael@0: is(element.hasAttribute(contentAttr), v.result, michael@0: v.result ? contentAttr + " should not be present" michael@0: : contentAttr + " should be present"); michael@0: element.removeAttribute(contentAttr); michael@0: }); michael@0: michael@0: // Tests after removeAttribute() is called. Should be equivalent with not set. michael@0: is(element.getAttribute(contentAttr), null, michael@0: "When not set, the content attribute should be null."); michael@0: is(element[contentAttr], false, michael@0: "When not set, the IDL attribute should return false"); michael@0: } michael@0: michael@0: /** michael@0: * Checks that a given attribute name for a given element is correctly reflected michael@0: * as an signed integer. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test on michael@0: * - attribute String name of the attribute michael@0: * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise michael@0: * - defaultValue Integer [optional] default value, if one exists michael@0: */ michael@0: function reflectInt(aParameters) michael@0: { michael@0: // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute(). michael@0: function expectedGetAttributeResult(value) { michael@0: return String(value); michael@0: } michael@0: michael@0: function stringToInteger(value, nonNegative, defaultValue) { michael@0: // Parse: Ignore leading whitespace, find [+/-][numbers] michael@0: var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value); michael@0: if (result) { michael@0: var resultInt = parseInt(result[1], 10); michael@0: if ((nonNegative ? 0 : -0x80000000) <= resultInt && resultInt <= 0x7FFFFFFF) { michael@0: // If the value is within allowed value range for signed/unsigned integer, return value michael@0: return resultInt; michael@0: } michael@0: } michael@0: return defaultValue; michael@0: } michael@0: michael@0: // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute. michael@0: function expectedIdlAttributeResult(value) { michael@0: // This returns the result of calling the ES ToInt32 algorithm on value. michael@0: return value << 0; michael@0: } michael@0: michael@0: var element = aParameters.element; michael@0: var attr = aParameters.attribute; michael@0: var nonNegative = aParameters.nonNegative; michael@0: michael@0: var defaultValue = aParameters.defaultValue !== undefined michael@0: ? aParameters.defaultValue michael@0: : nonNegative ? -1 : 0; michael@0: michael@0: ok(attr in element, attr + " should be an IDL attribute of this element"); michael@0: is(typeof element[attr], "number", attr + " IDL attribute should be a number"); michael@0: michael@0: // Check default value. michael@0: is(element[attr], defaultValue, "default value should be " + defaultValue); michael@0: ok(!element.hasAttribute(attr), attr + " shouldn't be present"); michael@0: michael@0: /** michael@0: * Test various values. michael@0: * value: The test value that will be set using both setAttribute(value) and michael@0: * element[attr] = value michael@0: */ michael@0: var valuesToTest = [ michael@0: // Test numeric inputs up to max signed integer michael@0: 0, 1, 55555, 2147483647, +42, michael@0: // Test string inputs up to max signed integer michael@0: "0", "1", "777777", "2147483647", "+42", michael@0: // Test negative numeric inputs up to min signed integer michael@0: -0, -1, -3333, -2147483648, michael@0: // Test negative string inputs up to min signed integer michael@0: "-0", "-1", "-222", "-2147483647", "-2147483648", michael@0: // Test numeric inputs that are outside legal 32 bit signed values michael@0: -2147483649, -3000000000, -4294967296, 2147483649, 4000000000, -4294967297, michael@0: // Test string inputs with extra padding michael@0: " 1111111", " 23456 ", michael@0: // Test non-numeric string inputs michael@0: "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello", michael@0: "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF", michael@0: // Test decimal numbers michael@0: 1.2345, 42.0, 3456789.1, -2.3456, -6789.12345, -2147483649.1234, michael@0: // Test decimal strings michael@0: "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234", michael@0: // Test special values michael@0: undefined, null, NaN, Infinity, -Infinity, michael@0: ]; michael@0: michael@0: valuesToTest.forEach(function(v) { michael@0: var intValue = stringToInteger(v, nonNegative, defaultValue); michael@0: michael@0: element.setAttribute(attr, v); michael@0: michael@0: is(element.getAttribute(attr), expectedGetAttributeResult(v), element.localName + ".setAttribute(" + michael@0: attr + ", " + v + "), " + element.localName + ".getAttribute(" + attr + ") "); michael@0: michael@0: if (intValue == -2147483648 && element[attr] == defaultValue) { michael@0: //TBD: Bug 586761: .setAttribute(attr, -2147483648) --> element[attr] == defaultValue instead of -2147483648 michael@0: todo_is(element[attr], intValue, "Bug 586761: " + element.localName + michael@0: ".setAttribute(value, " + v + "), " + element.localName + "[" + attr + "] "); michael@0: } else { michael@0: is(element[attr], intValue, element.localName + michael@0: ".setAttribute(" + attr + ", " + v + "), " + element.localName + "[" + attr + "] "); michael@0: } michael@0: element.removeAttribute(attr); michael@0: michael@0: if (nonNegative && expectedIdlAttributeResult(v) < 0) { michael@0: try { michael@0: element[attr] = v; michael@0: ok(false, element.localName + "[" + attr + "] = " + v + " should throw IndexSizeError"); michael@0: } catch(e) { michael@0: is(e.name, "IndexSizeError", element.localName + "[" + attr + "] = " + v + michael@0: " should throw IndexSizeError"); michael@0: is(e.code, DOMException.INDEX_SIZE_ERR, element.localName + "[" + attr + "] = " + v + michael@0: " should throw INDEX_SIZE_ERR"); michael@0: } michael@0: } else { michael@0: element[attr] = v; michael@0: if (expectedIdlAttributeResult(v) == -2147483648 && element[attr] == defaultValue) { michael@0: //TBD: Bug 586761: .setAttribute(attr, -2147483648) --> element[attr] == defaultValue instead of -2147483648 michael@0: todo_is(element[attr], expectedIdlAttributeResult(v), "Bug 586761: " + element.localName + "[" + michael@0: attr + "] = " + v + ", " + element.localName + "[" + attr + "] "); michael@0: } else { michael@0: is(element[attr], expectedIdlAttributeResult(v), element.localName + "[" + attr + "] = " + v + michael@0: ", " + element.localName + "[" + attr + "] "); michael@0: is(element.getAttribute(attr), String(expectedIdlAttributeResult(v)), michael@0: element.localName + "[" + attr + "] = " + v + ", " + michael@0: element.localName + ".getAttribute(" + attr + ") "); michael@0: } michael@0: } michael@0: element.removeAttribute(attr); michael@0: }); michael@0: michael@0: // Tests after removeAttribute() is called. Should be equivalent with not set. michael@0: is(element.getAttribute(attr), null, michael@0: "When not set, the content attribute should be null."); michael@0: is(element[attr], defaultValue, michael@0: "When not set, the IDL attribute should return default value."); michael@0: } michael@0: michael@0: /** michael@0: * Checks that a given attribute is correctly reflected as a url. michael@0: * michael@0: * @param aParameters Object object containing the parameters, which are: michael@0: * - element Element node to test michael@0: * - attribute String name of the attribute michael@0: * OR michael@0: * attribute Object object containing two attributes, 'content' and 'idl' michael@0: */ michael@0: function reflectURL(aParameters) michael@0: { michael@0: var element = aParameters.element; michael@0: var contentAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.content; michael@0: var idlAttr = typeof aParameters.attribute === "string" michael@0: ? aParameters.attribute : aParameters.attribute.idl; michael@0: michael@0: element[idlAttr] = ""; michael@0: is(element[idlAttr], document.URL, "Empty string should resolve to document URL"); michael@0: }