2019-02-19 13:09:52 +00:00
|
|
|
import { fromElement, getTitle, isValid } from '../../src/title';
|
|
|
|
|
2017-06-08 10:08:58 +00:00
|
|
|
QUnit.module( 'title#getTitle', {
|
2018-03-14 22:04:59 +00:00
|
|
|
beforeEach() {
|
2017-04-27 17:38:20 +00:00
|
|
|
this.config = new Map();
|
|
|
|
this.config.set( 'wgArticlePath', '/wiki/$1' );
|
|
|
|
|
|
|
|
this.location = global.location = { hostname: 'en.wikipedia.org' };
|
|
|
|
|
2019-10-17 07:37:24 +00:00
|
|
|
mediaWiki.util = {
|
|
|
|
escapeRegExp: this.sandbox.spy( ( str ) => {
|
2017-10-09 14:56:15 +00:00
|
|
|
return str.replace( /([\\{}()|.?*+\-^$[\]])/g, '\\$1' );
|
2017-04-27 17:38:20 +00:00
|
|
|
} )
|
|
|
|
};
|
|
|
|
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri = this.sandbox.stub().throws( 'UNIMPLEMENTED' );
|
2017-04-27 17:38:20 +00:00
|
|
|
},
|
2018-03-14 22:04:59 +00:00
|
|
|
afterEach() {
|
2017-04-27 17:38:20 +00:00
|
|
|
global.location = null;
|
2019-10-17 07:37:24 +00:00
|
|
|
mediaWiki.util = null;
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri = null;
|
2017-04-27 17:38:20 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should return the title of a url with a title query param', function ( assert ) {
|
2018-03-19 19:39:41 +00:00
|
|
|
const href = '/w/index.php?title=Foo';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: this.location.hostname,
|
|
|
|
query: {
|
|
|
|
title: 'Foo'
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
'Foo',
|
|
|
|
'The query title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should return the title of a pretty url if it conforms wgArticlePath', function ( assert ) {
|
2018-03-19 19:39:41 +00:00
|
|
|
const href = '/wiki/Foo';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: this.location.hostname,
|
|
|
|
path: href,
|
|
|
|
query: {}
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
'Foo',
|
|
|
|
'The ASCII title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should return the title of a pretty url properly decoded', function ( assert ) {
|
2018-03-19 19:39:41 +00:00
|
|
|
const href = '/wiki/%E6%B8%AC%E8%A9%A6';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: this.location.hostname,
|
|
|
|
path: href,
|
|
|
|
query: {}
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
'測試',
|
|
|
|
'The UTF-8 title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
|
|
|
|
2019-01-24 10:37:30 +00:00
|
|
|
QUnit.test( 'it should accept urls with fragments', function ( assert ) {
|
|
|
|
let href = '/wiki/Example_1#footnote_1';
|
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
|
|
|
host: this.location.hostname,
|
|
|
|
path: href,
|
|
|
|
query: {},
|
|
|
|
fragment: 'footnote_1'
|
|
|
|
} );
|
|
|
|
|
|
|
|
assert.strictEqual(
|
|
|
|
getTitle( href, this.config ),
|
|
|
|
'Example_1#footnote_1',
|
|
|
|
'It accepts pretty urls with fragments.'
|
|
|
|
);
|
|
|
|
|
|
|
|
href = '/w/index.php?title=Example_2#footnote_2';
|
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
|
|
|
host: this.location.hostname,
|
|
|
|
query: { title: 'Example_2' },
|
|
|
|
fragment: 'footnote_2'
|
|
|
|
} );
|
|
|
|
|
|
|
|
assert.strictEqual(
|
|
|
|
getTitle( href, this.config ),
|
|
|
|
'Example_2#footnote_2',
|
|
|
|
'It accepts title parameter urls with fragments.'
|
|
|
|
);
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should skip pretty urls with invalid % encoded characters', function ( assert ) {
|
|
|
|
const href = '/wiki/100%';
|
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
|
|
|
host: this.location.hostname,
|
|
|
|
path: href,
|
|
|
|
query: {}
|
|
|
|
} );
|
|
|
|
|
|
|
|
assert.strictEqual( getTitle( href, this.config ), undefined );
|
|
|
|
} );
|
|
|
|
|
2017-04-27 17:38:20 +00:00
|
|
|
QUnit.test( 'it should skip urls that mw.Uri cannot parse', function ( assert ) {
|
2018-03-19 19:39:41 +00:00
|
|
|
const href = 'javascript:void(0);'; // eslint-disable-line no-script-url
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).throws(
|
2017-04-27 17:38:20 +00:00
|
|
|
new Error( 'Cannot parse' )
|
|
|
|
);
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
undefined,
|
|
|
|
'No title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should skip urls that are external', function ( assert ) {
|
2018-03-19 19:39:41 +00:00
|
|
|
const href = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: 'www.youtube.com',
|
|
|
|
path: '/watch',
|
|
|
|
query: { v: 'dQw4w9WgXcQ' }
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
undefined,
|
|
|
|
'No title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should skip urls not on article path without one title query param', function ( assert ) {
|
|
|
|
// No params
|
2018-03-15 16:30:11 +00:00
|
|
|
let href = '/Foo';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: this.location.hostname,
|
|
|
|
path: '/Foo',
|
|
|
|
query: {}
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
undefined,
|
|
|
|
'No title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
|
|
|
|
// Multiple query params
|
|
|
|
href = '/Foo?a=1&title=Foo';
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Uri.withArgs( href ).returns( {
|
2017-04-27 17:38:20 +00:00
|
|
|
host: this.location.hostname,
|
|
|
|
path: '/Foo',
|
|
|
|
query: { a: 1, title: 'Foo' }
|
|
|
|
} );
|
|
|
|
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
getTitle( href, this.config ),
|
|
|
|
undefined,
|
|
|
|
'No title is returned.'
|
|
|
|
);
|
2017-04-27 17:38:20 +00:00
|
|
|
} );
|
2017-06-08 10:45:11 +00:00
|
|
|
|
|
|
|
QUnit.module( 'title#isValid', {
|
2018-03-14 22:04:59 +00:00
|
|
|
beforeEach() {
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title = {
|
2017-06-08 10:45:11 +00:00
|
|
|
newFromText: this.sandbox.stub().throws( 'UNIMPLEMENTED' )
|
|
|
|
};
|
|
|
|
},
|
2018-03-14 22:04:59 +00:00
|
|
|
afterEach() {
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title = null;
|
2017-06-08 10:45:11 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
2018-03-14 23:50:09 +00:00
|
|
|
QUnit.test( 'it should return null if the title is empty', ( assert ) => {
|
2018-09-13 13:28:47 +00:00
|
|
|
assert.strictEqual( isValid( '', [] ), null, 'Doesn\'t accept empty titles' );
|
2017-06-08 10:45:11 +00:00
|
|
|
} );
|
|
|
|
|
2018-03-14 23:50:09 +00:00
|
|
|
QUnit.test( 'it should return null if the title can\'t be parsed properly', ( assert ) => {
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title.newFromText.withArgs( 'title' ).returns( null );
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-09-13 13:28:47 +00:00
|
|
|
isValid( 'title', [] ),
|
2018-05-08 19:48:17 +00:00
|
|
|
null,
|
|
|
|
'Doesn\'t accept unparseable titles'
|
|
|
|
);
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title.newFromText.callCount, 1,
|
2018-01-18 18:48:16 +00:00
|
|
|
'mediaWiki.Title.newFromText called for parsing the title' );
|
2017-06-08 10:45:11 +00:00
|
|
|
} );
|
|
|
|
|
2018-03-14 23:50:09 +00:00
|
|
|
QUnit.test( 'it should return null if the title is not from a content namespace', ( assert ) => {
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title.newFromText.withArgs( 'title' ).returns( {
|
2017-06-08 10:45:11 +00:00
|
|
|
namespace: 1
|
|
|
|
} );
|
2018-05-20 12:32:51 +00:00
|
|
|
assert.strictEqual(
|
2018-05-08 19:48:17 +00:00
|
|
|
isValid( 'title', [ 5 ] ),
|
|
|
|
null,
|
|
|
|
'Only content namespace titles are accepted'
|
|
|
|
);
|
2017-06-08 10:45:11 +00:00
|
|
|
} );
|
|
|
|
|
2018-03-14 23:50:09 +00:00
|
|
|
QUnit.test( 'it should return the title object if the title is from a content namespace', ( assert ) => {
|
2018-03-19 19:39:41 +00:00
|
|
|
const mwTitle = {
|
2017-06-08 10:45:11 +00:00
|
|
|
namespace: 3
|
|
|
|
};
|
2018-06-21 15:47:13 +00:00
|
|
|
mediaWiki.Title.newFromText.withArgs( 'title' ).returns( mwTitle );
|
2018-05-08 19:48:17 +00:00
|
|
|
assert.strictEqual(
|
|
|
|
isValid( 'title', [ 1, 3, 5 ] ),
|
|
|
|
mwTitle,
|
|
|
|
'A content namespace title is accepted'
|
|
|
|
);
|
2017-06-08 10:45:11 +00:00
|
|
|
} );
|
2019-02-11 17:39:12 +00:00
|
|
|
|
|
|
|
QUnit.module( 'title#fromElement', {
|
|
|
|
beforeEach() {
|
|
|
|
global.location = {
|
|
|
|
host: 'own.host',
|
|
|
|
pathname: '/w/index.php',
|
|
|
|
search: '?oldid=1&extra=1'
|
|
|
|
};
|
|
|
|
mediaWiki.Title = {
|
|
|
|
newFromText: this.sandbox.stub().throws( 'UNIMPLEMENTED' )
|
|
|
|
};
|
|
|
|
},
|
|
|
|
afterEach() {
|
|
|
|
global.location = null;
|
|
|
|
mediaWiki.Title = null;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should accept anchor links that point to the own page', function ( assert ) {
|
|
|
|
const el = document.createElement( 'a' );
|
|
|
|
el.href = 'http://own.host/w/index.php?oldid=1&extra=1#example';
|
|
|
|
|
|
|
|
const config = new Map();
|
|
|
|
config.set( 'wgPageName', 'Talk:Page' );
|
|
|
|
|
|
|
|
const mwTitle = {
|
|
|
|
namespace: 1,
|
|
|
|
title: 'Page',
|
|
|
|
fragment: 'example'
|
|
|
|
};
|
|
|
|
mediaWiki.Title.newFromText.withArgs( 'Talk:Page#example' ).returns( mwTitle );
|
|
|
|
|
|
|
|
assert.propEqual( fromElement( el, config ), mwTitle );
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should ignore anchor links that are not identical', function ( assert ) {
|
|
|
|
const el = document.createElement( 'a' );
|
|
|
|
el.href = 'http://own.host/w/index.php?oldid=1#example';
|
|
|
|
|
|
|
|
const config = new Map();
|
|
|
|
config.set( 'wgPageName', 'Talk:Page' );
|
|
|
|
|
|
|
|
assert.strictEqual( fromElement( el, config ), null );
|
|
|
|
} );
|
2019-04-20 07:24:38 +00:00
|
|
|
|
|
|
|
QUnit.test( 'it should pass through anchor links with non-ASCII characters', function ( assert ) {
|
|
|
|
const el = document.createElement( 'a' );
|
|
|
|
el.href = 'http://own.host/w/index.php?oldid=1&extra=1#Fläche';
|
|
|
|
|
|
|
|
const config = new Map();
|
|
|
|
config.set( 'wgPageName', 'Talk:Page' );
|
|
|
|
|
|
|
|
const mwTitle = {
|
|
|
|
namespace: 1,
|
|
|
|
title: 'Page',
|
|
|
|
fragment: 'Fläche'
|
|
|
|
};
|
|
|
|
mediaWiki.Title.newFromText.withArgs( 'Talk:Page#Fläche' ).returns( mwTitle );
|
|
|
|
|
|
|
|
assert.propEqual( fromElement( el, config ), mwTitle );
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should decode anchor links with encoded characters', function ( assert ) {
|
|
|
|
const el = document.createElement( 'a' );
|
|
|
|
el.href = 'http://own.host/w/index.php?oldid=1&extra=1#Fl%C3%A4che';
|
|
|
|
|
|
|
|
const config = new Map();
|
|
|
|
config.set( 'wgPageName', 'Talk:Page' );
|
|
|
|
|
|
|
|
const mwTitle = {
|
|
|
|
namespace: 1,
|
|
|
|
title: 'Page',
|
|
|
|
fragment: 'Fläche'
|
|
|
|
};
|
|
|
|
mediaWiki.Title.newFromText.withArgs( 'Talk:Page#Fläche' ).returns( mwTitle );
|
|
|
|
|
|
|
|
assert.propEqual( fromElement( el, config ), mwTitle );
|
|
|
|
} );
|
|
|
|
|
|
|
|
QUnit.test( 'it should fail gracefully on anchor links with broken encoding', function ( assert ) {
|
|
|
|
const el = document.createElement( 'a' );
|
|
|
|
el.href = 'http://own.host/w/index.php?oldid=1&extra=1#malformed%A';
|
|
|
|
|
|
|
|
const config = new Map();
|
|
|
|
config.set( 'wgPageName', 'Talk:Page' );
|
|
|
|
|
|
|
|
assert.propEqual( fromElement( el, config ), null );
|
|
|
|
} );
|