609 lines
22 KiB
JavaScript
609 lines
22 KiB
JavaScript
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
/**
|
|
* @fileoverview Testing utilities for DOM related tests.
|
|
*
|
|
* @author robbyw@google.com (Robby Walker)
|
|
*/
|
|
|
|
goog.provide('goog.testing.dom');
|
|
|
|
goog.require('goog.dom');
|
|
goog.require('goog.dom.NodeIterator');
|
|
goog.require('goog.dom.NodeType');
|
|
goog.require('goog.dom.TagIterator');
|
|
goog.require('goog.dom.TagName');
|
|
goog.require('goog.dom.classes');
|
|
goog.require('goog.iter');
|
|
goog.require('goog.object');
|
|
goog.require('goog.string');
|
|
goog.require('goog.style');
|
|
goog.require('goog.testing.asserts');
|
|
goog.require('goog.userAgent');
|
|
|
|
|
|
/**
|
|
* A unique object to use as an end tag marker.
|
|
* @type {Object}
|
|
* @private
|
|
*/
|
|
goog.testing.dom.END_TAG_MARKER_ = {};
|
|
|
|
|
|
/**
|
|
* Tests if the given iterator over nodes matches the given Array of node
|
|
* descriptors. Throws an error if any match fails.
|
|
* @param {goog.iter.Iterator} it An iterator over nodes.
|
|
* @param {Array.<Node|number|string>} array Array of node descriptors to match
|
|
* against. Node descriptors can be any of the following:
|
|
* Node: Test if the two nodes are equal.
|
|
* number: Test node.nodeType == number.
|
|
* string starting with '#': Match the node's id with the text
|
|
* after "#".
|
|
* other string: Match the text node's contents.
|
|
*/
|
|
goog.testing.dom.assertNodesMatch = function(it, array) {
|
|
var i = 0;
|
|
goog.iter.forEach(it, function(node) {
|
|
if (array.length <= i) {
|
|
fail('Got more nodes than expected: ' + goog.testing.dom.describeNode_(
|
|
node));
|
|
}
|
|
var expected = array[i];
|
|
|
|
if (goog.dom.isNodeLike(expected)) {
|
|
assertEquals('Nodes should match at position ' + i, expected, node);
|
|
} else if (goog.isNumber(expected)) {
|
|
assertEquals('Node types should match at position ' + i, expected,
|
|
node.nodeType);
|
|
} else if (expected.charAt(0) == '#') {
|
|
assertEquals('Expected element at position ' + i,
|
|
goog.dom.NodeType.ELEMENT, node.nodeType);
|
|
var expectedId = expected.substr(1);
|
|
assertEquals('IDs should match at position ' + i,
|
|
expectedId, node.id);
|
|
|
|
} else {
|
|
assertEquals('Expected text node at position ' + i,
|
|
goog.dom.NodeType.TEXT, node.nodeType);
|
|
assertEquals('Node contents should match at position ' + i,
|
|
expected, node.nodeValue);
|
|
}
|
|
|
|
i++;
|
|
});
|
|
|
|
assertEquals('Used entire match array', array.length, i);
|
|
};
|
|
|
|
|
|
/**
|
|
* Exposes a node as a string.
|
|
* @param {Node} node A node.
|
|
* @return {string} A string representation of the node.
|
|
*/
|
|
goog.testing.dom.exposeNode = function(node) {
|
|
return (node.tagName || node.nodeValue) + (node.id ? '#' + node.id : '') +
|
|
':"' + (node.innerHTML || '') + '"';
|
|
};
|
|
|
|
|
|
/**
|
|
* Exposes the nodes of a range wrapper as a string.
|
|
* @param {goog.dom.AbstractRange} range A range.
|
|
* @return {string} A string representation of the range.
|
|
*/
|
|
goog.testing.dom.exposeRange = function(range) {
|
|
// This is deliberately not implemented as
|
|
// goog.dom.AbstractRange.prototype.toString, because it is non-authoritative.
|
|
// Two equivalent ranges may have very different exposeRange values, and
|
|
// two different ranges may have equal exposeRange values.
|
|
// (The mapping of ranges to DOM nodes/offsets is a many-to-many mapping).
|
|
if (!range) {
|
|
return 'null';
|
|
}
|
|
return goog.testing.dom.exposeNode(range.getStartNode()) + ':' +
|
|
range.getStartOffset() + ' to ' +
|
|
goog.testing.dom.exposeNode(range.getEndNode()) + ':' +
|
|
range.getEndOffset();
|
|
};
|
|
|
|
|
|
/**
|
|
* Determines if the current user agent matches the specified string. Returns
|
|
* false if the string does specify at least one user agent but does not match
|
|
* the running agent.
|
|
* @param {string} userAgents Space delimited string of user agents.
|
|
* @return {boolean} Whether the user agent was matched. Also true if no user
|
|
* agent was listed in the expectation string.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.checkUserAgents_ = function(userAgents) {
|
|
if (goog.string.startsWith(userAgents, '!')) {
|
|
if (goog.string.contains(userAgents, ' ')) {
|
|
throw new Error('Only a single negative user agent may be specified');
|
|
}
|
|
return !goog.userAgent[userAgents.substr(1)];
|
|
}
|
|
|
|
var agents = userAgents.split(' ');
|
|
var hasUserAgent = false;
|
|
for (var i = 0, len = agents.length; i < len; i++) {
|
|
var cls = agents[i];
|
|
if (cls in goog.userAgent) {
|
|
hasUserAgent = true;
|
|
if (goog.userAgent[cls]) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// If we got here, there was a user agent listed but we didn't match it.
|
|
return !hasUserAgent;
|
|
};
|
|
|
|
|
|
/**
|
|
* Map function that converts end tags to a specific object.
|
|
* @param {Node} node The node to map.
|
|
* @param {undefined} ignore Always undefined.
|
|
* @param {goog.dom.TagIterator} iterator The iterator.
|
|
* @return {Node|Object} The resulting iteration item.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.endTagMap_ = function(node, ignore, iterator) {
|
|
return iterator.isEndTag() ? goog.testing.dom.END_TAG_MARKER_ : node;
|
|
};
|
|
|
|
|
|
/**
|
|
* Check if the given node is important. A node is important if it is a
|
|
* non-empty text node, a non-annotated element, or an element annotated to
|
|
* match on this user agent.
|
|
* @param {Node} node The node to test.
|
|
* @return {boolean} Whether this node should be included for iteration.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.nodeFilter_ = function(node) {
|
|
if (node.nodeType == goog.dom.NodeType.TEXT) {
|
|
// If a node is part of a string of text nodes and it has spaces in it,
|
|
// we allow it since it's going to affect the merging of nodes done below.
|
|
if (goog.string.isBreakingWhitespace(node.nodeValue) &&
|
|
(!node.previousSibling ||
|
|
node.previousSibling.nodeType != goog.dom.NodeType.TEXT) &&
|
|
(!node.nextSibling ||
|
|
node.nextSibling.nodeType != goog.dom.NodeType.TEXT)) {
|
|
return false;
|
|
}
|
|
// Allow optional text to be specified as [[BROWSER1 BROWSER2]]Text
|
|
var match = node.nodeValue.match(/^\[\[(.+)\]\]/);
|
|
if (match) {
|
|
return goog.testing.dom.checkUserAgents_(match[1]);
|
|
}
|
|
} else if (node.className) {
|
|
return goog.testing.dom.checkUserAgents_(node.className);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
|
|
/**
|
|
* Determines the text to match from the given node, removing browser
|
|
* specification strings.
|
|
* @param {Node} node The node expected to match.
|
|
* @return {string} The text, stripped of browser specification strings.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.getExpectedText_ = function(node) {
|
|
// Strip off the browser specifications.
|
|
return node.nodeValue.match(/^(\[\[.+\]\])?(.*)/)[2];
|
|
};
|
|
|
|
|
|
/**
|
|
* Describes the given node.
|
|
* @param {Node} node The node to describe.
|
|
* @return {string} A description of the node.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.describeNode_ = function(node) {
|
|
if (node.nodeType == goog.dom.NodeType.TEXT) {
|
|
return '[Text: ' + node.nodeValue + ']';
|
|
} else {
|
|
return '<' + node.tagName + (node.id ? ' #' + node.id : '') + ' .../>';
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Assert that the html in {@code actual} is substantially similar to
|
|
* htmlPattern. This method tests for the same set of styles, for the same
|
|
* order of nodes, and the presence of attributes. Breaking whitespace nodes
|
|
* are ignored. Elements can be
|
|
* annotated with classnames corresponding to keys in goog.userAgent and will be
|
|
* expected to show up in that user agent and expected not to show up in
|
|
* others.
|
|
* @param {string} htmlPattern The pattern to match.
|
|
* @param {!Element} actual The element to check: its contents are matched
|
|
* against the HTML pattern.
|
|
* @param {boolean=} opt_strictAttributes If false, attributes that appear in
|
|
* htmlPattern must be in actual, but actual can have attributes not
|
|
* present in htmlPattern. If true, htmlPattern and actual must have the
|
|
* same set of attributes. Default is false.
|
|
*/
|
|
goog.testing.dom.assertHtmlContentsMatch = function(htmlPattern, actual,
|
|
opt_strictAttributes) {
|
|
var div = goog.dom.createDom(goog.dom.TagName.DIV);
|
|
div.innerHTML = htmlPattern;
|
|
|
|
var errorSuffix = '\nExpected\n' + htmlPattern + '\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() {
|
|
// If the iterator has already been advanced, don't advance it again.
|
|
if (!preIterated) {
|
|
actualNode = /** @type {Node} */ (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 = /** @type {Node} */ (goog.iter.nextOrValue(actualIt, null));
|
|
}
|
|
};
|
|
|
|
// HACK(brenneman): IE has unique ideas about whitespace handling when setting
|
|
// innerHTML. This results in elision of leading whitespace in the expected
|
|
// nodes where doing so doesn't affect visible rendering. As a workaround, we
|
|
// remove the leading whitespace in the actual nodes where necessary.
|
|
//
|
|
// The collapsible variable tracks whether we should collapse the whitespace
|
|
// in the next Text node we encounter.
|
|
var IE_TEXT_COLLAPSE =
|
|
goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
|
|
|
|
var collapsible = true;
|
|
|
|
var number = 0;
|
|
goog.iter.forEach(expectedIt, function(expectedNode) {
|
|
expectedNode = /** @type {Node} */ (expectedNode);
|
|
|
|
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) {
|
|
assertEquals('Tag names should match' + errorSuffix,
|
|
expectedNode.tagName, actualNode.tagName);
|
|
assertObjectEquals('Should have same styles' + errorSuffix,
|
|
goog.style.parseStyleAttribute(expectedNode.style.cssText),
|
|
goog.style.parseStyleAttribute(actualNode.style.cssText));
|
|
goog.testing.dom.assertAttributesEqual_(errorSuffix, expectedNode,
|
|
actualNode, !!opt_strictAttributes);
|
|
|
|
if (IE_TEXT_COLLAPSE &&
|
|
goog.style.getCascadedStyle(
|
|
/** @type {Element} */ (actualNode), 'display') != 'inline') {
|
|
// Text may be collapsed after any non-inline element.
|
|
collapsible = true;
|
|
}
|
|
} else {
|
|
// Concatenate text nodes until we reach a non text node.
|
|
var actualText = actualNode.nodeValue;
|
|
preIterated = true;
|
|
while ((actualNode = /** @type {Node} */
|
|
(goog.iter.nextOrValue(actualIt, null))) &&
|
|
actualNode.nodeType == goog.dom.NodeType.TEXT) {
|
|
actualText += actualNode.nodeValue;
|
|
}
|
|
|
|
if (IE_TEXT_COLLAPSE) {
|
|
// Collapse the leading whitespace, unless the string consists entirely
|
|
// of whitespace.
|
|
if (collapsible && !goog.string.isEmpty(actualText)) {
|
|
actualText = goog.string.trimLeft(actualText);
|
|
}
|
|
// Prepare to collapse whitespace in the next Text node if this one does
|
|
// not end in a whitespace character.
|
|
collapsible = /\s$/.test(actualText);
|
|
}
|
|
|
|
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));
|
|
};
|
|
|
|
|
|
/**
|
|
* Assert that the html in {@code actual} is substantially similar to
|
|
* htmlPattern. This method tests for the same set of styles, and for the same
|
|
* order of nodes. Breaking whitespace nodes are ignored. Elements can be
|
|
* annotated with classnames corresponding to keys in goog.userAgent and will be
|
|
* expected to show up in that user agent and expected not to show up in
|
|
* others.
|
|
* @param {string} htmlPattern The pattern to match.
|
|
* @param {string} actual The html to check.
|
|
*/
|
|
goog.testing.dom.assertHtmlMatches = function(htmlPattern, actual) {
|
|
var div = goog.dom.createDom(goog.dom.TagName.DIV);
|
|
div.innerHTML = actual;
|
|
|
|
goog.testing.dom.assertHtmlContentsMatch(htmlPattern, div);
|
|
};
|
|
|
|
|
|
/**
|
|
* Finds the first text node descendant of root with the given content. Note
|
|
* that this operates on a text node level, so if text nodes get split this
|
|
* may not match the user visible text. Using normalize() may help here.
|
|
* @param {string|RegExp} textOrRegexp The text to find, or a regular
|
|
* expression to find a match of.
|
|
* @param {Element} root The element to search in.
|
|
* @return {Node} The first text node that matches, or null if none is found.
|
|
*/
|
|
goog.testing.dom.findTextNode = function(textOrRegexp, root) {
|
|
var it = new goog.dom.NodeIterator(root);
|
|
var ret = goog.iter.nextOrValue(goog.iter.filter(it, function(node) {
|
|
if (node.nodeType == goog.dom.NodeType.TEXT) {
|
|
if (goog.isString(textOrRegexp)) {
|
|
return node.nodeValue == textOrRegexp;
|
|
} else {
|
|
return !!node.nodeValue.match(textOrRegexp);
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}), null);
|
|
return /** @type {Node} */ (ret);
|
|
};
|
|
|
|
|
|
/**
|
|
* Assert the end points of a range.
|
|
*
|
|
* Notice that "Are two ranges visually identical?" and "Do two ranges have
|
|
* the same endpoint?" are independent questions. Two visually identical ranges
|
|
* may have different endpoints. And two ranges with the same endpoints may
|
|
* be visually different.
|
|
*
|
|
* @param {Node} start The expected start node.
|
|
* @param {number} startOffset The expected start offset.
|
|
* @param {Node} end The expected end node.
|
|
* @param {number} endOffset The expected end offset.
|
|
* @param {goog.dom.AbstractRange} range The actual range.
|
|
*/
|
|
goog.testing.dom.assertRangeEquals = function(start, startOffset, end,
|
|
endOffset, range) {
|
|
assertEquals('Unexpected start node', start, range.getStartNode());
|
|
assertEquals('Unexpected end node', end, range.getEndNode());
|
|
assertEquals('Unexpected start offset', startOffset, range.getStartOffset());
|
|
assertEquals('Unexpected end offset', endOffset, range.getEndOffset());
|
|
};
|
|
|
|
|
|
/**
|
|
* Gets the value of a DOM attribute in deterministic way.
|
|
* @param {!Node} node A node.
|
|
* @param {string} name Attribute name.
|
|
* @return {*} Attribute value.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.getAttributeValue_ = function(node, name) {
|
|
// These hacks avoid nondetermistic results in the following cases:
|
|
// IE7: document.createElement('input').height returns a random number.
|
|
// FF3: getAttribute('disabled') returns different value for <div disabled="">
|
|
// and <div disabled="disabled">
|
|
// WebKit: Two radio buttons with the same name can't be checked at the same
|
|
// time, even if only one of them is in the document.
|
|
if (goog.userAgent.WEBKIT && node.tagName == 'INPUT' &&
|
|
node['type'] == 'radio' && name == 'checked') {
|
|
return false;
|
|
}
|
|
return goog.isDef(node[name]) &&
|
|
typeof node.getAttribute(name) != typeof node[name] ?
|
|
node[name] : node.getAttribute(name);
|
|
};
|
|
|
|
|
|
/**
|
|
* Assert that the attributes of two Nodes are the same (ignoring any
|
|
* instances of the style attribute).
|
|
* @param {string} errorSuffix String to add to end of error messages.
|
|
* @param {Node} expectedNode The node whose attributes we are expecting.
|
|
* @param {Node} actualNode The node with the actual attributes.
|
|
* @param {boolean} strictAttributes If false, attributes that appear in
|
|
* expectedNode must also be in actualNode, but actualNode can have
|
|
* attributes not present in expectedNode. If true, expectedNode and
|
|
* actualNode must have the same set of attributes.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.assertAttributesEqual_ = function(errorSuffix,
|
|
expectedNode, actualNode, strictAttributes) {
|
|
if (strictAttributes) {
|
|
goog.testing.dom.compareClassAttribute_(expectedNode, actualNode);
|
|
}
|
|
|
|
var expectedAttributes = expectedNode.attributes;
|
|
var actualAttributes = actualNode.attributes;
|
|
|
|
for (var i = 0, len = expectedAttributes.length; i < len; i++) {
|
|
var expectedName = expectedAttributes[i].name;
|
|
var expectedValue = goog.testing.dom.getAttributeValue_(expectedNode,
|
|
expectedName);
|
|
|
|
var actualAttribute = actualAttributes[expectedName];
|
|
var actualValue = goog.testing.dom.getAttributeValue_(actualNode,
|
|
expectedName);
|
|
|
|
// IE enumerates attribute names in the expected node that are not present,
|
|
// causing an undefined actualAttribute.
|
|
if (!expectedValue && !actualValue) {
|
|
continue;
|
|
}
|
|
|
|
if (expectedName == 'id' && goog.userAgent.IE) {
|
|
goog.testing.dom.compareIdAttributeForIe_(
|
|
/** @type {string} */ (expectedValue), actualAttribute,
|
|
strictAttributes, errorSuffix);
|
|
continue;
|
|
}
|
|
|
|
if (goog.testing.dom.ignoreAttribute_(expectedName)) {
|
|
continue;
|
|
}
|
|
|
|
assertNotUndefined('Expected to find attribute with name ' +
|
|
expectedName + ', in element ' +
|
|
goog.testing.dom.describeNode_(actualNode) + errorSuffix,
|
|
actualAttribute);
|
|
assertEquals('Expected attribute ' + expectedName +
|
|
' has a different value ' + errorSuffix,
|
|
expectedValue,
|
|
goog.testing.dom.getAttributeValue_(actualNode, actualAttribute.name));
|
|
}
|
|
|
|
if (strictAttributes) {
|
|
for (i = 0; i < actualAttributes.length; i++) {
|
|
var actualName = actualAttributes[i].name;
|
|
var actualAttribute = actualAttributes.getNamedItem(actualName);
|
|
|
|
if (!actualAttribute || goog.testing.dom.ignoreAttribute_(actualName)) {
|
|
continue;
|
|
}
|
|
|
|
assertNotUndefined('Unexpected attribute with name ' +
|
|
actualName + ' in element ' +
|
|
goog.testing.dom.describeNode_(actualNode) + errorSuffix,
|
|
expectedAttributes[actualName]);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Assert the class attribute of actualNode is the same as the one in
|
|
* expectedNode, ignoring classes that are useragents.
|
|
* @param {Node} expectedNode The DOM node whose class we expect.
|
|
* @param {Node} actualNode The DOM node with the actual class.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.compareClassAttribute_ = function(expectedNode,
|
|
actualNode) {
|
|
var classes = goog.dom.classes.get(expectedNode);
|
|
|
|
var expectedClasses = [];
|
|
for (var i = 0, len = classes.length; i < len; i++) {
|
|
if (!(classes[i] in goog.userAgent)) {
|
|
expectedClasses.push(classes[i]);
|
|
}
|
|
}
|
|
expectedClasses.sort();
|
|
|
|
var actualClasses = goog.dom.classes.get(actualNode);
|
|
actualClasses.sort();
|
|
|
|
assertArrayEquals(
|
|
'Expected class was: ' + expectedClasses.join(' ') +
|
|
', but actual class was: ' + actualNode.className,
|
|
expectedClasses, actualClasses);
|
|
};
|
|
|
|
|
|
/**
|
|
* Set of attributes IE adds to elements randomly.
|
|
* @type {Object}
|
|
* @private
|
|
*/
|
|
goog.testing.dom.BAD_IE_ATTRIBUTES_ = goog.object.createSet(
|
|
'methods', 'CHECKED', 'dataFld', 'dataFormatAs', 'dataSrc');
|
|
|
|
|
|
/**
|
|
* Whether to ignore the attribute.
|
|
* @param {string} name Name of the attribute.
|
|
* @return {boolean} True if the attribute should be ignored.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.ignoreAttribute_ = function(name) {
|
|
if (name == 'style' || name == 'class') {
|
|
return true;
|
|
}
|
|
return goog.userAgent.IE && goog.testing.dom.BAD_IE_ATTRIBUTES_[name];
|
|
};
|
|
|
|
|
|
/**
|
|
* Compare id attributes for IE. In IE, if an element lacks an id attribute
|
|
* in the original HTML, the element object will still have such an attribute,
|
|
* but its value will be the empty string.
|
|
* @param {string} expectedValue The expected value of the id attribute.
|
|
* @param {Attr} actualAttribute The actual id attribute.
|
|
* @param {boolean} strictAttributes Whether strict attribute checking should be
|
|
* done.
|
|
* @param {string} errorSuffix String to append to error messages.
|
|
* @private
|
|
*/
|
|
goog.testing.dom.compareIdAttributeForIe_ = function(expectedValue,
|
|
actualAttribute, strictAttributes, errorSuffix) {
|
|
if (expectedValue === '') {
|
|
if (strictAttributes) {
|
|
assertTrue('Unexpected attribute with name id in element ' +
|
|
errorSuffix, actualAttribute.value == '');
|
|
}
|
|
} else {
|
|
assertNotUndefined('Expected to find attribute with name id, in element ' +
|
|
errorSuffix, actualAttribute);
|
|
assertNotEquals('Expected to find attribute with name id, in element ' +
|
|
errorSuffix, '', actualAttribute.value);
|
|
assertEquals('Expected attribute has a different value ' + errorSuffix,
|
|
expectedValue, actualAttribute.value);
|
|
}
|
|
};
|