/content/html/content/test/reflect.js

https://github.com/JSilver99/mozilla-central-old · JavaScript · 579 lines · 396 code · 60 blank · 123 comment · 33 complexity · 5448a8db3fbf28695abcf923fa259d21 MD5 · raw file

  1. /* Any copyright is dedicated to the Public Domain.
  2. http://creativecommons.org/publicdomain/zero/1.0/ */
  3. /**
  4. * reflect.js is a collection of methods to test HTML attribute reflection.
  5. * Each of attribute is reflected differently, depending on various parameters,
  6. * see:
  7. * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
  8. *
  9. * Do not forget to add these line at the beginning of each new reflect* method:
  10. * ok(attr in element, attr + " should be an IDL attribute of this element");
  11. * is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
  12. */
  13. /**
  14. * Checks that a given attribute is correctly reflected as a string.
  15. *
  16. * @param aParameters Object object containing the parameters, which are:
  17. * - element Element node to test
  18. * - attribute String name of the attribute
  19. * OR
  20. * attribute Object object containing two attributes, 'content' and 'idl'
  21. * - otherValues Array [optional] other values to test in addition of the default ones
  22. */
  23. function reflectString(aParameters)
  24. {
  25. var element = aParameters.element;
  26. var contentAttr = typeof aParameters.attribute === "string"
  27. ? aParameters.attribute : aParameters.attribute.content;
  28. var idlAttr = typeof aParameters.attribute === "string"
  29. ? aParameters.attribute : aParameters.attribute.idl;
  30. var otherValues = aParameters.otherValues !== undefined
  31. ? aParameters.otherValues : [];
  32. ok(idlAttr in element,
  33. idlAttr + " should be an IDL attribute of this element");
  34. is(typeof element[idlAttr], "string",
  35. idlAttr + " IDL attribute should be a string");
  36. // Tests when the attribute isn't set.
  37. is(element.getAttribute(contentAttr), null,
  38. "When not set, the content attribute should be null.");
  39. is(element[idlAttr], "",
  40. "When not set, the IDL attribute should return the empty string");
  41. /**
  42. * TODO: as long as null stringification doesn't follow the WebIDL
  43. * specifications, don't add it to the loop below and keep it here.
  44. */
  45. element.setAttribute(contentAttr, null);
  46. todo_is(element.getAttribute(contentAttr), "null",
  47. "null should have been stringified to 'null'");
  48. todo_is(element[idlAttr], "null",
  49. "null should have been stringified to 'null'");
  50. element.removeAttribute(contentAttr);
  51. element[idlAttr] = null;
  52. // TODO: remove this ugly hack when null stringification will work as expected.
  53. if (element.localName == "textarea" && idlAttr == "wrap") {
  54. is(element.getAttribute(contentAttr), "null",
  55. "null should have been stringified to 'null'");
  56. is(element[idlAttr], "null", "null should have been stringified to 'null'");
  57. element.removeAttribute(contentAttr);
  58. } else {
  59. todo_is(element.getAttribute(contentAttr), "null",
  60. "null should have been stringified to 'null'");
  61. todo_is(element[idlAttr], "null",
  62. "null should have been stringified to 'null'");
  63. element.removeAttribute(contentAttr);
  64. }
  65. // Tests various strings.
  66. var stringsToTest = [
  67. // [ test value, expected result ]
  68. [ "", "" ],
  69. [ "null", "null" ],
  70. [ "undefined", "undefined" ],
  71. [ "foo", "foo" ],
  72. [ contentAttr, contentAttr ],
  73. [ idlAttr, idlAttr ],
  74. // TODO: uncomment this when null stringification will follow the specs.
  75. // [ null, "null" ],
  76. [ undefined, "undefined" ],
  77. [ true, "true" ],
  78. [ false, "false" ],
  79. [ 42, "42" ],
  80. // ES5, verse 8.12.8.
  81. [ { toString: function() { return "foo" } },
  82. "foo" ],
  83. [ { valueOf: function() { return "foo" } },
  84. "[object Object]" ],
  85. [ { valueOf: function() { return "quux" },
  86. toString: undefined },
  87. "quux" ],
  88. [ { valueOf: function() { return "foo" },
  89. toString: function() { return "bar" } },
  90. "bar" ]
  91. ];
  92. otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
  93. stringsToTest.forEach(function([v, r]) {
  94. element.setAttribute(contentAttr, v);
  95. is(element[idlAttr], r,
  96. "IDL attribute should return the value it has been set to.");
  97. is(element.getAttribute(contentAttr), r,
  98. "Content attribute should return the value it has been set to.");
  99. element.removeAttribute(contentAttr);
  100. element[idlAttr] = v;
  101. is(element[idlAttr], r,
  102. "IDL attribute should return the value it has been set to.");
  103. is(element.getAttribute(contentAttr), r,
  104. "Content attribute should return the value it has been set to.");
  105. element.removeAttribute(contentAttr);
  106. });
  107. // Tests after removeAttribute() is called. Should be equivalent with not set.
  108. is(element.getAttribute(contentAttr), null,
  109. "When not set, the content attribute should be null.");
  110. is(element[idlAttr], "",
  111. "When not set, the IDL attribute should return the empty string");
  112. }
  113. /**
  114. * Checks that a given attribute name for a given element is correctly reflected
  115. * as an unsigned int.
  116. *
  117. * @param aParameters Object object containing the parameters, which are:
  118. * - element Element node to test on
  119. * - attribute String name of the attribute
  120. * - nonZero Boolean whether the attribute should be non-null
  121. * - defaultValue Integer [optional] default value, if different from the default one
  122. */
  123. function reflectUnsignedInt(aParameters)
  124. {
  125. var element = aParameters.element;
  126. var attr = aParameters.attribute;
  127. var nonZero = aParameters.nonZero;
  128. var defaultValue = aParameters.defaultValue;
  129. if (defaultValue === undefined) {
  130. if (nonZero) {
  131. defaultValue = 1;
  132. } else {
  133. defaultValue = 0;
  134. }
  135. }
  136. ok(attr in element, attr + " should be an IDL attribute of this element");
  137. is(typeof element[attr], "number", attr + " IDL attribute should be a number");
  138. // Check default value.
  139. is(element[attr], defaultValue, "default value should be " + defaultValue);
  140. ok(!element.hasAttribute(attr), attr + " shouldn't be present");
  141. var values = [ 1, 3, 42, 2147483647 ];
  142. for each (var value in values) {
  143. element[attr] = value;
  144. is(element[attr], value, "." + attr + " should be equals " + value);
  145. is(element.getAttribute(attr), value,
  146. "@" + attr + " should be equals " + value);
  147. element.setAttribute(attr, value);
  148. is(element[attr], value, "." + attr + " should be equals " + value);
  149. is(element.getAttribute(attr), value,
  150. "@" + attr + " should be equals " + value);
  151. }
  152. // -3000000000 is equivalent to 1294967296 when using the IDL attribute.
  153. element[attr] = -3000000000;
  154. is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
  155. is(element.getAttribute(attr), 1294967296,
  156. "@" + attr + " should be equals to 1294967296");
  157. // When setting the content atribute, it's a string so it will be unvalid.
  158. element.setAttribute(attr, -3000000000);
  159. is(element.getAttribute(attr), -3000000000,
  160. "@" + attr + " should be equals to " + -3000000000);
  161. is(element[attr], defaultValue,
  162. "." + attr + " should be equals to " + defaultValue);
  163. var nonValidValues = [
  164. /* invalid value, value in the unsigned int range */
  165. [ -2147483648, 2147483648 ],
  166. [ -1, 4294967295 ],
  167. [ 3147483647, 3147483647 ],
  168. ];
  169. for each (var values in nonValidValues) {
  170. element[attr] = values[0];
  171. is(element.getAttribute(attr), values[1],
  172. "@" + attr + " should be equals to " + values[1]);
  173. is(element[attr], defaultValue,
  174. "." + attr + " should be equals to " + defaultValue);
  175. }
  176. for each (var values in nonValidValues) {
  177. element.setAttribute(attr, values[0]);
  178. is(element.getAttribute(attr), values[0],
  179. "@" + attr + " should be equals to " + values[0]);
  180. is(element[attr], defaultValue,
  181. "." + attr + " should be equals to " + defaultValue);
  182. }
  183. // Setting to 0 should throw an error if nonZero is true.
  184. var caught = false;
  185. try {
  186. element[attr] = 0;
  187. } catch(e) {
  188. caught = true;
  189. is(e.code, DOMException.INDEX_SIZE_ERR, "exception should be INDEX_SIZE_ERR");
  190. }
  191. if (nonZero) {
  192. ok(caught, "an exception should have been caught");
  193. } else {
  194. ok(!caught, "no exception should have been caught");
  195. }
  196. // If 0 is set in @attr, it will be ignored when calling .attr.
  197. element.setAttribute(attr, 0);
  198. is(element.getAttribute(attr), 0, "@" + attr + " should be equals to 0");
  199. if (nonZero) {
  200. is(element[attr], defaultValue,
  201. "." + attr + " should be equals to " + defaultValue);
  202. } else {
  203. is(element[attr], 0, "." + attr + " should be equals to 0");
  204. }
  205. }
  206. /**
  207. * Checks that a given attribute is correctly reflected as limited to known
  208. * values enumerated attribute.
  209. *
  210. * @param aParameters Object object containing the parameters, which are:
  211. * - element Element node to test on
  212. * - attribute String name of the attribute
  213. * OR
  214. * attribute Object object containing two attributes, 'content' and 'idl'
  215. * - validValues Array valid values we support
  216. * - invalidValues Array invalid values
  217. * - defaultValue String [optional] default value when no valid value is set
  218. * - unsupportedValues Array [optional] valid values we do not support
  219. */
  220. function reflectLimitedEnumerated(aParameters)
  221. {
  222. var element = aParameters.element;
  223. var contentAttr = typeof aParameters.attribute === "string"
  224. ? aParameters.attribute : aParameters.attribute.content;
  225. var idlAttr = typeof aParameters.attribute === "string"
  226. ? aParameters.attribute : aParameters.attribute.idl;
  227. var validValues = aParameters.validValues;
  228. var invalidValues = aParameters.invalidValues;
  229. var defaultValue = aParameters.defaultValue !== undefined
  230. ? aParameters.defaultValue : "";
  231. var unsupportedValues = aParameters.unsupportedValues !== undefined
  232. ? aParameters.unsupportedValues : [];
  233. ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element");
  234. is(typeof element[idlAttr], "string", idlAttr + " IDL attribute should be a string");
  235. // Explicitly check the default value.
  236. element.removeAttribute(contentAttr);
  237. is(element[idlAttr], defaultValue,
  238. "When no attribute is set, the value should be the default value.");
  239. // Check valid values.
  240. validValues.forEach(function (v) {
  241. element.setAttribute(contentAttr, v);
  242. is(element[idlAttr], v,
  243. v + " should be accepted as a valid value for " + idlAttr);
  244. is(element.getAttribute(contentAttr), v,
  245. "Content attribute should return the value it has been set to.");
  246. element.removeAttribute(contentAttr);
  247. element.setAttribute(contentAttr, v.toUpperCase());
  248. is(element[idlAttr], v,
  249. "Enumerated attributes should be case-insensitive.");
  250. is(element.getAttribute(contentAttr), v.toUpperCase(),
  251. "Content attribute should not be lower-cased.");
  252. element.removeAttribute(contentAttr);
  253. element[idlAttr] = v;
  254. is(element[idlAttr], v,
  255. v + " should be accepted as a valid value for " + idlAttr);
  256. is(element.getAttribute(contentAttr), v,
  257. "Content attribute should return the value it has been set to.");
  258. element.removeAttribute(contentAttr);
  259. element[idlAttr] = v.toUpperCase();
  260. is(element[idlAttr], v,
  261. "Enumerated attributes should be case-insensitive.");
  262. is(element.getAttribute(contentAttr), v.toUpperCase(),
  263. "Content attribute should not be lower-cased.");
  264. element.removeAttribute(contentAttr);
  265. });
  266. // Check invalid values.
  267. invalidValues.forEach(function (v) {
  268. element.setAttribute(contentAttr, v);
  269. is(element[idlAttr], defaultValue,
  270. "When the content attribute is set to an invalid value, the default value should be returned.");
  271. is(element.getAttribute(contentAttr), v,
  272. "Content attribute should not have been changed.");
  273. element.removeAttribute(contentAttr);
  274. element[idlAttr] = v;
  275. is(element[idlAttr], defaultValue,
  276. "When the value is set to an invalid value, the default value should be returned.");
  277. is(element.getAttribute(contentAttr), v,
  278. "Content attribute should not have been changed.");
  279. element.removeAttribute(contentAttr);
  280. });
  281. // Check valid values we currently do not support.
  282. // Basically, it's like the checks for the valid values but with some todo's.
  283. unsupportedValues.forEach(function (v) {
  284. element.setAttribute(contentAttr, v);
  285. todo_is(element[idlAttr], v,
  286. v + " should be accepted as a valid value for " + idlAttr);
  287. is(element.getAttribute(contentAttr), v,
  288. "Content attribute should return the value it has been set to.");
  289. element.removeAttribute(contentAttr);
  290. element.setAttribute(contentAttr, v.toUpperCase());
  291. todo_is(element[idlAttr], v,
  292. "Enumerated attributes should be case-insensitive.");
  293. is(element.getAttribute(contentAttr), v.toUpperCase(),
  294. "Content attribute should not be lower-cased.");
  295. element.removeAttribute(contentAttr);
  296. element[idlAttr] = v;
  297. todo_is(element[idlAttr], v,
  298. v + " should be accepted as a valid value for " + idlAttr);
  299. is(element.getAttribute(contentAttr), v,
  300. "Content attribute should return the value it has been set to.");
  301. element.removeAttribute(contentAttr);
  302. element[idlAttr] = v.toUpperCase();
  303. todo_is(element[idlAttr], v,
  304. "Enumerated attributes should be case-insensitive.");
  305. is(element.getAttribute(contentAttr), v.toUpperCase(),
  306. "Content attribute should not be lower-cased.");
  307. element.removeAttribute(contentAttr);
  308. });
  309. }
  310. /**
  311. * Checks that a given attribute is correctly reflected as a boolean.
  312. *
  313. * @param aParameters Object object containing the parameters, which are:
  314. * - element Element node to test on
  315. * - attribute String name of the attribute
  316. * OR
  317. * attribute Object object containing two attributes, 'content' and 'idl'
  318. */
  319. function reflectBoolean(aParameters)
  320. {
  321. var element = aParameters.element;
  322. var contentAttr = typeof aParameters.attribute === "string"
  323. ? aParameters.attribute : aParameters.attribute.content;
  324. var idlAttr = typeof aParameters.attribute === "string"
  325. ? aParameters.attribute : aParameters.attribute.idl;
  326. ok(idlAttr in element,
  327. idlAttr + " should be an IDL attribute of this element");
  328. is(typeof element[idlAttr], "boolean",
  329. idlAttr + " IDL attribute should be a boolean");
  330. // Tests when the attribute isn't set.
  331. is(element.getAttribute(contentAttr), null,
  332. "When not set, the content attribute should be null.");
  333. is(element[idlAttr], false,
  334. "When not set, the IDL attribute should return false");
  335. /**
  336. * Test various values.
  337. * Each value to test is actually an object containing a 'value' property
  338. * containing the value to actually test, a 'stringified' property containing
  339. * the stringified value and a 'result' property containing the expected
  340. * result when the value is set to the IDL attribute.
  341. */
  342. var valuesToTest = [
  343. { value: true, stringified: "true", result: true },
  344. { value: false, stringified: "false", result: false },
  345. { value: "true", stringified: "true", result: true },
  346. { value: "false", stringified: "false", result: true },
  347. { value: "foo", stringified: "foo", result: true },
  348. { value: idlAttr, stringified: idlAttr, result: true },
  349. { value: contentAttr, stringified: contentAttr, result: true },
  350. { value: "null", stringified: "null", result: true },
  351. { value: "undefined", stringified: "undefined", result: true },
  352. { value: "", stringified: "", result: false },
  353. { value: undefined, stringified: "undefined", result: false },
  354. { value: null, stringified: "null", result: false },
  355. { value: +0, stringified: "0", result: false },
  356. { value: -0, stringified: "0", result: false },
  357. { value: NaN, stringified: "NaN", result: false },
  358. { value: 42, stringified: "42", result: true },
  359. { value: Infinity, stringified: "Infinity", result: true },
  360. { value: -Infinity, stringified: "-Infinity", result: true },
  361. // ES5, verse 9.2.
  362. { value: { toString: function() { return "foo" } }, stringified: "foo",
  363. result: true },
  364. { value: { valueOf: function() { return "foo" } },
  365. stringified: "[object Object]", result: true },
  366. { value: { valueOf: function() { return "quux" }, toString: undefined },
  367. stringified: "quux", result: true },
  368. { value: { valueOf: function() { return "foo" },
  369. toString: function() { return "bar" } }, stringified: "bar",
  370. result: true },
  371. { value: { valueOf: function() { return false } },
  372. stringified: "[object Object]", result: true },
  373. { value: { foo: false, bar: false }, stringified: "[object Object]",
  374. result: true },
  375. { value: { }, stringified: "[object Object]", result: true },
  376. ];
  377. valuesToTest.forEach(function(v) {
  378. element.setAttribute(contentAttr, v.value);
  379. is(element[idlAttr], true,
  380. "IDL attribute should return always return 'true' if the content attribute has been set");
  381. if (v.value === null) {
  382. // bug 667856
  383. todo(element.getAttribute(contentAttr), v.stringified,
  384. "Content attribute should return the stringified value it has been set to.");
  385. } else {
  386. is(element.getAttribute(contentAttr), v.stringified,
  387. "Content attribute should return the stringified value it has been set to.");
  388. }
  389. element.removeAttribute(contentAttr);
  390. element[idlAttr] = v.value;
  391. is(element[idlAttr], v.result, "IDL attribute should return " + v.result);
  392. is(element.getAttribute(contentAttr), v.result ? "" : null,
  393. v.result ? "Content attribute should return the empty string."
  394. : "Content attribute should return null.");
  395. is(element.hasAttribute(contentAttr), v.result,
  396. v.result ? contentAttr + " should not be present"
  397. : contentAttr + " should be present");
  398. element.removeAttribute(contentAttr);
  399. });
  400. // Tests after removeAttribute() is called. Should be equivalent with not set.
  401. is(element.getAttribute(contentAttr), null,
  402. "When not set, the content attribute should be null.");
  403. is(element[contentAttr], false,
  404. "When not set, the IDL attribute should return false");
  405. }
  406. /**
  407. * Checks that a given attribute name for a given element is correctly reflected
  408. * as an signed integer.
  409. *
  410. * @param aParameters Object object containing the parameters, which are:
  411. * - element Element node to test on
  412. * - attribute String name of the attribute
  413. * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise
  414. * - defaultValue Integer [optional] default value, if one exists
  415. */
  416. function reflectInt(aParameters)
  417. {
  418. // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute().
  419. function expectedGetAttributeResult(value) {
  420. return (value !== null) ? String(value) : "";
  421. }
  422. function stringToInteger(value, nonNegative, defaultValue) {
  423. // Parse: Ignore leading whitespace, find [+/-][numbers]
  424. var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value);
  425. if (result) {
  426. if ((nonNegative ? 0:-0x80000000) <= result[1] && result[1] <= 0x7FFFFFFF) {
  427. // If the value is within allowed value range for signed/unsigned integer, return value
  428. return result[1];
  429. }
  430. }
  431. return defaultValue;
  432. }
  433. // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute.
  434. function expectedIdlAttributeResult(value) {
  435. // This returns the result of calling the ES ToInt32 algorithm on value.
  436. return value << 0;
  437. }
  438. var element = aParameters.element;
  439. var attr = aParameters.attribute;
  440. var nonNegative = aParameters.nonNegative;
  441. var defaultValue = aParameters.defaultValue !== undefined
  442. ? aParameters.defaultValue
  443. : nonNegative ? -1 : 0;
  444. ok(attr in element, attr + " should be an IDL attribute of this element");
  445. is(typeof element[attr], "number", attr + " IDL attribute should be a number");
  446. // Check default value.
  447. is(element[attr], defaultValue, "default value should be " + defaultValue);
  448. ok(!element.hasAttribute(attr), attr + " shouldn't be present");
  449. /**
  450. * Test various values.
  451. * value: The test value that will be set using both setAttribute(value) and
  452. * element[attr] = value
  453. */
  454. var valuesToTest = [
  455. // Test numeric inputs up to max signed integer
  456. 0, 1, 55555, 2147483647, +42,
  457. // Test string inputs up to max signed integer
  458. "0", "1", "777777", "2147483647", "+42",
  459. // Test negative numeric inputs up to min signed integer
  460. -0, -1, -3333, -2147483648,
  461. // Test negative string inputs up to min signed integer
  462. "-0", "-1", "-222", "-2147483647", "-2147483648",
  463. // Test numeric inputs that are outside legal 32 bit signed values
  464. -2147483649, -3000000000, -4294967296, 2147483649, 4000000000, -4294967297,
  465. // Test string inputs with extra padding
  466. " 1111111", " 23456 ",
  467. // Test non-numeric string inputs
  468. "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello",
  469. "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF",
  470. // Test decimal numbers
  471. 1.2345, 42.0, 3456789.1, -2.3456, -6789.12345, -2147483649.1234,
  472. // Test decimal strings
  473. "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234",
  474. // Test special values
  475. undefined, null, NaN, Infinity, -Infinity,
  476. ];
  477. valuesToTest.forEach(function(v) {
  478. var intValue = stringToInteger(v, nonNegative, defaultValue);
  479. element.setAttribute(attr, v);
  480. is(element.getAttribute(attr), expectedGetAttributeResult(v), element.localName + ".setAttribute(" +
  481. attr + ", " + v + "), " + element.localName + ".getAttribute(" + attr + ") ");
  482. if (intValue == -2147483648 && element[attr] == defaultValue) {
  483. //TBD: Bug 586761: .setAttribute(attr, -2147483648) --> element[attr] == defaultValue instead of -2147483648
  484. todo_is(element[attr], intValue, "Bug 586761: " + element.localName +
  485. ".setAttribute(value, " + v + "), " + element.localName + "[" + attr + "] ");
  486. } else {
  487. is(element[attr], intValue, element.localName +
  488. ".setAttribute(" + attr + ", " + v + "), " + element.localName + "[" + attr + "] ");
  489. }
  490. element.removeAttribute(attr);
  491. if (nonNegative && expectedIdlAttributeResult(v) < 0) {
  492. try {
  493. element[attr] = v;
  494. ok(false, element.localName + "[" + attr + "] = " + v + " should throw NS_ERROR_DOM_INDEX_SIZE_ERR");
  495. } catch(e) {
  496. is(e.code, DOMException.INDEX_SIZE_ERR, element.localName + "[" + attr + "] = " + v +
  497. " should throw NS_ERROR_DOM_INDEX_SIZE_ERR");
  498. }
  499. } else {
  500. element[attr] = v;
  501. if (expectedIdlAttributeResult(v) == -2147483648 && element[attr] == defaultValue) {
  502. //TBD: Bug 586761: .setAttribute(attr, -2147483648) --> element[attr] == defaultValue instead of -2147483648
  503. todo_is(element[attr], expectedIdlAttributeResult(v), "Bug 586761: " + element.localName + "[" +
  504. attr + "] = " + v + ", " + element.localName + "[" + attr + "] ");
  505. } else {
  506. is(element[attr], expectedIdlAttributeResult(v), element.localName + "[" + attr + "] = " + v +
  507. ", " + element.localName + "[" + attr + "] ");
  508. is(element.getAttribute(attr), expectedIdlAttributeResult(v), element.localName + "[" + attr +
  509. "] = " + v + ", " + element.localName + ".getAttribute(" + attr + ") ");
  510. }
  511. }
  512. element.removeAttribute(attr);
  513. });
  514. // Tests after removeAttribute() is called. Should be equivalent with not set.
  515. is(element.getAttribute(attr), null,
  516. "When not set, the content attribute should be null.");
  517. is(element[attr], defaultValue,
  518. "When not set, the IDL attribute should return default value.");
  519. }