Merge pull request #151 from acdha/overhauled-ajax-error-reporting

Overhauled AJAX error reporting
This commit is contained in:
iangilman 2013-07-03 09:56:07 -07:00
commit 850aa14802
12 changed files with 399 additions and 175 deletions

View File

@ -882,47 +882,49 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){
/** /**
* Wraps the given element in a nest of divs so that the element can * Wraps the given element in a nest of divs so that the element can
* be easily centered. * be easily centered using CSS tables
* @function * @function
* @name OpenSeadragon.makeCenteredNode * @name OpenSeadragon.makeCenteredNode
* @param {Element|String} element * @param {Element|String} element
* @returns {Element} * @returns {Element} outermost wrapper element
*/ */
makeCenteredNode: function( element ) { makeCenteredNode: function( element ) {
// Convert a possible ID to an actual HTMLElement
var div = $.makeNeutralElement( "div" ),
html = [],
innerDiv,
innerDivs;
element = $.getElement( element ); element = $.getElement( element );
//TODO: I dont understand the use of # inside the style attributes /*
// below. Invetigate the results of the constructed html in CSS tables require you to have a display:table/row/cell hierarchy so we need to create
// the browser and clean up the mark-up to make this clearer. three nested wrapper divs:
html.push('<div style="display:table; height:100%; width:100%;'); */
html.push('border:none; margin:0px; padding:0px;'); // neutralizing
html.push('#position:relative; overflow:hidden; text-align:left;">');
html.push('<div style="#position:absolute; #top:50%; width:100%; ');
html.push('border:none; margin:0px; padding:0px;'); // neutralizing
html.push('display:table-cell; vertical-align:middle;">');
html.push('<div style="#position:relative; #top:-50%; width:100%; ');
html.push('border:none; margin:0px; padding:0px;'); // neutralizing
html.push('text-align:center;"></div></div></div>');
div.innerHTML = html.join( '' ); var wrappers = [
div = div.firstChild; $.makeNeutralElement( 'div' ),
$.makeNeutralElement( 'div' ),
$.makeNeutralElement( 'div' )
];
innerDiv = div; // It feels like we should be able to pass style dicts to makeNeutralElement:
innerDivs = div.getElementsByTagName( "div" ); $.extend(wrappers[0].style, {
while ( innerDivs.length > 0 ) { display: "table",
innerDiv = innerDivs[ 0 ]; height: "100%",
innerDivs = innerDiv.getElementsByTagName( "div" ); width: "100%"
} });
innerDiv.appendChild( element ); $.extend(wrappers[1].style, {
display: "table-row"
});
return div; $.extend(wrappers[2].style, {
display: "table-cell",
verticalAlign: "middle",
textAlign: "center"
});
wrappers[0].appendChild(wrappers[1]);
wrappers[1].appendChild(wrappers[2]);
wrappers[2].appendChild(element);
return wrappers[0];
}, },

View File

@ -45,7 +45,8 @@ var I18N = {
ImageFormat: "Sorry, we don't support {0}-based Deep Zoom Images.", ImageFormat: "Sorry, we don't support {0}-based Deep Zoom Images.",
Security: "It looks like a security restriction stopped us from " + Security: "It looks like a security restriction stopped us from " +
"loading this Deep Zoom Image.", "loading this Deep Zoom Image.",
Status: "This space unintentionally left blank ({0} {1})." Status: "This space unintentionally left blank ({0} {1}).",
"Open-Failed": "Unable to open {0}: {1}"
}, },
Tooltips: { Tooltips: {
@ -80,7 +81,8 @@ $.extend( $, {
string = container[ props[ i ] ]; string = container[ props[ i ] ];
if ( typeof( string ) != "string" ) { if ( typeof( string ) != "string" ) {
string = ""; $.console.debug( "Untranslated source string:", prop );
string = ""; // FIXME: this breaks gettext()-style convention, which would return source
} }
return string.replace(/\{\d+\}/g, function(capture) { return string.replace(/\{\d+\}/g, function(capture) {

View File

@ -293,6 +293,11 @@ $.TileSource.prototype = {
callback = function( data ){ callback = function( data ){
var $TileSource = $.TileSource.determineType( _this, data, url ); var $TileSource = $.TileSource.determineType( _this, data, url );
if ( !$TileSource ) {
_this.raiseEvent( 'open-failed', { message: "Unable to load TileSource", source: url } );
return;
}
options = $TileSource.prototype.configure.apply( _this, [ data, url ]); options = $TileSource.prototype.configure.apply( _this, [ data, url ]);
readySource = new $TileSource( options ); readySource = new $TileSource( options );
_this.ready = true; _this.ready = true;
@ -315,6 +320,11 @@ $.TileSource.prototype = {
$.makeAjaxRequest( url, function( xhr ) { $.makeAjaxRequest( url, function( xhr ) {
var data = processResponse( xhr ); var data = processResponse( xhr );
callback( data ); callback( data );
}, function ( xhr ) {
_this.raiseEvent( 'open-failed', {
message: "HTTP " + xhr.status + " attempting to load TileSource",
source: url
});
}); });
} }
@ -458,6 +468,8 @@ $.TileSource.determineType = function( tileSource, data, url ){
return OpenSeadragon[ property ]; return OpenSeadragon[ property ];
} }
} }
$.console.error( "No TileSource was able to open %s %s", url, data );
}; };

View File

@ -171,6 +171,12 @@ $.Viewer = function( options ) {
//Inherit some behaviors and properties //Inherit some behaviors and properties
$.EventHandler.call( this ); $.EventHandler.call( this );
this.addHandler( 'open-failed', function (source, args) {
var msg = $.getString( "Errors.Open-Failed", args.source, args.message);
_this._showMessage( msg );
});
$.ControlDock.call( this, options ); $.ControlDock.call( this, options );
//Deal with tile sources //Deal with tile sources
@ -417,6 +423,8 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
$TileSource, $TileSource,
options; options;
_this._hideMessage();
//allow plain xml strings or json strings to be parsed here //allow plain xml strings or json strings to be parsed here
if( $.type( tileSource ) == 'string' ){ if( $.type( tileSource ) == 'string' ){
if( tileSource.match(/\s*<.*/) ){ if( tileSource.match(/\s*<.*/) ){
@ -433,6 +441,9 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
tileSource = new $.TileSource( tileSource, function( readySource ){ tileSource = new $.TileSource( tileSource, function( readySource ){
openTileSource( _this, readySource ); openTileSource( _this, readySource );
}); });
tileSource.addHandler( 'open-failed', function ( name, args ) {
_this.raiseEvent( 'open-failed', args );
});
} else if ( $.isPlainObject( tileSource ) || tileSource.nodeType ){ } else if ( $.isPlainObject( tileSource ) || tileSource.nodeType ){
if( $.isFunction( tileSource.getTileUrl ) ){ if( $.isFunction( tileSource.getTileUrl ) ){
@ -443,6 +454,13 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
} else { } else {
//inline configuration //inline configuration
$TileSource = $.TileSource.determineType( _this, tileSource ); $TileSource = $.TileSource.determineType( _this, tileSource );
if ( !$TileSource ) {
_this.raiseEvent( 'open-failed', {
message: "Unable to load TileSource",
source: tileSource
});
return;
}
options = $TileSource.prototype.configure.apply( _this, [ tileSource ]); options = $TileSource.prototype.configure.apply( _this, [ tileSource ]);
readySource = new $TileSource( options ); readySource = new $TileSource( options );
openTileSource( _this, readySource ); openTileSource( _this, readySource );
@ -1054,8 +1072,39 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, $.ControlDock.prototype,
this.referenceStrip.setFocus( page ); this.referenceStrip.setFocus( page );
} }
return this; return this;
} },
/**
* Display a message in the viewport
* @function
* @private
* @param {String} text message
*/
_showMessage: function ( message ) {
this._hideMessage();
var div = $.makeNeutralElement( "div" );
div.appendChild( document.createTextNode( message ) );
this.messageDiv = $.makeCenteredNode( div );
$.addClass(this.messageDiv, "openseadragon-message");
this.container.appendChild( this.messageDiv );
},
/**
* Hide any currently displayed viewport message
* @function
* @private
*/
_hideMessage: function () {
var div = this.messageDiv;
if (div) {
div.parentNode.removeChild(div);
delete this.messageDiv;
}
}
}); });
/** /**

View File

@ -1,23 +1,31 @@
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util */ /* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
(function() { (function() {
var viewer;
module('Basic'); module('Basic', {
setup: function () {
var example = $('<div id="example"></div>').appendTo("#qunit-fixture");
// TODO: Test drag testLog.reset();
var viewer = null;
// ----------
asyncTest('Open', function() {
$(document).ready(function() {
viewer = OpenSeadragon({ viewer = OpenSeadragon({
id: 'example', id: 'example',
prefixUrl: '/build/openseadragon/images/', prefixUrl: '/build/openseadragon/images/',
tileSources: '/test/data/testpattern.dzi',
springStiffness: 100 // Faster animation = faster tests springStiffness: 100 // Faster animation = faster tests
}); });
},
teardown: function () {
if (viewer && viewer.close) {
viewer.close();
}
viewer = null;
}
});
// ----------
asyncTest('Open', function() {
ok(viewer, 'Viewer exists'); ok(viewer, 'Viewer exists');
var openHandler = function(eventSender, eventData) { var openHandler = function(eventSender, eventData) {
@ -32,12 +40,36 @@
}; };
viewer.addHandler('open', openHandler); viewer.addHandler('open', openHandler);
viewer.open('/test/data/testpattern.dzi');
}); });
asyncTest('Open Error Handling', function() {
ok(viewer, 'Viewer exists');
viewer.addHandler('open', function(eventSender, eventData) {
ok(false, "The open event should not fire for failed opens");
start();
});
viewer.addHandler('open-failed', function(eventSender, eventData) {
ok(true, "The open-failed event should be fired when the source 404s");
equal($(".openseadragon-message").length, 1, "Open failures should display a message");
ok(testLog.log.contains('["AJAX request returned %s: %s",404,"/test/data/not-a-real-file"]'),
"AJAX failures should be logged to the console");
start();
});
viewer.open('/test/data/not-a-real-file');
}); });
// ---------- // ----------
asyncTest('Zoom', function() { asyncTest('Zoom', function() {
viewer.addHandler("open", function () {
var viewport = viewer.viewport; var viewport = viewer.viewport;
equal(viewport.getZoom(), 1, 'We start out unzoomed'); equal(viewport.getZoom(), 1, 'We start out unzoomed');
var zoomHandler = function() { var zoomHandler = function() {
@ -49,11 +81,15 @@
viewer.addHandler('animationfinish', zoomHandler); viewer.addHandler('animationfinish', zoomHandler);
viewport.zoomTo(2); viewport.zoomTo(2);
}); });
viewer.open('/test/data/testpattern.dzi');
});
// ---------- // ----------
asyncTest('Pan', function() { asyncTest('Pan', function() {
var viewport = viewer.viewport; viewer.addHandler("open", function () {
var center = viewport.getCenter(); var viewport = viewer.viewport,
center = viewport.getCenter();
ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned'); ok(center.x === 0.5 && center.y === 0.5, 'We start out unpanned');
var panHandler = function() { var panHandler = function() {
@ -67,10 +103,24 @@
viewport.panTo(new OpenSeadragon.Point(0.1, 0.1)); viewport.panTo(new OpenSeadragon.Point(0.1, 0.1));
}); });
viewer.open('/test/data/testpattern.dzi');
});
// ---------- // ----------
asyncTest('Home', function() { asyncTest('Home', function() {
// Test setup:
function opener() {
var viewport = viewer.viewport; var viewport = viewer.viewport;
var center = viewport.getCenter(); viewport.panTo(new OpenSeadragon.Point(0.1, 0.1));
viewport.zoomTo(2);
}
function stage1() {
var viewport = viewer.viewport,
center = viewport.getCenter();
viewer.removeHandler('animationfinish', stage1);
ok(center.x !== 0.5 && center.y !== 0.5, 'We start out panned'); ok(center.x !== 0.5 && center.y !== 0.5, 'We start out panned');
notEqual(viewport.getZoom(), 1, 'We start out zoomed'); notEqual(viewport.getZoom(), 1, 'We start out zoomed');
@ -84,10 +134,17 @@
viewer.addHandler('animationfinish', homeHandler); viewer.addHandler('animationfinish', homeHandler);
viewport.goHome(true); viewport.goHome(true);
}
viewer.addHandler("open", opener);
viewer.addHandler("animationfinish", stage1);
viewer.open('/test/data/testpattern.dzi');
}); });
// ---------- // ----------
asyncTest('Click', function() { asyncTest('Click', function() {
viewer.addHandler("open", function () {
var viewport = viewer.viewport, var viewport = viewer.viewport,
center = viewport.getCenter(); center = viewport.getCenter();
@ -106,8 +163,12 @@
Util.simulateViewerClick(viewer, 0.25, 0.25); Util.simulateViewerClick(viewer, 0.25, 0.25);
}); });
viewer.open('/test/data/testpattern.dzi');
});
// ---------- // ----------
test('Fullscreen', function() { asyncTest('Fullscreen', function() {
viewer.addHandler("open", function () {
ok(!viewer.isFullPage(), 'Started out not fullpage'); ok(!viewer.isFullPage(), 'Started out not fullpage');
ok(!$(viewer.element).hasClass('fullpage'), ok(!$(viewer.element).hasClass('fullpage'),
'No fullpage class on div'); 'No fullpage class on div');
@ -121,14 +182,18 @@
ok(!viewer.isFullPage(), 'Disabled fullpage'); ok(!viewer.isFullPage(), 'Disabled fullpage');
ok(!$(viewer.element).hasClass('fullpage'), ok(!$(viewer.element).hasClass('fullpage'),
'Fullpage class removed from div'); 'Fullpage class removed from div');
start();
});
viewer.open('/test/data/testpattern.dzi');
}); });
// ---------- // ----------
asyncTest('Close', function() { asyncTest('Close', function() {
viewer.addHandler("open", function () {
var closeHandler = function() { var closeHandler = function() {
viewer.removeHandler('close', closeHandler); viewer.removeHandler('close', closeHandler);
ok(!viewer.source, 'no source'); ok(!viewer.source, 'no source');
$('#example').empty();
ok(true, 'Close event was sent'); ok(true, 'Close event was sent');
ok(!viewer._updateRequestId, 'timer is off'); ok(!viewer._updateRequestId, 'timer is off');
setTimeout(function() { setTimeout(function() {
@ -140,5 +205,7 @@
viewer.addHandler('close', closeHandler); viewer.addHandler('close', closeHandler);
viewer.close(); viewer.close();
}); });
viewer.open('/test/data/testpattern.dzi');
});
})(); })();

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html> <html>
<head> <head>
<title>OpenSeadragon Basic Demo</title> <title>OpenSeadragon Basic Demo</title>

View File

@ -3,7 +3,13 @@
// This module tests whether our various file formats can be opened. // This module tests whether our various file formats can be opened.
// TODO: Add more file formats (with corresponding test data). // TODO: Add more file formats (with corresponding test data).
module('Formats'); module('Formats', {
setup: function () {
var example = document.createElement("div");
example.id = "example";
document.getElementById("qunit-fixture").appendChild(example);
}
});
var viewer = null; var viewer = null;

View File

@ -1,3 +1,5 @@
/* global QUnit, module, Util, $, console, test, asyncTest, start, ok, equal */
QUnit.config.autostart = false; QUnit.config.autostart = false;
(function () { (function () {
@ -15,13 +17,17 @@ QUnit.config.autostart = false;
module("navigator", { module("navigator", {
setup: function () { setup: function () {
Util.resetDom(); Util.initializeTestDOM();
resetTestVariables(); resetTestVariables();
$(document).scrollTop(0); $(document).scrollTop(0);
$(document).scrollLeft(0); $(document).scrollLeft(0);
}, },
teardown: function () { teardown: function () {
Util.resetDom(); // jQuery UI creates its controls outside the normal DOM hierarchy which QUnit cleans up:
if ($('#exampleNavigator').is(':ui-dialog')) {
$('#exampleNavigator').dialog('destroy');
}
resetTestVariables(); resetTestVariables();
} }
}); });
@ -31,7 +37,7 @@ QUnit.config.autostart = false;
}); });
var resetTestVariables = function () { var resetTestVariables = function () {
if (viewer != null) { if (viewer) {
viewer.close(); viewer.close();
} }
displayRegion = null; displayRegion = null;
@ -125,11 +131,11 @@ QUnit.config.autostart = false;
viewerAndNavigatorDisplayReady = viewer.drawer !== null && viewerAndNavigatorDisplayReady = viewer.drawer !== null &&
!viewer.drawer.needsUpdate() && !viewer.drawer.needsUpdate() &&
currentDisplayWidth > 0 && currentDisplayWidth > 0 &&
Util.equalsWithVariance(lastDisplayRegionLeft, currentDisplayRegionLeft, .0001) && Util.equalsWithVariance(lastDisplayRegionLeft, currentDisplayRegionLeft, 0.0001) &&
Util.equalsWithVariance(lastDisplayWidth, currentDisplayWidth, .0001) && Util.equalsWithVariance(lastDisplayWidth, currentDisplayWidth, 0.0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).x, viewer.viewport.getBounds().x, .0001) && Util.equalsWithVariance(viewer.viewport.getBounds(true).x, viewer.viewport.getBounds().x, 0.0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).y, viewer.viewport.getBounds().y, .0001) && Util.equalsWithVariance(viewer.viewport.getBounds(true).y, viewer.viewport.getBounds().y, 0.0001) &&
Util.equalsWithVariance(viewer.viewport.getBounds(true).width, viewer.viewport.getBounds().width, .0001); Util.equalsWithVariance(viewer.viewport.getBounds(true).width, viewer.viewport.getBounds().width, 0.0001);
} }
catch (err) { catch (err) {
//Ignore. Subsequent code will try again shortly //Ignore. Subsequent code will try again shortly
@ -138,7 +144,7 @@ QUnit.config.autostart = false;
count++; count++;
setTimeout(function () { setTimeout(function () {
waitForViewer(handler, count, currentDisplayRegionLeft, currentDisplayWidth); waitForViewer(handler, count, currentDisplayRegionLeft, currentDisplayWidth);
}, 100) }, 100);
} }
else { else {
if (count === 40) { if (count === 40) {
@ -201,21 +207,21 @@ QUnit.config.autostart = false;
expecteYCoordinate = 1 / viewer.source.aspectRatio - viewer.viewport.getBounds().height; expecteYCoordinate = 1 / viewer.source.aspectRatio - viewer.viewport.getBounds().height;
} }
if (viewer.viewport.getBounds().width < 1) { if (viewer.viewport.getBounds().width < 1) {
Util.assessNumericValue(expectedXCoordinate, viewer.viewport.getBounds().x, .04, ' Viewer at ' + theContentCorner + ', x coord'); Util.assessNumericValue(expectedXCoordinate, viewer.viewport.getBounds().x, 0.04, ' Viewer at ' + theContentCorner + ', x coord');
} }
if (viewer.viewport.getBounds().height < 1 / viewer.source.aspectRatio) { if (viewer.viewport.getBounds().height < 1 / viewer.source.aspectRatio) {
Util.assessNumericValue(expecteYCoordinate, viewer.viewport.getBounds().y, .04, ' Viewer at ' + theContentCorner + ', y coord'); Util.assessNumericValue(expecteYCoordinate, viewer.viewport.getBounds().y, 0.04, ' Viewer at ' + theContentCorner + ', y coord');
}
} }
}; };
};
var assessViewerInCenter = function () { var assessViewerInCenter = function () {
var yPositionVariance = .04; var yPositionVariance = 0.04;
if (viewer.source.aspectRatio < 1) { if (viewer.source.aspectRatio < 1) {
yPositionVariance = yPositionVariance / viewer.source.aspectRatio; yPositionVariance = yPositionVariance / viewer.source.aspectRatio;
} }
Util.assessNumericValue(1 / viewer.source.aspectRatio / 2, viewer.viewport.getCenter().y, yPositionVariance, ' Viewer at center, y coord'); Util.assessNumericValue(1 / viewer.source.aspectRatio / 2, viewer.viewport.getCenter().y, yPositionVariance, ' Viewer at center, y coord');
Util.assessNumericValue(.5, viewer.viewport.getCenter().x, .4, ' Viewer at center, x coord'); Util.assessNumericValue(0.5, viewer.viewport.getCenter().x, 0.4, ' Viewer at center, x coord');
}; };
var clickOnNavigator = function (theContentCorner) { var clickOnNavigator = function (theContentCorner) {
@ -239,7 +245,7 @@ QUnit.config.autostart = false;
yPos = contentStartFromTop + displayRegionHeight; yPos = contentStartFromTop + displayRegionHeight;
} }
simulateNavigatorClick(viewer.navigator, xPos, yPos); simulateNavigatorClick(viewer.navigator, xPos, yPos);
} };
}; };
var dragNavigatorBackToCenter = function () { var dragNavigatorBackToCenter = function () {
@ -354,11 +360,12 @@ QUnit.config.autostart = false;
clientX:1, clientX:1,
clientY:1 clientY:1
}; };
mainViewerElement.simulate('blur', event);
$("#" + seadragonProperties.id).simulate('blur', event);
if (testProperties.expectedAutoFade) { if (testProperties.expectedAutoFade) {
setTimeout(assessAutoFadeTriggered,autoFadeWaitTime); setTimeout(assessAutoFadeTriggered,autoFadeWaitTime);
} } else {
else {
setTimeout(assessAutoFadeDisabled,autoFadeWaitTime); setTimeout(assessAutoFadeDisabled,autoFadeWaitTime);
} }
} }

View File

@ -1,17 +1,33 @@
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog */
(function() { (function() {
module("strings"); module("strings", {
setup: function () {
testLog.reset();
}
});
test("getSubString", function() { test("getSubString", function() {
equal(OpenSeadragon.getString("Errors.Dzi"), equal(OpenSeadragon.getString("Errors.Dzi"),
"Hmm, this doesn't appear to be a valid Deep Zoom Image.", "Hmm, this doesn't appear to be a valid Deep Zoom Image.",
"Read sub-string"); "Read sub-string");
}); });
test("getStringWithPlaceholders", function() {
equal(OpenSeadragon.getString("Errors.Open-Failed", "foo", "bar"),
"Unable to open foo: bar",
"String placeholder replacement");
});
test("getInvalidString", function() { test("getInvalidString", function() {
equal(OpenSeadragon.getString("Greeting"), "", equal(OpenSeadragon.getString("Greeting"), "", "Handled unset string key");
"Handled unset string key"); ok(testLog.debug.contains('["Untranslated source string:","Greeting"]'),
equal(OpenSeadragon.getString("Errors"), "", 'Invalid string keys are logged');
"Handled requesting parent key");
equal(OpenSeadragon.getString("Errors"), "", "Handled requesting parent key");
ok(testLog.debug.contains('["Untranslated source string:","Errors"]'),
'Invalid string parent keys are logged');
}); });
test("setString", function() { test("setString", function() {

View File

@ -10,12 +10,6 @@
<body> <body>
<div id="qunit"></div> <div id="qunit"></div>
<div id="qunit-fixture"></div> <div id="qunit-fixture"></div>
<div>
<div id="example"></div>
<div id="exampleNavigator"></div>
</div>
<div id="wideexample"></div>
<div id="tallexample"></div>
<script src="/node_modules/grunt-contrib-qunit/test/libs/qunit.js"></script> <script src="/node_modules/grunt-contrib-qunit/test/libs/qunit.js"></script>
<script src="/test/lib/jquery-1.9.1.min.js"></script> <script src="/test/lib/jquery-1.9.1.min.js"></script>
<script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script> <script src="/test/lib/jquery-ui-1.10.2/js/jquery-ui-1.10.2.min.js"></script>

View File

@ -1,3 +1,5 @@
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util */
(function() { (function() {
// ---------- // ----------
@ -30,16 +32,11 @@
.simulate('mouseup', event); .simulate('mouseup', event);
}, },
resetDom: function () { initializeTestDOM: function () {
if ($('#exampleNavigator').is(':ui-dialog')) { $("#qunit-fixture")
$('#exampleNavigator').dialog('destroy'); .append('<div><div id="example"></div><div id="exampleNavigator"></div></div>')
} .append('<div id="wideexample"></div>')
$("#exampleNavigator").remove(); .append('<div id="tallexample"></div>');
$(".navigator").remove();
$("#example").empty();
$("#tallexample").empty();
$("#wideexample").empty();
$("#example").parent().append('<div id="exampleNavigator"></div>');
}, },
equalsWithVariance: function (value1, value2, variance) { equalsWithVariance: function (value1, value2, variance) {
@ -74,5 +71,51 @@
}; };
/*
Test console log capture
1. Only the OpenSeadragon.console logger is touched
2. All log messages are stored in window.testLog in arrays keyed on the logger name (e.g. log,
warning, error, etc.) as JSON-serialized strings to simplify comparisons
3. The captured log arrays have a custom contains() method for ease of testing
4. testLog.reset() will clear all of the message arrays, intended for use in test setup routines
*/
var testConsole = window.testConsole = {},
testLog = window.testLog = {
log: [],
debug: [],
info: [],
warn: [],
error: [],
reset: function () {
for (var i in testLog) {
if (testLog.hasOwnProperty(i) && 'length' in testLog[i] && 'push' in testLog[i]) {
testLog[i].length = 0;
}
}
}
};
for (var i in testLog) {
if (testLog.hasOwnProperty(i) && testLog[i].push) {
testConsole[i] = (function (arr) {
return function () {
var args = Array.prototype.slice.call(arguments, 0); // Coerce to true Array
arr.push(JSON.stringify(args)); // Store as JSON to avoid tedious array-equality tests
};
})(testLog[i]);
testLog[i].contains = function (needle) {
for (var i = 0; i < this.length; i++) {
if (this[i] == needle) {
return true;
}
}
return false;
};
}
}
OpenSeadragon.console = testConsole;
})(); })();

View File

@ -1,3 +1,5 @@
/* global module, asyncTest, $, ok, equal, strictEqual, notEqual, start, test, Util, testLog */
(function() { (function() {
module("utils"); module("utils");
@ -56,10 +58,33 @@
asyncTest("makeAjaxRequest", function() { asyncTest("makeAjaxRequest", function() {
var timeWatcher = Util.timeWatcher(); var timeWatcher = Util.timeWatcher();
OpenSeadragon.makeAjaxRequest('data/testpattern.dzi', function(xhr) { OpenSeadragon.makeAjaxRequest('data/testpattern.dzi',
ok(/deepzoom/.test(xhr.response), 'file loaded'); function(xhr) {
equal(xhr.status, 200, 'Success callback called for HTTP 200');
ok(/deepzoom/.test(xhr.responseText), 'Success function called');
timeWatcher.done(); timeWatcher.done();
},
function(xhr) {
ok(false, 'Error callback should not be called');
timeWatcher.done();
}
);
}); });
asyncTest("makeAjaxRequest for invalid file", function() {
var timeWatcher = Util.timeWatcher();
OpenSeadragon.makeAjaxRequest('not-a-real-dzi-file',
function(xhr) {
ok(false, 'Success function should not be called for errors');
timeWatcher.done();
},
function(xhr) {
equal(xhr.status, 404, 'Error callback called for HTTP 404');
ok(true, 'Error function should be called for errors');
timeWatcher.done();
}
);
}); });
// ---------- // ----------