mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/MultimediaViewer
synced 2024-12-18 19:01:47 +00:00
f8fe9c0af3
This removes the thumbnail blurring. The initial page thumbnail is still in place. This too can be slightly improved as sizing up to the MMV frame is done via JS right now, and causes a noticeable change. But we can simply do this with CSS immediately i think. Bug: T71609 Bug: T65504 Change-Id: If2a92689be9ee7ecd64561dc224991f31274d58a
622 lines
25 KiB
JavaScript
622 lines
25 KiB
JavaScript
const { MultimediaViewer } = require( 'mmv' );
|
|
const { getMultimediaViewer } = require( './mmv.testhelpers.js' );
|
|
const { MultimediaViewerBootstrap } = require( 'mmv.bootstrap' );
|
|
|
|
( function () {
|
|
QUnit.module( 'mmv', QUnit.newMwEnvironment( {
|
|
beforeEach: function () {
|
|
// prevent a real "back" navigation from taking place
|
|
this.sandbox.stub( require( 'mediawiki.router' ), 'back' );
|
|
}
|
|
} ) );
|
|
|
|
QUnit.test( 'eachPreloadableLightboxIndex()', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
let expectedIndices;
|
|
let i;
|
|
|
|
viewer.preloadDistance = 3;
|
|
viewer.thumbs = [];
|
|
|
|
// 0..10
|
|
for ( i = 0; i < 11; i++ ) {
|
|
viewer.thumbs.push( { image: false } );
|
|
}
|
|
|
|
viewer.currentIndex = 2;
|
|
i = 0;
|
|
expectedIndices = [ 2, 3, 1, 4, 0, 5 ];
|
|
viewer.eachPreloadableLightboxIndex( function ( index ) {
|
|
assert.strictEqual( index, expectedIndices[ i++ ], 'preload on left edge' );
|
|
} );
|
|
|
|
viewer.currentIndex = 9;
|
|
i = 0;
|
|
expectedIndices = [ 9, 10, 8, 7, 6 ];
|
|
viewer.eachPreloadableLightboxIndex( function ( index ) {
|
|
assert.strictEqual( index, expectedIndices[ i++ ], 'preload on right edge' );
|
|
} );
|
|
} );
|
|
|
|
QUnit.test( 'Progress', function ( assert ) {
|
|
const imageDeferred = $.Deferred();
|
|
const viewer = getMultimediaViewer();
|
|
const fakeImage = {
|
|
filePageTitle: new mw.Title( 'File:Stuff.jpg' )
|
|
};
|
|
// custom clock ensures progress handlers execute in correct sequence
|
|
const clock = this.sandbox.useFakeTimers();
|
|
|
|
viewer.thumbs = [];
|
|
viewer.displayPlaceholderThumbnail = function () {};
|
|
viewer.setImage = function () {};
|
|
viewer.scroll = function () {};
|
|
viewer.preloadFullscreenThumbnail = function () {};
|
|
viewer.fetchSizeIndependentLightboxInfo = () => $.Deferred().resolve( {} );
|
|
viewer.ui = {
|
|
setFileReuseData: function () {},
|
|
setupForLoad: function () {},
|
|
canvas: { set: function () {},
|
|
getCurrentImageWidths: function () {
|
|
return { real: 0 };
|
|
},
|
|
getDimensions: function () {
|
|
return {};
|
|
}
|
|
},
|
|
panel: {
|
|
setImageInfo: function () {},
|
|
scroller: {
|
|
animateMetadataOnce: function () {}
|
|
},
|
|
progressBar: {
|
|
hide: this.sandbox.stub(),
|
|
animateTo: this.sandbox.stub(),
|
|
jumpTo: this.sandbox.stub()
|
|
}
|
|
},
|
|
open: function () {} };
|
|
|
|
viewer.imageProvider.get = () => imageDeferred.promise();
|
|
viewer.imageInfoProvider.get = () => $.Deferred().resolve( {} );
|
|
viewer.thumbnailInfoProvider.get = () => $.Deferred().resolve( {} );
|
|
|
|
// loadImage will call setupProgressBar, which will attach done, fail &
|
|
// progress handlers
|
|
viewer.loadImage( fakeImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.jumpTo.lastCall.calledWith( 0 ), true,
|
|
'Percentage correctly reset by loadImage' );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.firstCall.calledWith( 5 ), true,
|
|
'Percentage correctly animated to 5 by loadImage' );
|
|
|
|
imageDeferred.notify( 'response', 45 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.secondCall.calledWith( 45 ), true,
|
|
'Percentage correctly funneled to panel UI' );
|
|
|
|
imageDeferred.resolve( {}, {} );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.thirdCall.calledWith( 100 ), true,
|
|
'Percentage correctly funneled to panel UI' );
|
|
|
|
clock.restore();
|
|
|
|
viewer.close();
|
|
} );
|
|
|
|
QUnit.test( 'Progress when switching images', function ( assert ) {
|
|
const firstImageDeferred = $.Deferred();
|
|
const secondImageDeferred = $.Deferred();
|
|
const firstImage = {
|
|
index: 1,
|
|
filePageTitle: new mw.Title( 'File:First.jpg' )
|
|
};
|
|
const secondImage = {
|
|
index: 2,
|
|
filePageTitle: new mw.Title( 'File:Second.jpg' )
|
|
};
|
|
const viewer = getMultimediaViewer();
|
|
// custom clock ensures progress handlers execute in correct sequence
|
|
const clock = this.sandbox.useFakeTimers();
|
|
|
|
// animation would keep running, conflict with other tests
|
|
this.sandbox.stub( $.fn, 'animate' ).returnsThis();
|
|
|
|
viewer.thumbs = [];
|
|
viewer.displayPlaceholderThumbnail = function () {};
|
|
viewer.setImage = function () {};
|
|
viewer.scroll = function () {};
|
|
viewer.preloadFullscreenThumbnail = function () {};
|
|
viewer.preloadImagesMetadata = function () {};
|
|
viewer.preloadThumbnails = function () {};
|
|
viewer.fetchSizeIndependentLightboxInfo = () => $.Deferred().resolve( {} );
|
|
viewer.ui = {
|
|
setFileReuseData: function () {},
|
|
setupForLoad: function () {},
|
|
canvas: { set: function () {},
|
|
getCurrentImageWidths: function () {
|
|
return { real: 0 };
|
|
},
|
|
getDimensions: function () {
|
|
return {};
|
|
}
|
|
},
|
|
panel: {
|
|
setImageInfo: function () {},
|
|
scroller: {
|
|
animateMetadataOnce: function () {}
|
|
},
|
|
progressBar: {
|
|
hide: this.sandbox.stub(),
|
|
animateTo: this.sandbox.stub(),
|
|
jumpTo: this.sandbox.stub()
|
|
}
|
|
},
|
|
open: function () {},
|
|
empty: function () {} };
|
|
|
|
viewer.imageInfoProvider.get = () => $.Deferred().resolve( {} );
|
|
viewer.thumbnailInfoProvider.get = () => $.Deferred().resolve( {} );
|
|
|
|
// load some image
|
|
viewer.imageProvider.get = this.sandbox.stub().returns( firstImageDeferred );
|
|
viewer.loadImage( firstImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.jumpTo.getCall( 0 ).calledWith( 0 ), true,
|
|
'Percentage correctly reset for new first image' );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.getCall( 0 ).calledWith( 5 ), true,
|
|
'Percentage correctly animated to 5 for first new image' );
|
|
|
|
// progress on active image
|
|
firstImageDeferred.notify( 'response', 20 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.getCall( 1 ).calledWith( 20 ), true,
|
|
'Percentage correctly animated when active image is loading' );
|
|
|
|
// change to another image
|
|
viewer.imageProvider.get = this.sandbox.stub().returns( secondImageDeferred );
|
|
viewer.loadImage( secondImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.jumpTo.getCall( 1 ).calledWith( 0 ), true,
|
|
'Percentage correctly reset for second new image' );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.getCall( 2 ).calledWith( 5 ), true,
|
|
'Percentage correctly animated to 5 for second new image' );
|
|
|
|
// progress on active image
|
|
secondImageDeferred.notify( 'response', 30 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.getCall( 3 ).calledWith( 30 ), true,
|
|
'Percentage correctly animated when active image is loading' );
|
|
|
|
// progress on inactive image
|
|
firstImageDeferred.notify( 'response', 40 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.callCount, 4,
|
|
'Percentage not animated when inactive image is loading' );
|
|
|
|
// progress on active image
|
|
secondImageDeferred.notify( 'response', 50 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.getCall( 4 ).calledWith( 50 ), true,
|
|
'Percentage correctly ignored inactive image & only animated when active image is loading' );
|
|
|
|
// change back to first image
|
|
viewer.imageProvider.get = this.sandbox.stub().returns( firstImageDeferred );
|
|
viewer.loadImage( firstImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.jumpTo.getCall( 2 ).calledWith( 40 ), true,
|
|
'Percentage jumps to right value when changing images' );
|
|
|
|
secondImageDeferred.resolve( {}, {} );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.hide.called, false,
|
|
'Progress bar not hidden when something finishes in the background' );
|
|
|
|
// change back to second image, which has finished loading
|
|
viewer.imageProvider.get = this.sandbox.stub().returns( secondImageDeferred );
|
|
viewer.loadImage( secondImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.hide.called, true,
|
|
'Progress bar hidden when switching to finished image' );
|
|
|
|
clock.restore();
|
|
|
|
viewer.close();
|
|
} );
|
|
|
|
QUnit.test( 'resetThumbnailStates', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, false, 'Real thumbnail state is correct' );
|
|
|
|
viewer.realThumbnailShown = true;
|
|
|
|
viewer.resetThumbnailStates();
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, false, 'Real thumbnail state is correct' );
|
|
} );
|
|
|
|
QUnit.test( 'Placeholder first, then real thumbnail', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
|
|
viewer.setImage = function () {};
|
|
viewer.ui = { canvas: {
|
|
maybeDisplayPlaceholder: function () {
|
|
}
|
|
} };
|
|
viewer.imageInfoProvider.get = this.sandbox.stub();
|
|
|
|
viewer.displayPlaceholderThumbnail( { originalWidth: 100, originalHeight: 100 }, undefined, undefined );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, false, 'Real thumbnail state is correct' );
|
|
|
|
viewer.displayRealThumbnail( { url: undefined } );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, true, 'Real thumbnail state is correct' );
|
|
} );
|
|
|
|
QUnit.test( 'Placeholder first, then real thumbnail - missing size', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
|
|
viewer.currentIndex = 1;
|
|
viewer.setImage = function () {};
|
|
viewer.ui = { canvas: {
|
|
maybeDisplayPlaceholder: function () {
|
|
}
|
|
} };
|
|
viewer.imageInfoProvider.get = this.sandbox.stub().returns( $.Deferred().resolve( { width: 100, height: 100 } ) );
|
|
|
|
viewer.displayPlaceholderThumbnail( { index: 1 }, undefined, undefined );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, false, 'Real thumbnail state is correct' );
|
|
|
|
viewer.displayRealThumbnail( { url: undefined } );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, true, 'Real thumbnail state is correct' );
|
|
} );
|
|
|
|
QUnit.test( 'Real thumbnail first, then placeholder', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
|
|
viewer.setImage = function () {};
|
|
viewer.ui = {
|
|
showImage: function () {},
|
|
canvas: {}
|
|
};
|
|
|
|
viewer.displayRealThumbnail( { url: undefined } );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, true, 'Real thumbnail state is correct' );
|
|
|
|
viewer.displayPlaceholderThumbnail( {}, undefined, undefined );
|
|
|
|
assert.strictEqual( viewer.realThumbnailShown, true, 'Real thumbnail state is correct' );
|
|
} );
|
|
|
|
QUnit.test( 'New image loaded while another one is loading', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
const firstImageDeferred = $.Deferred();
|
|
const secondImageDeferred = $.Deferred();
|
|
const firstLigthboxInfoDeferred = $.Deferred();
|
|
const secondLigthboxInfoDeferred = $.Deferred();
|
|
const firstImage = {
|
|
filePageTitle: new mw.Title( 'File:Foo.jpg' ),
|
|
index: 0
|
|
};
|
|
const secondImage = {
|
|
filePageTitle: new mw.Title( 'File:Bar.jpg' ),
|
|
index: 1
|
|
};
|
|
// custom clock ensures progress handlers execute in correct sequence
|
|
const clock = this.sandbox.useFakeTimers();
|
|
|
|
viewer.preloadFullscreenThumbnail = function () {};
|
|
viewer.fetchSizeIndependentLightboxInfo = this.sandbox.stub();
|
|
viewer.ui = {
|
|
setFileReuseData: function () {},
|
|
setupForLoad: function () {},
|
|
canvas: {
|
|
set: function () {},
|
|
getCurrentImageWidths: function () {
|
|
return { real: 0 };
|
|
},
|
|
getDimensions: function () {
|
|
return {};
|
|
}
|
|
},
|
|
panel: {
|
|
setImageInfo: this.sandbox.stub(),
|
|
scroller: {
|
|
animateMetadataOnce: function () {}
|
|
},
|
|
progressBar: {
|
|
hide: this.sandbox.stub(),
|
|
animateTo: this.sandbox.stub(),
|
|
jumpTo: this.sandbox.stub()
|
|
},
|
|
empty: function () {}
|
|
},
|
|
open: function () {},
|
|
empty: function () {} };
|
|
viewer.displayRealThumbnail = this.sandbox.stub();
|
|
viewer.eachPreloadableLightboxIndex = function () {};
|
|
viewer.animateMetadataDivOnce = this.sandbox.stub().returns( $.Deferred().reject() );
|
|
viewer.imageProvider.get = this.sandbox.stub();
|
|
viewer.imageInfoProvider.get = () => $.Deferred().reject( {} );
|
|
viewer.thumbnailInfoProvider.get = () => $.Deferred().resolve( {} );
|
|
|
|
viewer.imageProvider.get.returns( firstImageDeferred.promise() );
|
|
viewer.fetchSizeIndependentLightboxInfo.returns( firstLigthboxInfoDeferred.promise() );
|
|
viewer.loadImage( firstImage );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.animateMetadataDivOnce.called, false, 'Metadata of the first image should not be animated' );
|
|
assert.strictEqual( viewer.ui.panel.setImageInfo.called, false, 'Metadata of the first image should not be shown' );
|
|
|
|
viewer.imageProvider.get.returns( secondImageDeferred.promise() );
|
|
viewer.fetchSizeIndependentLightboxInfo.returns( secondLigthboxInfoDeferred.promise() );
|
|
viewer.loadImage( secondImage );
|
|
clock.tick( 10 );
|
|
|
|
viewer.ui.panel.progressBar.animateTo.reset();
|
|
firstImageDeferred.notify( undefined, 45 );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.ui.panel.progressBar.animateTo.reset.called, undefined, 'Progress of the first image should not be shown' );
|
|
|
|
firstImageDeferred.resolve( {}, {} );
|
|
firstLigthboxInfoDeferred.resolve( {} );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.displayRealThumbnail.called, false, 'The first image being done loading should have no effect' );
|
|
|
|
viewer.displayRealThumbnail = this.sandbox.spy( () => viewer.close() );
|
|
secondImageDeferred.resolve( {}, {} );
|
|
secondLigthboxInfoDeferred.resolve( {} );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( viewer.displayRealThumbnail.called, true, 'The second image being done loading should result in the image being shown' );
|
|
|
|
clock.restore();
|
|
} );
|
|
|
|
QUnit.test( 'Events are not trapped after the viewer is closed', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
const $document = $( document );
|
|
const $qf = $( '#qunit-fixture' );
|
|
const eventTypes = [ 'keydown', 'keyup', 'keypress', 'click', 'mousedown', 'mouseup' ];
|
|
const modifiers = [ undefined, 'altKey', 'ctrlKey', 'shiftKey', 'metaKey' ];
|
|
// Events are async, we need to wait for the last event to be caught before ending the test
|
|
const done = assert.async();
|
|
const oldScrollTo = $.scrollTo;
|
|
|
|
assert.expect( 0 );
|
|
|
|
// animation would keep running, conflict with other tests
|
|
this.sandbox.stub( $.fn, 'animate' ).returnsThis();
|
|
|
|
$.scrollTo = function () {
|
|
return { scrollTop: () => {}, on: () => {}, off: () => {} };
|
|
};
|
|
|
|
viewer.setupEventHandlers();
|
|
|
|
viewer.imageProvider.get = () => $.Deferred().reject();
|
|
viewer.imageInfoProvider.get = () => $.Deferred().reject();
|
|
viewer.thumbnailInfoProvider.get = () => $.Deferred().reject();
|
|
viewer.fileRepoInfoProvider.get = () => $.Deferred().reject();
|
|
|
|
viewer.preloadFullscreenThumbnail = function () {};
|
|
viewer.initWithThumbs( [] );
|
|
|
|
viewer.loadImage(
|
|
{
|
|
filePageTitle: new mw.Title( 'File:Stuff.jpg' ),
|
|
thumbnail: new Image( 10, 10 )
|
|
},
|
|
new Image()
|
|
);
|
|
|
|
viewer.ui.$closeButton.trigger( 'click' );
|
|
|
|
function eventHandler( e ) {
|
|
if ( e.isDefaultPrevented() ) {
|
|
assert.true( false, 'Event was incorrectly trapped: ' + e.which );
|
|
}
|
|
|
|
e.preventDefault();
|
|
|
|
// Wait for the last event
|
|
if ( e.which === 32 && e.type === 'mouseup' ) {
|
|
$document.off( '.mmvtest' );
|
|
viewer.cleanupEventHandlers();
|
|
$.scrollTo = oldScrollTo;
|
|
done();
|
|
}
|
|
}
|
|
|
|
for ( let j = 0; j < eventTypes.length; j++ ) {
|
|
$document.on( eventTypes[ j ] + '.mmvtest', eventHandler );
|
|
|
|
eventloop:
|
|
for ( let i = 0; i < 256; i++ ) {
|
|
// Save some time by not testing unlikely values for mouse events
|
|
if ( i > 32 ) {
|
|
switch ( eventTypes[ j ] ) {
|
|
case 'click':
|
|
case 'mousedown':
|
|
case 'mouseup':
|
|
break eventloop;
|
|
}
|
|
}
|
|
|
|
for ( let k = 0; k < modifiers.length; k++ ) {
|
|
const eventParameters = { which: i };
|
|
if ( modifiers[ k ] !== undefined ) {
|
|
eventParameters[ modifiers[ k ] ] = true;
|
|
}
|
|
$qf.trigger( $.Event( eventTypes[ j ], eventParameters ) );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
QUnit.test( 'Refuse to load too-big thumbnails', function ( assert ) {
|
|
let expectedWidth;
|
|
const reuestedWidth = 1000;
|
|
const originalWidth = 50;
|
|
const viewer = getMultimediaViewer();
|
|
|
|
viewer.thumbnailInfoProvider.get = function ( fileTitle, width ) {
|
|
assert.strictEqual( width, expectedWidth );
|
|
return $.Deferred().reject();
|
|
};
|
|
|
|
// non-vector should be capped to original size
|
|
let title = mw.Title.newFromText( 'File:Foobar.png' );
|
|
expectedWidth = originalWidth;
|
|
viewer.fetchThumbnail( title, reuestedWidth, null, originalWidth, 60 );
|
|
|
|
// vector images can be aritrarily large
|
|
title = mw.Title.newFromText( 'File:Foobar.svg' );
|
|
expectedWidth = reuestedWidth;
|
|
viewer.fetchThumbnail( title, reuestedWidth, null, originalWidth, 60 );
|
|
} );
|
|
|
|
QUnit.test( 'fetchThumbnail()', function ( assert ) {
|
|
let guessedThumbnailInfoStub;
|
|
let thumbnailInfoStub;
|
|
let imageStub;
|
|
let promise;
|
|
let useThumbnailGuessing;
|
|
const viewer = new MultimediaViewer( {
|
|
imageQueryParameter: function () {},
|
|
language: function () {},
|
|
recordVirtualViewBeaconURI: function () {},
|
|
extensions: function () {
|
|
return { jpg: 'default' };
|
|
},
|
|
useThumbnailGuessing: () => useThumbnailGuessing
|
|
} );
|
|
const sandbox = this.sandbox;
|
|
const file = new mw.Title( 'File:Copyleft.svg' );
|
|
const sampleURL = 'http://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Copyleft.svg/300px-Copyleft.svg.png';
|
|
const width = 100;
|
|
const originalWidth = 1000;
|
|
const originalHeight = 1000;
|
|
const image = {};
|
|
// custom clock ensures progress handlers execute in correct sequence
|
|
const clock = this.sandbox.useFakeTimers();
|
|
|
|
function setupStubs() {
|
|
guessedThumbnailInfoStub = viewer.guessedThumbnailInfoProvider.get = sandbox.stub();
|
|
thumbnailInfoStub = viewer.thumbnailInfoProvider.get = sandbox.stub();
|
|
imageStub = viewer.imageProvider.get = sandbox.stub();
|
|
}
|
|
|
|
useThumbnailGuessing = true;
|
|
|
|
// When we lack sample URL and original dimensions, the classic provider should be used
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().resolve( { url: 'guessedURL' } ) );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.returns( $.Deferred().resolve( image ) );
|
|
promise = viewer.fetchThumbnail( file, width );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.called, false, 'When we lack sample URL and original dimensions, GuessedThumbnailInfoProvider is not called' );
|
|
assert.strictEqual( thumbnailInfoStub.calledOnce, true, 'When we lack sample URL and original dimensions, ThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( imageStub.calledOnce, true, 'When we lack sample URL and original dimensions, ImageProvider is called once' );
|
|
assert.strictEqual( imageStub.calledWith( 'apiURL' ), true, 'When we lack sample URL and original dimensions, ImageProvider is called with the API url' );
|
|
assert.strictEqual( promise.state(), 'resolved', 'When we lack sample URL and original dimensions, fetchThumbnail resolves' );
|
|
|
|
// When the guesser bails out, the classic provider should be used
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().reject() );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.returns( $.Deferred().resolve( image ) );
|
|
promise = viewer.fetchThumbnail( file, width, sampleURL, originalWidth, originalHeight );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.calledOnce, true, 'When the guesser bails out, GuessedThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( thumbnailInfoStub.calledOnce, true, 'When the guesser bails out, ThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( imageStub.calledOnce, true, 'When the guesser bails out, ImageProvider is called once' );
|
|
assert.strictEqual( imageStub.calledWith( 'apiURL' ), true, 'When the guesser bails out, ImageProvider is called with the API url' );
|
|
assert.strictEqual( promise.state(), 'resolved', 'When the guesser bails out, fetchThumbnail resolves' );
|
|
|
|
// When the guesser returns an URL, that should be used
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().resolve( { url: 'guessedURL' } ) );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.returns( $.Deferred().resolve( image ) );
|
|
promise = viewer.fetchThumbnail( file, width, sampleURL, originalWidth, originalHeight );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.calledOnce, true, 'When the guesser returns an URL, GuessedThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( thumbnailInfoStub.called, false, 'When the guesser returns an URL, ThumbnailInfoProvider is not called' );
|
|
assert.strictEqual( imageStub.calledOnce, true, 'When the guesser returns an URL, ImageProvider is called once' );
|
|
assert.strictEqual( imageStub.calledWith( 'guessedURL' ), true, 'When the guesser returns an URL, ImageProvider is called with the guessed url' );
|
|
assert.strictEqual( promise.state(), 'resolved', 'When the guesser returns an URL, fetchThumbnail resolves' );
|
|
|
|
// When the guesser returns an URL, but that returns 404, image loading should be retried with the classic provider
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().resolve( { url: 'guessedURL' } ) );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.withArgs( 'guessedURL' ).returns( $.Deferred().reject() );
|
|
imageStub.withArgs( 'apiURL' ).returns( $.Deferred().resolve( image ) );
|
|
promise = viewer.fetchThumbnail( file, width, sampleURL, originalWidth, originalHeight );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.calledOnce, true, 'When the guesser returns an URL, but that returns 404, GuessedThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( thumbnailInfoStub.calledOnce, true, 'When the guesser returns an URL, but that returns 404, ThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( imageStub.calledTwice, true, 'When the guesser returns an URL, but that returns 404, ImageProvider is called twice' );
|
|
assert.strictEqual( imageStub.getCall( 0 ).calledWith( 'guessedURL' ), true, 'When the guesser returns an URL, but that returns 404, ImageProvider is called first with the guessed url' );
|
|
assert.strictEqual( imageStub.getCall( 1 ).calledWith( 'apiURL' ), true, 'When the guesser returns an URL, but that returns 404, ImageProvider is called second with the guessed url' );
|
|
assert.strictEqual( promise.state(), 'resolved', 'When the guesser returns an URL, but that returns 404, fetchThumbnail resolves' );
|
|
|
|
// When even the retry fails, fetchThumbnail() should reject
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().resolve( { url: 'guessedURL' } ) );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.withArgs( 'guessedURL' ).returns( $.Deferred().reject() );
|
|
imageStub.withArgs( 'apiURL' ).returns( $.Deferred().reject() );
|
|
promise = viewer.fetchThumbnail( file, width, sampleURL, originalWidth, originalHeight );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.calledOnce, true, 'When even the retry fails, GuessedThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( thumbnailInfoStub.calledOnce, true, 'When even the retry fails, ThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( imageStub.calledTwice, true, 'When even the retry fails, ImageProvider is called twice' );
|
|
assert.strictEqual( imageStub.getCall( 0 ).calledWith( 'guessedURL' ), true, 'When even the retry fails, ImageProvider is called first with the guessed url' );
|
|
assert.strictEqual( imageStub.getCall( 1 ).calledWith( 'apiURL' ), true, 'When even the retry fails, ImageProvider is called second with the guessed url' );
|
|
assert.strictEqual( promise.state(), 'rejected', 'When even the retry fails, fetchThumbnail rejects' );
|
|
|
|
useThumbnailGuessing = false;
|
|
|
|
// When guessing is disabled, the classic provider is used
|
|
setupStubs();
|
|
guessedThumbnailInfoStub.returns( $.Deferred().resolve( { url: 'guessedURL' } ) );
|
|
thumbnailInfoStub.returns( $.Deferred().resolve( { url: 'apiURL' } ) );
|
|
imageStub.returns( $.Deferred().resolve( image ) );
|
|
promise = viewer.fetchThumbnail( file, width );
|
|
clock.tick( 10 );
|
|
assert.strictEqual( guessedThumbnailInfoStub.called, false, 'When guessing is disabled, GuessedThumbnailInfoProvider is not called' );
|
|
assert.strictEqual( thumbnailInfoStub.calledOnce, true, 'When guessing is disabled, ThumbnailInfoProvider is called once' );
|
|
assert.strictEqual( imageStub.calledOnce, true, 'When guessing is disabled, ImageProvider is called once' );
|
|
assert.strictEqual( imageStub.calledWith( 'apiURL' ), true, 'When guessing is disabled, ImageProvider is called with the API url' );
|
|
assert.strictEqual( promise.state(), 'resolved', 'When guessing is disabled, fetchThumbnail resolves' );
|
|
|
|
clock.restore();
|
|
} );
|
|
|
|
QUnit.test( 'document.title', function ( assert ) {
|
|
const viewer = getMultimediaViewer();
|
|
const bootstrap = new MultimediaViewerBootstrap();
|
|
const title = new mw.Title( 'File:This_should_show_up_in_document_title.png' );
|
|
const oldDocumentTitle = document.title;
|
|
|
|
this.sandbox.stub( mw.loader, 'using' ).returns( $.Deferred().resolve( viewer ) );
|
|
viewer.currentImageFileTitle = title;
|
|
bootstrap.setupEventHandlers();
|
|
viewer.setTitle();
|
|
|
|
assert.notStrictEqual( document.title.match( title.getNameText() ), null, 'File name is visible in title' );
|
|
|
|
viewer.close();
|
|
bootstrap.cleanupEventHandlers();
|
|
|
|
assert.strictEqual( document.title, oldDocumentTitle, 'Original title restored after viewer is closed' );
|
|
} );
|
|
}() );
|