Skip to content

Commit

Permalink
Merge pull request #20 from jagoda/capture_errors
Browse files Browse the repository at this point in the history
Script errors in fixtures are not reported in the parent window.
  • Loading branch information
Duncan Wong committed Dec 3, 2013
2 parents 3403f5c + 9c3ad26 commit 03160e6
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 47 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Finally, there are two convenience methods to access the contents of the sandbox
Options:
- `fixtures.containerId`
- change the ID of the iframe that gets injected into the page
- `fixtures.visible`
- make fixtures 'visible' in the DOM (default: false)
- `fixtures.path`
- change the path to look for fixtures (default: `spec/javascripts/fixtures`)

Expand Down
22 changes: 12 additions & 10 deletions fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

self.containerId = 'js-fixtures';
self.path = 'spec/javascripts/fixtures';
self.visible = false;
self.window = function(){
var iframe = document.getElementById(self.containerId);
if (!iframe) return null;
Expand Down Expand Up @@ -64,15 +63,8 @@
var cb = typeof arguments[arguments.length - 1] === 'function' ? arguments[arguments.length -1] : null;
var iframe = document.createElement('iframe');
iframe.setAttribute('id', self.containerId);
if (self.visible) {
// Firefox needs the frame to be displayed in order for the contents
// to register as 'visible'.
iframe.style.display = 'block';
iframe.style.width = '1px';
iframe.style.height = '1px';
} else {
iframe.style.display = 'none';
}
iframe.style.opacity = 0;
iframe.style.filter = 'alpha(0)';

document.body.appendChild(iframe);
var doc = iframe.contentWindow || iframe.contentDocument;
Expand All @@ -88,6 +80,7 @@
}

doc.open();
doc.defaultView.onerror = captureErrors;
doc.write(html)
doc.close();
};
Expand All @@ -96,6 +89,15 @@
if (!container) createContainer.apply(self, arguments);
else self.window().document.body.innerHTML += html;
};
var captureErrors = function(){
if (window.onerror){
// Rewrite the message prefix to indicate that the error
// occurred in the fixture.
arguments[0] = arguments[0].replace(/^[^:]*/, "Uncaught fixture error");
window.onerror.apply(window, arguments);
}
return true;
};
var getFixtureHtml = function(url){
if (typeof fixturesCache[url] === 'undefined'){
loadFixtureIntoCache(url);
Expand Down
60 changes: 25 additions & 35 deletions test/fixtures-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,54 +33,44 @@ define(function(require){
it("should set 'spec/javascripts/fixtures/' as the default fixtures path", function(){
expect(fixtures.path).to.equal('spec/javascripts/fixtures');
});
it("should disable fixture visibility by default", function(){
expect(fixtures.visible).to.equal(false);
});
it("should set body to null", function(){
expect(fixtures.body()).to.be(null);
});
it("should set window to null", function(){
expect(fixtures.window()).to.be(null);
});
});
describe("visible", function(){
describe("content", function(){
// jQuery defines 'visible' based on if an element consumes space in the page layout.
// See http://api.jquery.com/visible-selector/
// and https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
var oldVisible;
beforeEach(function(){
oldVisible = fixtures.visible;
});
afterEach(function(){
fixtures.visible = oldVisible;
});

describe("when enabled", function(){
it("should be 'visible'", function(){
fixtures.set("<button id='test'>Test</button>");
var button = fixtures.window().document.getElementById('test');
expect(button.offsetHeight).to.be.greaterThan(0);
expect(button.offsetWidth).to.be.greaterThan(0);
});
describe("throws an unhandled error", function(){
var errorHandler;
beforeEach(function(){
fixtures.visible = true;
fixtures.set("<button id='test'>Test</button>");
});
it("should display fixtures", function(){
var container = document.getElementById(fixtures.containerId);
var button = fixtures.window().document.getElementById('test');
expect(container.style.display).to.equal('block');
// Firefox will collapse inner dimensions to 0 if the
// element is not displayed.
expect(button.offsetHeight).to.be.greaterThan(0);
expect(button.offsetWidth).to.be.greaterThan(0);
errorHandler = window.onerror;
});
});
describe("when disabled", function(){
beforeEach(function(){
fixtures.visible = false;
fixtures.set("<button id='test'>Test</button>");
afterEach(function(){
window.onerror = errorHandler;
});
it("should hide fixtures", function(){
var container = document.getElementById(fixtures.containerId);
var button = fixtures.window().document.getElementById('test');
expect(container.style.display).to.equal('none');
// Chrome never collapses the element while Firefox
// does so we don't test dimensions here.
it("is reported in the parent window", function(done){
window.onerror = function (message) {
// Need to manually pass failed exceptions to the
// callback since we have overriden the default
// error handler for the test case.
try {
expect(message).to.equal('Uncaught fixture error: boom');
return done();
} catch (error) {
return done(error);
}
};
fixtures.set('<scr' + 'ipt>throw new Error("boom")</scr' + 'ipt>');
});
});
});
Expand Down

0 comments on commit 03160e6

Please sign in to comment.