style.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Tools for testing Closure renderers against static markup
  16. * spec pages.
  17. *
  18. */
  19. goog.setTestOnly('goog.testing.ui.style');
  20. goog.provide('goog.testing.ui.style');
  21. goog.require('goog.array');
  22. goog.require('goog.asserts');
  23. goog.require('goog.dom');
  24. goog.require('goog.dom.classlist');
  25. goog.require('goog.testing.asserts');
  26. /**
  27. * Uses document.write to add an iFrame to the page with the reference path in
  28. * the src attribute. Used for loading an html file containing reference
  29. * structures to test against into the page. Should be called within the body of
  30. * the jsunit test page.
  31. * @param {string} referencePath A path to a reference HTML file.
  32. */
  33. goog.testing.ui.style.writeReferenceFrame = function(referencePath) {
  34. document.write(
  35. '<iframe id="reference" name="reference" ' +
  36. 'src="' + referencePath + '"></iframe>');
  37. };
  38. /**
  39. * Returns a reference to the first element child of a node with the given id
  40. * from the page loaded into the reference iFrame. Used to retrieve a particular
  41. * reference DOM structure to test against.
  42. * @param {string} referenceId The id of a container element for a reference
  43. * structure in the reference page.
  44. * @return {Node} The root element of the reference structure.
  45. */
  46. goog.testing.ui.style.getReferenceNode = function(referenceId) {
  47. return goog.dom.getFirstElementChild(
  48. window.frames['reference'].document.getElementById(referenceId));
  49. };
  50. /**
  51. * Returns an array of all element children of a given node.
  52. * @param {Node} element The node to get element children of.
  53. * @return {!Array<!Node>} An array of all the element children.
  54. */
  55. goog.testing.ui.style.getElementChildren = function(element) {
  56. var first = goog.dom.getFirstElementChild(element);
  57. if (!first) {
  58. return [];
  59. }
  60. var children = [first], next;
  61. while (next = goog.dom.getNextElementSibling(children[children.length - 1])) {
  62. children.push(next);
  63. }
  64. return children;
  65. };
  66. /**
  67. * Tests whether a given node is a "content" node of a reference structure,
  68. * which means it is allowed to have arbitrary children.
  69. * @param {Node} element The node to test.
  70. * @return {boolean} Whether the given node is a content node or not.
  71. */
  72. goog.testing.ui.style.isContentNode = function(element) {
  73. return element.className.indexOf('content') != -1;
  74. };
  75. /**
  76. * Tests that the structure, node names, and classes of the given element are
  77. * the same as the reference structure with the given id. Throws an error if the
  78. * element doesn't have the same nodes at each level of the DOM with the same
  79. * classes on each. The test ignores all DOM structure within content nodes.
  80. * @param {Node} element The root node of the DOM structure to test.
  81. * @param {string} referenceId The id of the container for the reference
  82. * structure to test against.
  83. */
  84. goog.testing.ui.style.assertStructureMatchesReference = function(
  85. element, referenceId) {
  86. goog.testing.ui.style.assertStructureMatchesReferenceInner_(
  87. element, goog.testing.ui.style.getReferenceNode(referenceId));
  88. };
  89. /**
  90. * A recursive function for comparing structure, node names, and classes between
  91. * a test and reference DOM structure. Throws an error if one of these things
  92. * doesn't match. Used internally by
  93. * {@link goog.testing.ui.style.assertStructureMatchesReference}.
  94. * @param {Node} element DOM element to test.
  95. * @param {Node} reference DOM element to use as a reference (test against).
  96. * @private
  97. */
  98. goog.testing.ui.style.assertStructureMatchesReferenceInner_ = function(
  99. element, reference) {
  100. if (!element && !reference) {
  101. return;
  102. }
  103. assertTrue('Expected two elements.', !!element && !!reference);
  104. assertEquals(
  105. 'Expected nodes to have the same nodeName.', element.nodeName,
  106. reference.nodeName);
  107. var testElem = goog.asserts.assertElement(element);
  108. var refElem = goog.asserts.assertElement(reference);
  109. var elementClasses = goog.dom.classlist.get(testElem);
  110. goog.array.forEach(goog.dom.classlist.get(refElem), function(referenceClass) {
  111. assertContains(
  112. 'Expected test node to have all reference classes.', referenceClass,
  113. elementClasses);
  114. });
  115. // Call assertStructureMatchesReferenceInner_ on all element children
  116. // unless this is a content node
  117. var elChildren = goog.testing.ui.style.getElementChildren(element),
  118. refChildren = goog.testing.ui.style.getElementChildren(reference);
  119. if (!goog.testing.ui.style.isContentNode(reference)) {
  120. if (elChildren.length != refChildren.length) {
  121. assertEquals(
  122. 'Expected same number of children for a non-content node.',
  123. elChildren.length, refChildren.length);
  124. }
  125. for (var i = 0; i < elChildren.length; i++) {
  126. goog.testing.ui.style.assertStructureMatchesReferenceInner_(
  127. elChildren[i], refChildren[i]);
  128. }
  129. }
  130. };