2014-04-14 18:32:30 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the MediaWiki extension MediaViewer.
|
|
|
|
*
|
|
|
|
* MediaViewer 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.
|
|
|
|
*
|
|
|
|
* MediaViewer 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 MediaViewer. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2018-11-12 16:33:24 +00:00
|
|
|
( function () {
|
2014-04-14 18:32:30 +00:00
|
|
|
QUnit.module( 'mmv.routing.Router', QUnit.newMwEnvironment() );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'Constructor sanity checks', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var router;
|
|
|
|
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
assert.ok( router, 'Router created successfully' );
|
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'isMediaViewerHash()', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var router = new mw.mmv.routing.Router();
|
|
|
|
|
2018-06-06 18:23:25 +00:00
|
|
|
assert.strictEqual( router.isMediaViewerHash( 'mediaviewer/foo' ), true, 'Legacy hash' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '#mediaviewer/foo' ), true, 'Legacy hash with #' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( 'mediaviewer' ), true, 'Bare legacy hash' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '#mediaviewer' ), true, 'Bare legacy hash with #' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '/media/foo' ), true, 'Normal hash' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '#/media/foo' ), true, 'Normal hash with #' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '/media' ), true, 'Bare hash' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '#/media' ), true, 'Bare hash with #' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( 'foo/media' ), false, 'Foreign hash' );
|
|
|
|
assert.strictEqual( router.isMediaViewerHash( '' ), false, 'Empty hash' );
|
2014-04-14 18:32:30 +00:00
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'createHash()/parseHash()', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var route, parsedRoute, hash, title,
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
route = new mw.mmv.routing.MainFileRoute();
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.deepEqual( parsedRoute, route, 'Bare hash' );
|
|
|
|
|
|
|
|
title = new mw.Title( 'File:Foo.png' );
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Normal hash' );
|
|
|
|
assert.ok( hash.match( /File:Foo.png/ ), 'Simple filenames remain readable' );
|
|
|
|
|
|
|
|
title = new mw.Title( 'File:Foo.png' );
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
2016-07-18 13:49:27 +00:00
|
|
|
assert.notEqual( hash[ 0 ], '#', 'Leading # is not included in the returned hash' );
|
2014-04-14 18:32:30 +00:00
|
|
|
parsedRoute = router.parseHash( '#' + hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Leading # is accepted when parsing a hash' );
|
|
|
|
|
|
|
|
title = new mw.Title( 'File:Foo.png' );
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Normal hash' );
|
|
|
|
assert.ok( hash.match( /File:Foo.png/ ), 'Simple filenames remain readable' );
|
|
|
|
|
|
|
|
title = new mw.Title( 'File:Foo/bar.png' );
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Filename with /' );
|
2018-06-06 18:23:25 +00:00
|
|
|
assert.notOk( hash.match( 'Foo/bar' ), '/ is encoded' );
|
2014-04-14 18:32:30 +00:00
|
|
|
|
|
|
|
title = new mw.Title( 'File:Foo bar.png' );
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Filename with space' );
|
2018-06-06 18:23:25 +00:00
|
|
|
assert.notOk( hash.match( 'Foo bar' ), 'space is replaced...' );
|
2014-04-14 18:32:30 +00:00
|
|
|
assert.ok( hash.match( 'Foo_bar' ), '...with underscore' );
|
|
|
|
|
2015-01-23 12:48:27 +00:00
|
|
|
title = new mw.Title( 'File:看門狗 (遊戲).jpg' );
|
2014-04-14 18:32:30 +00:00
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Unicode filename' );
|
|
|
|
|
|
|
|
title = new mw.Title( 'File:%!"$&\'()*,-./:;=?@\\^_`~+.jpg' );
|
|
|
|
if ( title ) {
|
|
|
|
route = new mw.mmv.routing.ThumbnailRoute( title );
|
|
|
|
hash = router.createHash( route );
|
|
|
|
parsedRoute = router.parseHash( hash );
|
|
|
|
assert.strictEqual( parsedRoute.fileTitle.getPrefixedDb(),
|
|
|
|
title.getPrefixedDb(), 'Special characters' );
|
|
|
|
} else {
|
|
|
|
// mw.Title depends on $wgLegalTitleChars - do not fail test if it is non-standard
|
|
|
|
assert.ok( true, 'Skipped' );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'createHash() error handling', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var router = new mw.mmv.routing.Router();
|
|
|
|
|
2015-01-23 12:48:27 +00:00
|
|
|
assert.ok( mw.mmv.testHelpers.getException( function () { return new mw.mmv.routing.ThumbnailRoute(); } ),
|
2014-04-14 18:32:30 +00:00
|
|
|
'Exception thrown then ThumbnailRoute has no title' );
|
2015-01-23 12:48:27 +00:00
|
|
|
assert.ok( mw.mmv.testHelpers.getException( function () {
|
2014-04-14 18:32:30 +00:00
|
|
|
router.createHash( this.sandbox.createStubInstance( mw.mmv.routing.Route ) );
|
|
|
|
} ), 'Exception thrown for unknown Route subclass' );
|
2015-01-23 12:48:27 +00:00
|
|
|
assert.ok( mw.mmv.testHelpers.getException( function () {
|
2014-04-14 18:32:30 +00:00
|
|
|
router.createHash( {} );
|
|
|
|
} ), 'Exception thrown for non-Route class' );
|
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'parseHash() with invalid hashes', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var router = new mw.mmv.routing.Router();
|
|
|
|
|
2018-06-06 18:23:25 +00:00
|
|
|
assert.notOk( router.parseHash( 'foo' ), 'Non-MMV hash is rejected.' );
|
|
|
|
assert.notOk( router.parseHash( '#foo' ), 'Non-MMV hash is rejected (with #).' );
|
|
|
|
assert.notOk( router.parseHash( '/media/foo/bar' ), 'Invalid MMV hash is rejected.' );
|
|
|
|
assert.notOk( router.parseHash( '#/media/foo/bar' ), 'Invalid MMV hash is rejected (with #).' );
|
2014-04-14 18:32:30 +00:00
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'parseHash() backwards compatibility', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var route,
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
route = router.parseHash( '#mediaviewer/File:Foo bar.png' );
|
|
|
|
assert.strictEqual( route.fileTitle.getPrefixedDb(), 'File:Foo_bar.png',
|
|
|
|
'Old urls (with space) are handled' );
|
|
|
|
|
|
|
|
route = router.parseHash( '#mediaviewer/File:Mexican \'Alien\' Piñata.jpg' );
|
|
|
|
assert.strictEqual( route.fileTitle.getPrefixedDb(), 'File:Mexican_\'Alien\'_Piñata.jpg',
|
|
|
|
'Old urls (without percent-encoding) are handled' );
|
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'createHashedUrl()', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var url,
|
|
|
|
route = new mw.mmv.routing.MainFileRoute(),
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
url = router.createHashedUrl( route, 'http://example.com/' );
|
2015-02-25 14:55:37 +00:00
|
|
|
assert.strictEqual( url, 'http://example.com/#/media', 'Url generation works' );
|
2014-04-14 18:32:30 +00:00
|
|
|
|
|
|
|
url = router.createHashedUrl( route, 'http://example.com/#foo' );
|
2015-02-25 14:55:37 +00:00
|
|
|
assert.strictEqual( url, 'http://example.com/#/media', 'Urls with fragments are handled' );
|
2014-04-14 18:32:30 +00:00
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'parseLocation()', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var location, route,
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
location = { href: 'http://example.com/foo#mediaviewer/File:Foo.png' };
|
|
|
|
route = router.parseLocation( location );
|
|
|
|
assert.strictEqual( route.fileTitle.getPrefixedDb(), 'File:Foo.png', 'Reading location works' );
|
|
|
|
|
2015-02-25 14:55:37 +00:00
|
|
|
location = { href: 'http://example.com/foo#/media/File:Foo.png' };
|
|
|
|
route = router.parseLocation( location );
|
|
|
|
assert.strictEqual( route.fileTitle.getPrefixedDb(), 'File:Foo.png', 'Reading location works' );
|
|
|
|
|
2014-04-14 18:32:30 +00:00
|
|
|
location = { href: 'http://example.com/foo' };
|
|
|
|
route = router.parseLocation( location );
|
2018-06-06 18:23:25 +00:00
|
|
|
assert.notOk( route, 'Reading location without fragment part works' );
|
2014-04-14 18:32:30 +00:00
|
|
|
} );
|
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'parseLocation() with real location', function ( assert ) {
|
2014-04-14 18:32:30 +00:00
|
|
|
var route, title, hash,
|
|
|
|
router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
// mw.Title does not accept % in page names
|
2016-12-14 13:09:10 +00:00
|
|
|
this.sandbox.stub( mw, 'Title', function ( name ) {
|
|
|
|
return {
|
|
|
|
name: name,
|
|
|
|
getMain: function () { return name.replace( /^File:/, '' ); }
|
|
|
|
};
|
|
|
|
} );
|
2014-04-14 18:32:30 +00:00
|
|
|
title = new mw.Title( 'File:%40.png' );
|
|
|
|
hash = router.createHash( new mw.mmv.routing.ThumbnailRoute( title ) );
|
|
|
|
|
|
|
|
window.location.hash = hash;
|
|
|
|
route = router.parseLocation( window.location );
|
2014-08-25 19:00:23 +00:00
|
|
|
assert.strictEqual( route.fileTitle.getMain(), '%40.png',
|
2014-04-14 18:32:30 +00:00
|
|
|
'Reading location set via location.hash works' );
|
|
|
|
|
|
|
|
if ( window.history ) {
|
|
|
|
window.history.pushState( null, null, '#' + hash );
|
|
|
|
route = router.parseLocation( window.location );
|
2014-08-25 19:00:23 +00:00
|
|
|
assert.strictEqual( route.fileTitle.getMain(), '%40.png',
|
2014-04-14 18:32:30 +00:00
|
|
|
'Reading location set via pushState() works' );
|
|
|
|
} else {
|
|
|
|
assert.ok( true, 'Skipped pushState() test, not supported on this browser' );
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset location, might interfere with other tests
|
|
|
|
window.location.hash = '#';
|
|
|
|
} );
|
2015-02-25 14:55:37 +00:00
|
|
|
|
2017-07-25 23:38:21 +00:00
|
|
|
QUnit.test( 'tokenizeHash()', function ( assert ) {
|
2015-02-25 14:55:37 +00:00
|
|
|
var router = new mw.mmv.routing.Router();
|
|
|
|
|
|
|
|
router.legacyPrefix = 'legacy';
|
|
|
|
router.applicationPrefix = 'prefix';
|
|
|
|
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#foo/bar' ), [], 'No known prefix' );
|
|
|
|
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#prefix' ), [ 'prefix' ], 'Current prefix, with #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'prefix' ), [ 'prefix' ], 'Current prefix, without #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#prefix/bar' ), [ 'prefix', 'bar' ], 'Current prefix, with # and element' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'prefix/bar' ), [ 'prefix', 'bar' ], 'Current prefix, with element without #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#prefix/bar/baz' ), [ 'prefix', 'bar', 'baz' ], 'Current prefix, with # and 2 elements' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'prefix/bar/baz' ), [ 'prefix', 'bar', 'baz' ], 'Current prefix, with 2 elements without #' );
|
|
|
|
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#legacy' ), [ 'legacy' ], 'Legacy prefix, with #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'legacy' ), [ 'legacy' ], 'Legacy prefix, without #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#legacy/bar' ), [ 'legacy', 'bar' ], 'Legacy prefix, with # and element' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'legacy/bar' ), [ 'legacy', 'bar' ], 'Legacy prefix, with element without #' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( '#legacy/bar/baz' ), [ 'legacy', 'bar', 'baz' ], 'Legacy prefix, with # and 2 elements' );
|
|
|
|
assert.deepEqual( router.tokenizeHash( 'legacy/bar/baz' ), [ 'legacy', 'bar', 'baz' ], 'Legacy prefix, with 2 elements without #' );
|
|
|
|
|
|
|
|
} );
|
2018-11-12 16:33:24 +00:00
|
|
|
}() );
|