goog.testing.dom.assertHtmlContentsMatch = function()

in closure/goog/testing/dom.js [305:424]


goog.testing.dom.assertHtmlContentsMatch = function(
    htmlPattern, actual, opt_strictAttributes) {
  'use strict';
  var div = goog.dom.createDom(goog.dom.TagName.DIV);

  goog.dom.safe.setInnerHtml(
      div,
      goog.html.uncheckedconversions
          .safeHtmlFromStringKnownToSatisfyTypeContract(
              goog.string.Const.from('HTML is never attached to DOM'),
              htmlPattern));

  var errorSuffix =
      '\nExpected\n' + div.innerHTML + '\nActual\n' + actual.innerHTML;

  var actualIt = goog.iter.filter(
      goog.iter.map(
          new goog.dom.TagIterator(actual), goog.testing.dom.endTagMap_),
      goog.testing.dom.nodeFilter_);

  var expectedIt = goog.iter.filter(
      new goog.dom.NodeIterator(div), goog.testing.dom.nodeFilter_);

  var actualNode;
  var preIterated = false;
  var advanceActualNode = function() {
    'use strict';
    // If the iterator has already been advanced, don't advance it again.
    if (!preIterated) {
      actualNode = goog.iter.nextOrValue(actualIt, null);
    }
    preIterated = false;

    // Advance the iterator so long as it is return end tags.
    while (actualNode == goog.testing.dom.END_TAG_MARKER_) {
      actualNode = goog.iter.nextOrValue(actualIt, null);
    }
  };


  var number = 0;
  goog.iter.forEach(expectedIt, function(expectedNode) {
    'use strict';
    advanceActualNode();
    assertNotNull(
        'Finished actual HTML before finishing expected HTML at ' +
            'node number ' + number + ': ' +
            goog.testing.dom.describeNode_(expectedNode) + errorSuffix,
        actualNode);

    // Do no processing for expectedNode == div.
    if (expectedNode == div) {
      return;
    }

    assertEquals(
        'Should have the same node type, got ' +
            goog.testing.dom.describeNode_(actualNode) + ' but expected ' +
            goog.testing.dom.describeNode_(expectedNode) + '.' + errorSuffix,
        expectedNode.nodeType, actualNode.nodeType);

    if (expectedNode.nodeType == goog.dom.NodeType.ELEMENT) {
      var expectedElem = goog.asserts.assertElement(expectedNode);
      var actualElem = goog.asserts.assertElement(actualNode);

      assertEquals(
          'Tag names should match' + errorSuffix, expectedElem.tagName,
          actualElem.tagName);
      assertEquals(
          'Namespaces should match' + errorSuffix, expectedElem.namespaceURI,
          actualElem.namespaceURI);
      assertObjectEquals(
          'Should have same styles' + errorSuffix,
          goog.style.parseStyleAttribute(expectedElem.style.cssText),
          goog.style.parseStyleAttribute(actualElem.style.cssText));
      goog.testing.dom.assertAttributesEqual_(
          errorSuffix, expectedElem, actualElem, !!opt_strictAttributes);

      // Contents of template tags belong to a separate document and are not
      // iterated on by the current iterator, unless the browser is too old to
      // treat template tags differently. We recursively assert equality of the
      // two template document fragments.
      if (actualElem.tagName == goog.dom.TagName.TEMPLATE) {
        // IE throws if HTMLTemplateElement is referenced at runtime.
        actualElem = /** @type {HTMLTemplateElement} */ (actualElem);
        if (actualElem.content) {
          goog.testing.dom.assertHtmlMatches(
              expectedElem.innerHTML, actualElem.innerHTML,
              opt_strictAttributes);
        }
      }
    } else {
      // Concatenate text nodes until we reach a non text node.
      var actualText = actualNode.nodeValue;
      preIterated = true;
      while ((actualNode = goog.iter.nextOrValue(actualIt, null)) &&
             actualNode.nodeType == goog.dom.NodeType.TEXT) {
        actualText += actualNode.nodeValue;
      }

      var expectedText = goog.testing.dom.getExpectedText_(expectedNode);
      if ((actualText && !goog.string.isBreakingWhitespace(actualText)) ||
          (expectedText && !goog.string.isBreakingWhitespace(expectedText))) {
        var normalizedActual = actualText.replace(/\s+/g, ' ');
        var normalizedExpected = expectedText.replace(/\s+/g, ' ');

        assertEquals(
            'Text should match' + errorSuffix, normalizedExpected,
            normalizedActual);
      }
    }

    number++;
  });

  advanceActualNode();
  assertNull(
      'Finished expected HTML before finishing actual HTML' + errorSuffix,
      goog.iter.nextOrValue(actualIt, null));
};