Add imageinfo, thumbnail info, repoinfo provider

Change-Id: I80ffec39ee6c9e0ea0b37be2fc48315063b5ff8a
Mingle: https://wikimedia.mingle.thoughtworks.com/projects/multimedia/cards/123
This commit is contained in:
Gergő Tisza 2014-01-31 02:03:08 +00:00
parent 9f0641c214
commit 85a37d0e14
13 changed files with 963 additions and 42 deletions

View file

@ -147,6 +147,9 @@ call_user_func( function() {
'mmv.provider.Api.js',
'mmv.provider.ImageUsage.js',
'mmv.provider.GlobalUsage.js',
'mmv.provider.ImageInfo.js',
'mmv.provider.FileRepoInfo.js',
'mmv.provider.ThumbnailInfo.js',
),
'dependencies' => array(

View file

@ -122,8 +122,12 @@ class MultimediaViewerHooks {
'tests/qunit/mmv.testhelpers.js',
'tests/qunit/mmv.test.js',
'tests/qunit/mmv.model.test.js',
'tests/qunit/provider/mmv.provider.Api.test.js',
'tests/qunit/provider/mmv.provider.ImageUsage.test.js',
'tests/qunit/provider/mmv.provider.GlobalUsage.test.js',
'tests/qunit/provider/mmv.provider.ImageInfo.test.js',
'tests/qunit/provider/mmv.provider.FileRepoInfo.test.js',
'tests/qunit/provider/mmv.provider.ThumbnailInfo.test.js',
'tests/qunit/mmv.lightboxinterface.test.js',
'tests/qunit/mmv.ui.description.test.js',
'tests/qunit/mmv.ui.fileUsage.test.js',

View file

@ -29,8 +29,8 @@
* @param {string} descriptionUrl URL to the image description page
* @param {string} repo The repository this image belongs to
* @param {string} lastUploader The last person to upload a version of this image.
* @param {string} lastUploadDateTime The time and date the last upload occurred
* @param {string} originalUploadDateTime The time and date the original upload occurred
* @param {string} uploadDateTime The time and date the last upload occurred
* @param {string} creationDateTime The time and date the original upload occurred
* @param {string} description
* @param {string} source
* @param {string} author

View file

@ -15,8 +15,7 @@
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw ) {
( function ( mw, $ ) {
/**
* @class mw.mmv.provider.Api
* Base class for API-based data providers.
@ -62,6 +61,82 @@
return errorMessage;
};
/**
* @method
* Returns a fixed a title based on the API response.
* The title of the returned file might be different from the requested title, e.g.
* if we used a namespace alias. If that happens the old and new title will be set in
* data.query.normalized; this method creates an updated title based on that.
* @param {mw.Title} title
* @param {Object} data
* @return {mw.Title}
*/
Api.prototype.getNormalizedTitle = function( title, data ) {
if ( data && data.query && data.query.normalized ) {
for ( var normalized = data.query.normalized, length = normalized.length, i = 0; i < length; i++ ) {
if ( normalized[i].from === title.getPrefixedText() ) {
title = new mw.Title( normalized[i].to );
break;
}
}
}
return title;
};
/**
* @method
* Returns a promise with the specified field from the API result.
* This is intended to be used as a .then() callback for action=query APIs.
* @param {string} field
* @param {Object} data
* @return {jQuery.Promise} when successful, the first argument will be the field data,
* when unsuccessful, it will be an error message. The second argument is always
* the full API response.
*/
Api.prototype.getQueryField = function( field, data ) {
if ( data && data.query && data.query[field] ) {
return $.Deferred().resolve( data.query[field], data );
} else {
return $.Deferred().reject( this.getErrorMessage( data ), data );
}
};
/**
* @method
* Returns a promise with the specified page from the API result.
* This is intended to be used as a .then() callback for action=query&prop=(...) APIs.
* @param {mw.Title} title
* @param {Object} data
* @return {jQuery.Promise} when successful, the first argument will be the page data,
* when unsuccessful, it will be an error message. The second argument is always
* the full API response.
*/
Api.prototype.getQueryPage = function( title, data ) {
var pageName, pageData = null;
if ( data && data.query && data.query.pages ) {
title = this.getNormalizedTitle( title, data );
pageName = title.getPrefixedText();
// pages is an associative array indexed by pageid,
// we need to iterate through to find the right page
$.each( data.query.pages, function ( id, page ) {
if ( page.title === pageName ) {
pageData = page;
return false;
}
} );
if ( pageData ) {
return $.Deferred().resolve( pageData, data );
}
}
// If we got to this point either the pages array is missing completely, or we iterated
// through it and the requested page was not found. Neither is supposed to happen
// (if the page simply did not exist, there would still be a record for it).
return $.Deferred().reject( this.getErrorMessage( data ), data );
};
mw.mmv.provider = {};
mw.mmv.provider.Api = Api;
}( mediaWiki ) );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,60 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, oo, $ ) {
/**
* @class mw.mmv.provider.FileRepoInfo
* Gets file repo information.
* @extends mw.mmv.provider.Api
* @inheritdoc
* @param {mw.Api} api
*/
function FileRepoInfo( api ) {
mw.mmv.provider.Api.call( this, api );
}
oo.inheritClass( FileRepoInfo, mw.mmv.provider.Api );
/**
* @method
* Runs an API GET request to get the repo info.
* @return {jQuery.Promise} a promise which resolves to an array of mw.mmv.model.Repo objects.
*/
FileRepoInfo.prototype.get = function() {
var provider = this;
if ( !this.cache['*'] ) {
this.cache['*'] = this.api.get( {
action: 'query',
meta: 'filerepoinfo',
format: 'json'
} ).then( function( data ) {
return provider.getQueryField( 'repos', data );
} ).then( function( reposArray ) {
var reposHash = {};
$.each( reposArray, function ( i, repo ) {
reposHash[repo.name] = mw.mmv.model.Repo.newFromRepoInfo( repo );
} );
return reposHash;
} );
}
return this.cache['*'];
};
mw.mmv.provider.FileRepoInfo = FileRepoInfo;
}( mediaWiki, OO, jQuery ) );

View file

@ -74,27 +74,22 @@
gulimit: this.options.apiLimit,
format: 'json'
} ).then( function( data ) {
return provider.getQueryPage( file, data );
} ).then( function( pageData, data ) {
var pages;
if ( data && data.query && data.query.pages ) {
// pages is an associative array indexed by pageid, turn it into proper array
pages = $.map( data.query.pages, function ( v ) { return v; } );
// the API returns a result for non-existent files as well so pages[0] will always exist
pages = $.map( pages[0].globalusage || {}, function( item ) {
return {
wiki: item.wiki,
page: new mw.Title( item.title, item.ns )
};
} );
return new mw.mmv.model.FileUsage(
file,
mw.mmv.model.FileUsage.Scope.GLOBAL,
pages.slice( 0, provider.options.dataLimit ),
pages.length,
!!( data['query-continue'] && data['query-continue'].globalusage )
);
} else {
return $.Deferred().reject( provider.getErrorMessage( data ) );
}
pages = $.map( pageData.globalusage || {}, function( item ) {
return {
wiki: item.wiki,
page: new mw.Title( item.title, item.ns )
};
} );
return new mw.mmv.model.FileUsage(
file,
mw.mmv.model.FileUsage.Scope.GLOBAL,
pages.slice( 0, provider.options.dataLimit ),
pages.length,
!!( data['query-continue'] && data['query-continue'].globalusage )
);
} );
}

View file

@ -0,0 +1,97 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, oo, $ ) {
/**
* @class mw.mmv.provider.ImageInfo
* Gets file information.
* See https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii
* @extends mw.mmv.provider.Api
* @inheritdoc
* @param {mw.Api} api
*/
function ImageInfo( api ) {
mw.mmv.provider.Api.call( this, api );
}
oo.inheritClass( ImageInfo, mw.mmv.provider.Api );
/**
* List of imageinfo API properties which are needed to construct an Image model.
* @type {string[]}
*/
ImageInfo.prototype.iiprop = [
'timestamp',
'user',
'url',
'size',
'mime',
'mediatype',
'extmetadata'
];
/**
* List of imageinfo extmetadata fields which are needed to construct an Image model.
* @type {string[]}
*/
ImageInfo.prototype.iiextmetadatafilter = [
'DateTime',
'DateTimeOriginal',
'ImageDescription',
'License',
'Credit',
'Artist',
'GPSLatitude',
'GPSLongitude'
];
/**
* @method
* Runs an API GET request to get the image info.
* @param {mw.Title} file
* @return {jQuery.Promise} a promise which resolves to an mw.mmv.model.Image object.
*/
ImageInfo.prototype.get = function( file ) {
var provider = this,
cacheKey = file.getPrefixedDb();
if ( !this.cache[cacheKey] ) {
this.cache[cacheKey] = this.api.get( {
action: 'query',
prop: 'imageinfo',
titles: file.getPrefixedDb(),
iiprop: this.iiprop,
iiextmetadatafilter: this.iiextmetadatafilter,
format: 'json'
} ).then( function( data ) {
return provider.getQueryPage( file, data );
} ).then( function( page ) {
if ( page.imageinfo && page.imageinfo.length ) {
return mw.mmv.model.Image.newFromImageInfo( file, page );
} else if ( page.missing === '' && page.imagerepository === '' ) {
return $.Deferred().reject( 'file does not exist: ' + file.getPrefixedDb() );
} else {
return $.Deferred().reject( 'unknown error' );
}
} );
}
return this.cache[cacheKey];
};
mw.mmv.provider.ImageInfo = ImageInfo;
}( mediaWiki, OO, jQuery ) );

View file

@ -60,24 +60,22 @@
iulimit: this.options.apiLimit,
format: 'json'
} ).then( function( data ) {
return provider.getQueryField( 'imageusage', data );
} ).then( function( imageusage, data ) {
var pages;
if ( data && data.query && data.query.imageusage ) {
pages = $.map( data.query.imageusage, function( item ) {
return {
wiki: null,
page: new mw.Title( item.title, item.ns )
};
} );
return new mw.mmv.model.FileUsage(
file,
mw.mmv.model.FileUsage.Scope.LOCAL,
pages.slice( 0, provider.options.dataLimit ),
pages.length,
!!( data['query-continue'] && data['query-continue'].imageusage )
);
} else {
return $.Deferred().reject( provider.getErrorMessage( data ) );
}
pages = $.map( imageusage, function( item ) {
return {
wiki: null,
page: new mw.Title( item.title, item.ns )
};
} );
return new mw.mmv.model.FileUsage(
file,
mw.mmv.model.FileUsage.Scope.LOCAL,
pages.slice( 0, provider.options.dataLimit ),
pages.length,
!!( data['query-continue'] && data['query-continue'].imageusage )
);
} );
}

View file

@ -0,0 +1,69 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, oo, $ ) {
/**
* @class mw.mmv.provider.ThumbnailInfo
* Gets thumbnail information.
* See https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii
* @extends mw.mmv.provider.Api
* @inheritdoc
* @param {mw.Api} api
*/
function ThumbnailInfo( api ) {
mw.mmv.provider.Api.call( this, api );
}
oo.inheritClass( ThumbnailInfo, mw.mmv.provider.Api );
/**
* @method
* Runs an API GET request to get the thumbnail info.
* @param {mw.Title} file
* @param {number} width thumbnail width
* @return {jQuery.Promise} a promise which resolves to the thumbnail URL
*/
ThumbnailInfo.prototype.get = function( file, width ) {
var provider = this,
cacheKey = file.getPrefixedDb() + '|' + width;
if ( !this.cache[cacheKey] ) {
this.cache[cacheKey] = this.api.get( {
action: 'query',
prop: 'imageinfo',
titles: file.getPrefixedDb(),
iiprop: ['url'],
iiurlwidth: width,
format: 'json'
} ).then( function( data ) {
return provider.getQueryPage( file, data );
} ).then( function( page ) {
if ( page.imageinfo && page.imageinfo[0] ) {
return page.imageinfo[0].thumburl;
} else if ( page.missing === '' && page.imagerepository === '' ) {
return $.Deferred().reject( 'file does not exist: ' + file.getPrefixedDb() );
} else {
return $.Deferred().reject( 'unknown error' );
}
} );
}
return this.cache[cacheKey];
};
mw.mmv.provider.ThumbnailInfo = ThumbnailInfo;
}( mediaWiki, OO, jQuery ) );

View file

@ -0,0 +1,177 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw ) {
QUnit.module( 'mmv.provider.Api', QUnit.newMwEnvironment() );
QUnit.test( 'Api constructor sanity check', 2, function ( assert ) {
var api = { get: function() {} },
options = {},
apiProvider = new mw.mmv.provider.Api( api, options ),
ApiProviderWithNoOptions = new mw.mmv.provider.Api( api );
assert.ok( apiProvider );
assert.ok( ApiProviderWithNoOptions );
} );
QUnit.test( 'getErrorMessage test', 2, function ( assert ) {
var api = { get: function() {} },
apiProvider = new mw.mmv.provider.Api( api ),
errorMessage;
errorMessage = apiProvider.getErrorMessage( {
servedby: 'mw1194',
error: {
code: 'unknown_action',
info: 'Unrecognized value for parameter \'action\': FOO'
}
} );
assert.strictEqual( errorMessage,
'unknown_action: Unrecognized value for parameter \'action\': FOO',
'error message is parsed correctly');
assert.strictEqual( apiProvider.getErrorMessage( {} ), 'unknown error', 'missing error message is handled');
} );
QUnit.test( 'getNormalizedTitle test', 3, function ( assert ) {
var api = { get: function() {} },
apiProvider = new mw.mmv.provider.Api( api ),
title = new mw.Title( 'Image:Stuff.jpg' ),
normalizedTitle;
normalizedTitle = apiProvider.getNormalizedTitle( title, {} );
assert.strictEqual( normalizedTitle, title, 'missing normalization block is handled' );
normalizedTitle = apiProvider.getNormalizedTitle( title, {
query: {
normalized: [
{
from: 'Image:Foo.jpg',
to: 'File:Foo.jpg'
}
]
}
} );
assert.strictEqual( normalizedTitle, title, 'irrelevant normalization info is skipped' );
normalizedTitle = apiProvider.getNormalizedTitle( title, {
query: {
normalized: [
{
from: 'Image:Stuff.jpg',
to: 'File:Stuff.jpg'
}
]
}
} );
assert.strictEqual( normalizedTitle.getPrefixedDb(), 'File:Stuff.jpg', 'normalization happens' );
} );
QUnit.test( 'getQueryField test', 3, function ( assert ) {
var api = { get: function() {} },
apiProvider = new mw.mmv.provider.Api( api ),
data;
data = {
query: {
imageusage: [
{
pageid: 736,
ns: 0,
title: 'Albert Einstein'
}
]
}
};
QUnit.stop();
apiProvider.getQueryField( 'imageusage', data ).then( function ( field ) {
assert.strictEqual( field, data.query.imageusage, 'specified field is found');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryField( 'imageusage', {} ).fail( function () {
assert.ok( true, 'promise rejected when data is missing');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryField( 'imageusage', { data: { query: {} } } ).fail( function () {
assert.ok( true, 'promise rejected when field is missing');
QUnit.start();
} );
} );
QUnit.test( 'getQueryPage test', 6, function ( assert ) {
var api = { get: function() {} },
apiProvider = new mw.mmv.provider.Api( api ),
title = new mw.Title( 'File:Stuff.jpg' ),
titleWithNamespaceAlias = new mw.Title( 'Image:Stuff.jpg' ),
otherTitle = new mw.Title( 'File:Foo.jpg' ),
data;
data = {
normalized: [
{
from: 'Image:Stuff.jpg',
to: 'File:Stuff.jpg'
}
],
query: {
pages: {
'-1': {
title: 'File:Stuff.jpg'
}
}
}
};
QUnit.stop();
apiProvider.getQueryPage( title, data ).then( function ( field ) {
assert.strictEqual( field, data.query.pages['-1'], 'specified page is found');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryPage( titleWithNamespaceAlias, data ).then( function ( field ) {
assert.strictEqual( field, data.query.pages['-1'],
'specified page is found even if its title was normalized');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryPage( otherTitle, {} ).fail( function () {
assert.ok( true, 'promise rejected when page has different title');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryPage( title, {} ).fail( function () {
assert.ok( true, 'promise rejected when data is missing');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryPage( title, { data: { query: {} } } ).fail( function () {
assert.ok( true, 'promise rejected when pages are missing');
QUnit.start();
} );
QUnit.stop();
apiProvider.getQueryPage( title, { data: { query: { pages: {} } } } ).fail( function () {
assert.ok( true, 'promise rejected when pages are empty');
QUnit.start();
} );
} );
}( mediaWiki ) );

View file

@ -0,0 +1,126 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
QUnit.module( 'mmv.provider.FileRepoInfo', QUnit.newMwEnvironment() );
QUnit.test( 'FileRepoInfo constructor sanity check', 1, function ( assert ) {
var api = { get: function() {} },
fileRepoInfoProvider = new mw.mmv.provider.FileRepoInfo( api );
assert.ok( fileRepoInfoProvider );
} );
QUnit.asyncTest( 'FileRepoInfo get test', 14, function ( assert ) {
var apiCallCount = 0,
api = { get: function() {
apiCallCount++;
return $.Deferred().resolve( {
'query': {
'repos': [
{
'name': 'shared',
'displayname': 'Wikimedia Commons',
'rootUrl': '//upload.beta.wmflabs.org/wikipedia/commons',
'local': false,
'url': '//upload.beta.wmflabs.org/wikipedia/commons',
'thumbUrl': '//upload.beta.wmflabs.org/wikipedia/commons/thumb',
'initialCapital': true,
'descBaseUrl': '//commons.wikimedia.beta.wmflabs.org/wiki/File:',
'scriptDirUrl': '//commons.wikimedia.beta.wmflabs.org/w',
'fetchDescription': true,
'favicon': 'http://bits.wikimedia.org/favicon/wikipedia.ico'
},
{
'name': 'wikimediacommons',
'displayname': 'Wikimedia Commons',
'rootUrl': '//upload.beta.wmflabs.org/wikipedia/en',
'local': false,
'url': '//upload.beta.wmflabs.org/wikipedia/en',
'thumbUrl': '//upload.beta.wmflabs.org/wikipedia/en/thumb',
'initialCapital': true,
'scriptDirUrl': 'http://commons.wikimedia.org/w',
'fetchDescription': true,
'descriptionCacheExpiry': 43200,
'apiurl': 'http://commons.wikimedia.org/w/api.php',
'articlepath': '/wiki/$1',
'server': '//commons.wikimedia.org',
'favicon': '//bits.wikimedia.org/favicon/commons.ico'
},
{
'name': 'local',
'displayname': null,
'rootUrl': '//upload.beta.wmflabs.org/wikipedia/en',
'local': true,
'url': '//upload.beta.wmflabs.org/wikipedia/en',
'thumbUrl': '//upload.beta.wmflabs.org/wikipedia/en/thumb',
'initialCapital': true,
'scriptDirUrl': '/w',
'favicon': 'http://bits.wikimedia.org/favicon/wikipedia.ico'
}
]
}
} );
} },
fileRepoInfoProvider = new mw.mmv.provider.FileRepoInfo( api );
fileRepoInfoProvider.get().then( function( repos ) {
assert.strictEqual( repos.shared.displayName,
'Wikimedia Commons', 'displayName is set correctly' );
assert.strictEqual( repos.shared.favIcon,
'http://bits.wikimedia.org/favicon/wikipedia.ico', 'favIcon is set correctly' );
assert.strictEqual( repos.shared.isLocal, false, 'isLocal is set correctly' );
assert.strictEqual( repos.shared.descBaseUrl,
'//commons.wikimedia.beta.wmflabs.org/wiki/File:', 'descBaseUrl is set correctly' );
assert.strictEqual( repos.wikimediacommons.displayName,
'Wikimedia Commons', 'displayName is set correctly' );
assert.strictEqual( repos.wikimediacommons.favIcon,
'//bits.wikimedia.org/favicon/commons.ico', 'favIcon is set correctly' );
assert.strictEqual( repos.wikimediacommons.isLocal, false, 'isLocal is set correctly' );
assert.strictEqual( repos.wikimediacommons.apiUrl,
'http://commons.wikimedia.org/w/api.php', 'apiUrl is set correctly' );
assert.strictEqual( repos.wikimediacommons.server,
'//commons.wikimedia.org', 'server is set correctly' );
assert.strictEqual( repos.wikimediacommons.articlePath,
'/wiki/$1', 'articlePath is set correctly' );
assert.strictEqual( repos.local.displayName, null, 'displayName is set correctly' );
assert.strictEqual( repos.local.favIcon,
'http://bits.wikimedia.org/favicon/wikipedia.ico', 'favIcon is set correctly' );
assert.strictEqual( repos.local.isLocal, true, 'isLocal is set correctly' );
} ).then( function() {
// call the data provider a second time to check caching
return fileRepoInfoProvider.get();
} ).then( function() {
assert.strictEqual( apiCallCount, 1 );
QUnit.start();
} );
} );
QUnit.asyncTest( 'FileRepoInfo fail test', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {} );
} },
fileRepoInfoProvider = new mw.mmv.provider.FileRepoInfo( api );
fileRepoInfoProvider.get().fail( function() {
assert.ok( true, 'promise rejected when no data is returned' );
QUnit.start();
} );
} );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,185 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
QUnit.module( 'mmv.provider.ImageInfo', QUnit.newMwEnvironment() );
QUnit.test( 'ImageInfo constructor sanity check', 1, function ( assert ) {
var api = { get: function() {} },
imageInfoProvider = new mw.mmv.provider.ImageInfo( api );
assert.ok( imageInfoProvider );
} );
QUnit.asyncTest( 'ImageInfo get test', 18, function ( assert ) {
var apiCallCount = 0,
api = { get: function() {
apiCallCount++;
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
ns: 6,
title: 'File:Stuff.jpg',
missing: '',
imagerepository: 'shared',
imageinfo: [
{
timestamp: '2013-08-25T14:41:02Z',
user: 'Dylanbot11',
userid: '3053121',
size: 346684,
width: 720,
height: 1412,
comment: 'User created page with UploadWizard',
url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Stuff.jpg',
descriptionurl: 'https://commons.wikimedia.org/wiki/File:Stuff.jpg',
sha1: 'a1ba23d471f4dad208b71c143e2e105a0e3032db',
metadata: [],
extmetadata: {
License: {
value: 'cc0',
source: 'commons-templates',
hidden: ''
},
GPSLatitude: {
value: '90.000000',
source: 'commons-desc-page'
},
GPSLongitude: {
value: ' 180.000000',
source: 'commons-desc-page'
},
ImageDescription: {
value: 'Wikis stuff',
source: 'commons-desc-page'
},
DateTimeOriginal: {
value: '2013-08-25, 15:38:38',
source: 'commons-desc-page'
},
DateTime: {
value: '2013-08-25T14:41:02Z',
source: 'commons-desc-page'
},
Credit: {
value: 'Wikipedia',
source: 'commons-desc-page',
hidden: ''
},
Artist: {
value: 'Wikimeda',
source: 'commons-desc-page'
}
},
mime: 'image/jpeg',
mediatype: 'BITMAP'
}
]
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
imageInfoProvider = new mw.mmv.provider.ImageInfo( api );
imageInfoProvider.get( file ).then( function( image ) {
assert.strictEqual( image.title.getPrefixedDb(), 'File:Stuff.jpg', 'title is set correctly' );
assert.strictEqual( image.size, 346684, 'size is set correctly' );
assert.strictEqual( image.width, 720, 'width is set correctly' );
assert.strictEqual( image.height, 1412, 'height is set correctly' );
assert.strictEqual( image.mimeType, 'image/jpeg', 'mimeType is set correctly' );
assert.strictEqual( image.url, 'https://upload.wikimedia.org/wikipedia/commons/1/19/Stuff.jpg', 'url is set correctly' );
assert.strictEqual( image.descriptionUrl, 'https://commons.wikimedia.org/wiki/File:Stuff.jpg', 'descriptionUrl is set correctly' );
assert.strictEqual( image.repo, 'shared', 'repo is set correctly' );
assert.strictEqual( image.lastUploader, 'Dylanbot11', 'lastUploader is set correctly' );
assert.strictEqual( image.uploadDateTime, '2013-08-25T14:41:02Z', 'uploadDateTime is set correctly' );
assert.strictEqual( image.creationDateTime, '2013-08-25, 15:38:38', 'creationDateTime is set correctly' );
assert.strictEqual( image.description, 'Wikis stuff', 'description is set correctly' );
assert.strictEqual( image.source, 'Wikipedia', 'source is set correctly' );
assert.strictEqual( image.author, 'Wikimeda', 'author is set correctly' );
assert.strictEqual( image.license, 'cc0', 'license is set correctly' );
assert.strictEqual( image.latitude, 90, 'latitude is set correctly' );
assert.strictEqual( image.longitude, 180, 'longitude is set correctly' );
} ).then( function() {
// call the data provider a second time to check caching
return imageInfoProvider.get( file );
} ).then( function() {
assert.strictEqual( apiCallCount, 1 );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ImageInfo fail test', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
imageInfoProvider = new mw.mmv.provider.ImageInfo( api );
imageInfoProvider.get( file ).fail( function() {
assert.ok( true, 'promise rejected when no data is returned' );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ImageInfo fail test 2', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
title: 'File:Stuff.jpg'
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
imageInfoProvider = new mw.mmv.provider.ImageInfo( api );
imageInfoProvider.get( file ).fail( function() {
assert.ok( true, 'promise rejected when imageinfo is missing' );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ImageInfo missing page test', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
title: 'File:Stuff.jpg',
missing: '',
imagerepository: ''
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
imageInfoProvider = new mw.mmv.provider.ImageInfo( api );
imageInfoProvider.get( file ).fail( function( errorMessage ) {
assert.strictEqual(errorMessage, 'file does not exist: File:Stuff.jpg',
'error message is set correctly for missing file');
QUnit.start();
} );
} );
}( mediaWiki, jQuery ) );

View file

@ -0,0 +1,132 @@
/*
* This file is part of the MediaWiki extension MultimediaViewer.
*
* MultimediaViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MultimediaViewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MultimediaViewer. If not, see <http://www.gnu.org/licenses/>.
*/
( function ( mw, $ ) {
QUnit.module( 'mmv.provider.ThumbnailInfo', QUnit.newMwEnvironment() );
QUnit.test( 'ThumbnailInfo constructor sanity check', 1, function ( assert ) {
var api = { get: function() {} },
thumbnailInfoProvider = new mw.mmv.provider.ThumbnailInfo( api );
assert.ok( thumbnailInfoProvider );
} );
QUnit.asyncTest( 'ThumbnailInfo get test', 4, function ( assert ) {
var apiCallCount = 0,
api = { get: function() {
apiCallCount++;
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
ns: 6,
title: 'File:Stuff.jpg',
missing: '',
imagerepository: 'shared',
imageinfo: [
{
thumburl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Stuff.jpg/51px-Stuff.jpg',
thumbwidth: 100,
thumbheight: 200,
url: 'https://upload.wikimedia.org/wikipedia/commons/1/19/Stuff.jpg',
descriptionurl: 'https://commons.wikimedia.org/wiki/File:Stuff.jpg'
}
]
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
thumbnailInfoProvider = new mw.mmv.provider.ThumbnailInfo( api );
thumbnailInfoProvider.get( file, 100 ).then( function( thumnailUrl ) {
assert.strictEqual( thumnailUrl,
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Stuff.jpg/51px-Stuff.jpg',
'URL is set correctly' );
} ).then( function() {
assert.strictEqual( apiCallCount, 1 );
// call the data provider a second time to check caching
return thumbnailInfoProvider.get( file, 100 );
} ).then( function() {
assert.strictEqual( apiCallCount, 1 );
// call a third time with different size to check caching
return thumbnailInfoProvider.get( file, 110 );
} ).then( function() {
assert.strictEqual( apiCallCount, 2 );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ThumbnailInfo fail test', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
thumbnailInfoProvider = new mw.mmv.provider.ThumbnailInfo( api );
thumbnailInfoProvider.get( file, 100 ).fail( function() {
assert.ok( true, 'promise rejected when no data is returned' );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ThumbnailInfo fail test 2', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
title: 'File:Stuff.jpg'
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
thumbnailInfoProvider = new mw.mmv.provider.ThumbnailInfo( api );
thumbnailInfoProvider.get( file, 100 ).fail( function() {
assert.ok( true, 'promise rejected when imageinfo is missing' );
QUnit.start();
} );
} );
QUnit.asyncTest( 'ThumbnailInfo missing page test', 1, function ( assert ) {
var api = { get: function() {
return $.Deferred().resolve( {
query: {
pages: {
'-1': {
title: 'File:Stuff.jpg',
missing: '',
imagerepository: ''
}
}
}
} );
} },
file = new mw.Title( 'File:Stuff.jpg' ),
thumbnailInfoProvider = new mw.mmv.provider.ThumbnailInfo( api );
thumbnailInfoProvider.get( file ).fail( function( errorMessage ) {
assert.strictEqual(errorMessage, 'file does not exist: File:Stuff.jpg',
'error message is set correctly for missing file');
QUnit.start();
} );
} );
}( mediaWiki, jQuery ) );