diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index ba53d714..93e5883f 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2288,6 +2288,29 @@ getJasmineRequireObj().matchersUtil = function(j$) { a.ignoreCase == b.ignoreCase; } if (typeof a != 'object' || typeof b != 'object') { return false; } + + var aIsDomNode = j$.isDomNode(a); + var bIsDomNode = j$.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + if (a.isEqualNode) { + return a.isEqualNode(b); + } + // IE8 doesn't support isEqualNode, try to use outerHTML && innerText + var aIsElement = a instanceof Element; + var bIsElement = b instanceof Element; + if (aIsElement && bIsElement) { + return a.outerHTML == b.outerHTML; + } + if (aIsElement || bIsElement) { + return false; + } + return a.innerText == b.innerText && a.textContent == b.textContent; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. var length = aStack.length; diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index ebca6a7d..2e68a3d2 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -132,6 +132,45 @@ describe("matchersUtil", function() { expect(j$.matchersUtil.equals(a,b)).toBe(true); }); + it("passes for equivalent DOM nodes", function() { + if (typeof document === 'undefined') { + return; + } + var a = document.createElement("div"); + a.setAttribute("test-attr", "attr-value") + a.appendChild(document.createTextNode('test')); + + var b = document.createElement("div"); + b.setAttribute("test-attr", "attr-value") + b.appendChild(document.createTextNode('test')); + + expect(j$.matchersUtil.equals(a,b)).toBe(true); + }); + + it("fails for DOM nodes with different attributes or child nodes", function() { + if (typeof document === 'undefined') { + return; + } + var a = document.createElement("div"); + a.setAttribute("test-attr", "attr-value") + a.appendChild(document.createTextNode('test')); + + var b = document.createElement("div"); + b.setAttribute("test-attr", "attr-value2") + b.appendChild(document.createTextNode('test')); + + expect(j$.matchersUtil.equals(a,b)).toBe(false); + + b.setAttribute("test-attr", "attr-value"); + expect(j$.matchersUtil.equals(a,b)).toBe(true); + + b.appendChild(document.createTextNode('2')); + expect(j$.matchersUtil.equals(a,b)).toBe(false); + + a.appendChild(document.createTextNode('2')); + expect(j$.matchersUtil.equals(a,b)).toBe(true); + }); + it("passes when Any is used", function() { var number = 3, anyNumber = new j$.Any(Number); diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index 1f7a6817..f58331fd 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -110,6 +110,29 @@ getJasmineRequireObj().matchersUtil = function(j$) { a.ignoreCase == b.ignoreCase; } if (typeof a != 'object' || typeof b != 'object') { return false; } + + var aIsDomNode = j$.isDomNode(a); + var bIsDomNode = j$.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + if (a.isEqualNode) { + return a.isEqualNode(b); + } + // IE8 doesn't support isEqualNode, try to use outerHTML && innerText + var aIsElement = a instanceof Element; + var bIsElement = b instanceof Element; + if (aIsElement && bIsElement) { + return a.outerHTML == b.outerHTML; + } + if (aIsElement || bIsElement) { + return false; + } + return a.innerText == b.innerText && a.textContent == b.textContent; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. var length = aStack.length;