diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 31839b5f..79e38067 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2933,8 +2933,7 @@ getJasmineRequireObj().toThrowError = function(j$) { } // Get Error constructor of thrown - if (!thrown || !thrown.constructor || !thrown.constructor.constructor || - !(thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { + if (!isErrorObject(thrown)) { fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; return fail; } @@ -3035,7 +3034,18 @@ getJasmineRequireObj().toThrowError = function(j$) { var Surrogate = function() {}; Surrogate.prototype = type.prototype; - return (new Surrogate()) instanceof Error; + return isErrorObject(new Surrogate()); + } + + function isErrorObject(thrown) { + if (thrown instanceof Error) { + return true; + } + if (thrown && thrown.constructor && thrown.constructor.constructor && + (thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { + return true; + } + return false; } } diff --git a/spec/core/matchers/toThrowErrorSpec.js b/spec/core/matchers/toThrowErrorSpec.js index db7050c7..14726464 100644 --- a/spec/core/matchers/toThrowErrorSpec.js +++ b/spec/core/matchers/toThrowErrorSpec.js @@ -65,51 +65,41 @@ describe("toThrowError", function() { expect(result.message()).toEqual("Expected function to throw an Error, but it threw 4."); }); - function isNotRunningInBrowser() { - return typeof document === 'undefined' - } - - function isRunningInPhantomJS(minVersion, maxVersion) { - if (!window.callPhantom) { - return false; + describe("when error is from another frame", function() { + function isNotRunningInBrowser() { + return typeof document === 'undefined' } - function getVerNum(ver) { - var nums = ver.split('.'), verNum = 0; - if ((nums[0] = +nums[0])) { verNum += nums[0] * 10000; } - if ((nums[1] = +nums[1])) { verNum += nums[1] * 100; } - if ((nums[2] = +nums[2])) { verNum += nums[2]; } - return verNum; - } + var iframe = null; - if (minVersion || maxVersion) { - var ver = (/\sPhantomJS\/([\d\.]+)\s/.exec(window.navigator.userAgent) || [])[1]; - if (!ver) { return false; } - ver = getVerNum(ver); - if (minVersion && ver < getVerNum(minVersion)) { return false; } - if (maxVersion && ver > getVerNum(maxVersion)) { return false; } - } - return true; - } + afterEach(function() { + if (iframe !== null) { + document.body.removeChild(iframe); + } + }); - it("passes if thrown is an instanceof Error regardless of global that contains its constructor", function() { - if (isNotRunningInBrowser() || isRunningInPhantomJS(null, '1.9.8')) { - return; - } + it("passes if thrown is an instanceof Error regardless of global that contains its constructor", function() { + if (isNotRunningInBrowser() || jasmine.getEnv().phantomVersion < 2 || jasmine.getEnv().ieVersion < 10) { + return; + } - var matcher = jasmineUnderTest.matchers.toThrowError(), - iframe = document.body.appendChild(document.createElement("iframe")), - iframeDocument = iframe.contentDocument, - result; + var matcher = jasmineUnderTest.matchers.toThrowError(); + iframe = document.body.appendChild(document.createElement("iframe")); + iframe.src = "about:blank"; + var iframeDocument = iframe.contentWindow.document; - iframeDocument.body.appendChild(iframeDocument.createElement("script")) - .textContent = "function method() { throw new Error('foo'); }"; + if (iframeDocument.body) { + iframeDocument.body.appendChild(iframeDocument.createElement("script")) + .textContent = "function method() { throw new Error('foo'); }"; + } else { + // older IE + iframeDocument.write("
"); + } - result = matcher.compare(iframe.contentWindow.method); - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an Error, but it threw Error."); - - document.body.removeChild(iframe); + var result = matcher.compare(iframe.contentWindow.method); + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an Error, but it threw Error."); + }); }); it("fails with the correct message if thrown is a falsy value", function() { diff --git a/spec/helpers/BrowserFlags.js b/spec/helpers/BrowserFlags.js index c8300b62..ca39c678 100644 --- a/spec/helpers/BrowserFlags.js +++ b/spec/helpers/BrowserFlags.js @@ -20,4 +20,8 @@ return /Firefox\/([0-9]{0,})/.exec(userAgent); }); + env.phantomVersion = browserVersion(function(userAgent) { + return /PhantomJs\/([0-9.]{0,})+/.exec(userAgent); + }); + })(jasmine.getEnv()); diff --git a/src/core/matchers/toThrowError.js b/src/core/matchers/toThrowError.js index f6859c61..7ddda72e 100644 --- a/src/core/matchers/toThrowError.js +++ b/src/core/matchers/toThrowError.js @@ -29,8 +29,7 @@ getJasmineRequireObj().toThrowError = function(j$) { } // Get Error constructor of thrown - if (!thrown || !thrown.constructor || !thrown.constructor.constructor || - !(thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { + if (!isErrorObject(thrown)) { fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; return fail; } @@ -131,7 +130,18 @@ getJasmineRequireObj().toThrowError = function(j$) { var Surrogate = function() {}; Surrogate.prototype = type.prototype; - return (new Surrogate()) instanceof Error; + return isErrorObject(new Surrogate()); + } + + function isErrorObject(thrown) { + if (thrown instanceof Error) { + return true; + } + if (thrown && thrown.constructor && thrown.constructor.constructor && + (thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { + return true; + } + return false; } }