3 var mwLanguageCache
= {}, oldGetOuterHtml
, formatnumTests
;
5 QUnit
.module( 'mediawiki.jqueryMsg', QUnit
.newMwEnvironment( {
7 this.orgMwLangauge
= mw
.language
;
8 mw
.language
= $.extend( true, {}, this.orgMwLangauge
);
9 oldGetOuterHtml
= $.fn
.getOuterHtml
;
10 $.fn
.getOuterHtml = function () {
11 var $div
= $( '<div>' ), html
;
12 $div
.append( $( this ).eq( 0 ).clone() );
19 teardown: function () {
20 mw
.language
= this.orgMwLangauge
;
21 $.fn
.getOuterHtml
= oldGetOuterHtml
;
25 function getMwLanguage( langCode
, cb
) {
26 if ( mwLanguageCache
[langCode
] !== undefined ) {
27 mwLanguageCache
[langCode
].add( cb
);
30 mwLanguageCache
[langCode
] = $.Callbacks( 'once memory' );
31 mwLanguageCache
[langCode
].add( cb
);
33 url
: mw
.util
.wikiScript( 'load' ),
35 skin
: mw
.config
.get( 'skin' ),
37 debug
: mw
.config
.get( 'debug' ),
39 'mediawiki.language.data',
45 }).done( function () {
46 mwLanguageCache
[langCode
].fire( mw
.language
);
47 }).fail( function () {
48 mwLanguageCache
[langCode
].fire( false );
52 QUnit
.test( 'Replace', 9, function ( assert
) {
53 var parser
= mw
.jqueryMsg
.getMessageFunction();
55 mw
.messages
.set( 'simple', 'Foo $1 baz $2' );
57 assert
.equal( parser( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
58 assert
.equal( parser( 'simple', 'bar' ), 'Foo bar baz $2', 'Replacements with less substitutes' );
59 assert
.equal( parser( 'simple', 'bar', 'quux' ), 'Foo bar baz quux', 'Replacements with all substitutes' );
61 mw
.messages
.set( 'plain-input', '<foo foo="foo">x$1y<</foo>z' );
64 parser( 'plain-input', 'bar' ),
65 '<foo foo="foo">xbary&lt;</foo>z',
66 'Input is not considered html'
69 mw
.messages
.set( 'plain-replace', 'Foo $1' );
72 parser( 'plain-replace', '<bar bar="bar">></bar>' ),
73 'Foo <bar bar="bar">&gt;</bar>',
74 'Replacement is not considered html'
77 mw
.messages
.set( 'object-replace', 'Foo $1' );
80 parser( 'object-replace', $( '<div class="bar">></div>' ) ),
81 'Foo <div class="bar">></div>',
82 'jQuery objects are preserved as raw html'
86 parser( 'object-replace', $( '<div class="bar">></div>' ).get( 0 ) ),
87 'Foo <div class="bar">></div>',
88 'HTMLElement objects are preserved as raw html'
92 parser( 'object-replace', $( '<div class="bar">></div>' ).toArray() ),
93 'Foo <div class="bar">></div>',
94 'HTMLElement[] arrays are preserved as raw html'
97 mw
.messages
.set( 'wikilink-replace', 'Foo [$1 bar]' );
99 parser( 'wikilink-replace', 'http://example.org/?x=y&z' ),
100 'Foo <a href="http://example.org/?x=y&z">bar</a>',
101 'Href is not double-escaped in wikilink function'
105 QUnit
.test( 'Plural', 3, function ( assert
) {
106 var parser
= mw
.jqueryMsg
.getMessageFunction();
108 mw
.messages
.set( 'plural-msg', 'Found $1 {{PLURAL:$1|item|items}}' );
109 assert
.equal( parser( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
110 assert
.equal( parser( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
111 assert
.equal( parser( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
114 QUnit
.test( 'Gender', 11, function ( assert
) {
115 // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg
116 // TODO: English may not be the best language for these tests. Use a language like Arabic or Russian
118 parser
= mw
.jqueryMsg
.getMessageFunction();
120 // The values here are not significant,
121 // what matters is which of the values is choosen by the parser
122 mw
.messages
.set( 'gender-msg', '$1: {{GENDER:$2|blue|pink|green}}' );
124 user
.options
.set( 'gender', 'male' );
126 parser( 'gender-msg', 'Bob', 'male' ),
128 'Masculine from string "male"'
131 parser( 'gender-msg', 'Bob', user
),
133 'Masculine from mw.user object'
136 user
.options
.set( 'gender', 'unknown' );
138 parser( 'gender-msg', 'Foo', user
),
140 'Neutral from mw.user object' );
142 parser( 'gender-msg', 'Alice', 'female' ),
144 'Feminine from string "female"' );
146 parser( 'gender-msg', 'User' ),
148 'Neutral when no parameter given' );
150 parser( 'gender-msg', 'User', 'unknown' ),
152 'Neutral from string "unknown"'
155 mw
.messages
.set( 'gender-msg-one-form', '{{GENDER:$1|User}}: $2 {{PLURAL:$2|edit|edits}}' );
158 parser( 'gender-msg-one-form', 'male', 10 ),
160 'Gender neutral and plural form'
163 parser( 'gender-msg-one-form', 'female', 1 ),
165 'Gender neutral and singular form'
168 mw
.messages
.set( 'gender-msg-lowercase', '{{gender:$1|he|she}} is awesome' );
170 parser( 'gender-msg-lowercase', 'male' ),
175 parser( 'gender-msg-lowercase', 'female' ),
180 mw
.messages
.set( 'gender-msg-wrong', '{{gender}} test' );
182 parser( 'gender-msg-wrong', 'female' ),
184 'Invalid syntax should result in {{gender}} simply being stripped away'
188 QUnit
.test( 'Grammar', 2, function ( assert
) {
189 var parser
= mw
.jqueryMsg
.getMessageFunction();
191 // Assume the grammar form grammar_case_foo is not valid in any language
192 mw
.messages
.set( 'grammar-msg', 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}' );
193 assert
.equal( parser( 'grammar-msg' ), 'Przeszukaj ' + mw
.config
.get( 'wgSiteName' ), 'Grammar Test with sitename' );
195 mw
.messages
.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' );
196 assert
.equal( parser( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ' , 'Grammar Test with wrong grammar template syntax' );
199 QUnit
.test( 'Match PHP parser', mw
.libs
.phpParserData
.tests
.length
, function ( assert
) {
200 mw
.messages
.set( mw
.libs
.phpParserData
.messages
);
201 $.each( mw
.libs
.phpParserData
.tests
, function ( i
, test
) {
203 getMwLanguage( test
.lang
, function ( langClass
) {
206 assert
.ok( false, 'Language "' + test
.lang
+ '" failed to load' );
209 mw
.config
.set( 'wgUserLanguage', test
.lang
) ;
210 var parser
= new mw
.jqueryMsg
.parser( { language
: langClass
} );
212 parser
.parse( test
.key
, test
.args
).html(),
220 QUnit
.test( 'Wikilink', 6, function ( assert
) {
221 var parser
= mw
.jqueryMsg
.getMessageFunction(),
223 expectedDisambiguationsText
,
224 expectedMultipleBars
,
225 expectedSpecialCharacters
,
226 specialCharactersPageName
;
229 The below three are all identical to or based on real messages. For disambiguations-text,
230 the bold was removed because it is not yet implemented.
233 mw
.messages
.set( 'statistics-users', '注册[[Special:ListUsers|用户]]' );
235 expectedListUsers
= '注册' + $( '<a>' ).attr( {
236 title
: 'Special:ListUsers',
237 href
: mw
.util
.wikiGetlink( 'Special:ListUsers' )
238 } ).text( '用户' ).getOuterHtml();
241 parser( 'statistics-users' ),
246 expectedDisambiguationsText
= 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from ' +
248 title
: 'MediaWiki:Disambiguationspage',
249 href
: mw
.util
.wikiGetlink( 'MediaWiki:Disambiguationspage' )
250 } ).text( 'MediaWiki:Disambiguationspage' ).getOuterHtml() + '.';
251 mw
.messages
.set( 'disambiguations-text', 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from [[MediaWiki:Disambiguationspage]].' );
253 parser( 'disambiguations-text' ),
254 expectedDisambiguationsText
,
255 'Wikilink without pipe'
258 mw
.messages
.set( 'version-entrypoints-index-php', '[https://www.mediawiki.org/wiki/Manual:index.php index.php]' );
260 parser( 'version-entrypoints-index-php' ),
261 '<a href="https://www.mediawiki.org/wiki/Manual:index.php">index.php</a>',
265 // Pipe trick is not supported currently, but should not parse as text either.
266 mw
.messages
.set( 'pipe-trick', '[[Tampa, Florida|]]' );
268 parser( 'pipe-trick' ),
269 'pipe-trick: Parse error at position 0 in input: [[Tampa, Florida|]]',
270 'Pipe trick should return error string.'
273 expectedMultipleBars
= $( '<a>' ).attr( {
275 href
: mw
.util
.wikiGetlink( 'Main Page' )
276 } ).text( 'Main|Page' ).getOuterHtml();
277 mw
.messages
.set( 'multiple-bars', '[[Main Page|Main|Page]]' );
279 parser( 'multiple-bars' ),
280 expectedMultipleBars
,
284 specialCharactersPageName
= '"Who" wants to be a millionaire & live on \'Exotic Island\'?';
285 expectedSpecialCharacters
= $( '<a>' ).attr( {
286 title
: specialCharactersPageName
,
287 href
: mw
.util
.wikiGetlink( specialCharactersPageName
)
288 } ).text( specialCharactersPageName
).getOuterHtml();
290 mw
.messages
.set( 'special-characters', '[[' + specialCharactersPageName
+ ']]' );
292 parser( 'special-characters' ),
293 expectedSpecialCharacters
,
298 QUnit
.test( 'Int', 4, function ( assert
) {
299 var parser
= mw
.jqueryMsg
.getMessageFunction(),
300 newarticletextSource
= 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the [[{{Int:Helppage}}|help page]] for more info). If you are here by mistake, click your browser\'s back button.',
301 expectedNewarticletext
;
303 mw
.messages
.set( 'helppage', 'Help:Contents' );
305 expectedNewarticletext
= 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the ' +
307 title
: mw
.msg( 'helppage' ),
308 href
: mw
.util
.wikiGetlink( mw
.msg( 'helppage' ) )
309 } ).text( 'help page' ).getOuterHtml() + ' for more info). If you are here by mistake, click your browser\'s back button.';
311 mw
.messages
.set( 'newarticletext', newarticletextSource
);
314 parser( 'newarticletext' ),
315 expectedNewarticletext
,
316 'Link with nested message'
319 mw
.messages
.set( 'portal-url', 'Project:Community portal' );
320 mw
.messages
.set( 'see-portal-url', '{{Int:portal-url}} is an important community page.' );
322 parser( 'see-portal-url' ),
323 'Project:Community portal is an important community page.',
327 mw
.messages
.set( 'newarticletext-lowercase',
328 newarticletextSource
.replace( 'Int:Helppage', 'int:helppage' ) );
331 parser( 'newarticletext-lowercase' ),
332 expectedNewarticletext
,
333 'Link with nested message, lowercase include'
336 mw
.messages
.set( 'uses-missing-int', '{{int:doesnt-exist}}' );
339 parser( 'uses-missing-int' ),
341 'int: where nested message does not exist'
345 // Tests that getMessageFunction is used for messages with curly braces or square brackets,
346 // but not otherwise.
347 QUnit
.test( 'mw.msg()', 8, function ( assert
) {
349 var map
, oldGMF
, outerCalled
, innerCalled
;
353 'curly-brace': '{{int:message}}',
354 'single-square-bracket': '[https://www.mediawiki.org/ MediaWiki]',
355 'double-square-bracket': '[[Some page]]',
356 'regular': 'Other message'
359 oldGMF
= mw
.jqueryMsg
.getMessageFunction
;
361 mw
.jqueryMsg
.getMessageFunction = function() {
368 function verifyGetMessageFunction( key
, shouldCall
) {
371 ( new mw
.Message( map
, key
) ).parser();
372 assert
.strictEqual( outerCalled
, shouldCall
, 'Outer function called for ' + key
);
373 assert
.strictEqual( innerCalled
, shouldCall
, 'Inner function called for ' + key
);
376 verifyGetMessageFunction( 'curly-brace', true );
377 verifyGetMessageFunction( 'single-square-bracket', true );
378 verifyGetMessageFunction( 'double-square-bracket', true );
379 verifyGetMessageFunction( 'regular', false );
381 mw
.jqueryMsg
.getMessageFunction
= oldGMF
;
387 number
: 987654321.654321,
388 result
: '987654321.654321',
389 description
: 'formatnum test for English, decimal seperator'
393 number
: 987654321.654321,
394 result
: '٩٨٧٦٥٤٣٢١٫٦٥٤٣٢١',
395 description
: 'formatnum test for Arabic, with decimal seperator'
399 number
: '٩٨٧٦٥٤٣٢١٫٦٥٤٣٢١',
402 description
: 'formatnum test for Arabic, with decimal seperator, reverse'
408 description
: 'formatnum test for Arabic, negative number'
415 description
: 'formatnum test for Arabic, negative number, reverse'
419 number
: 987654321.654321,
420 result
: '987654321,654321',
421 description
: 'formatnum test for Nederlands, decimal seperator'
427 description
: 'formatnum test for Nederlands, negative number'
431 number
: 'invalidnumber',
432 result
: 'invalidnumber',
433 description
: 'formatnum test for Nederlands, invalid number'
437 QUnit
.test( 'formatnum', formatnumTests
.length
, function ( assert
) {
438 mw
.messages
.set( 'formatnum-msg', '{{formatnum:$1}}' );
439 mw
.messages
.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
440 $.each( formatnumTests
, function ( i
, test
) {
442 getMwLanguage( test
.lang
, function ( langClass
) {
445 assert
.ok( false, 'Language "' + test
.lang
+ '" failed to load' );
448 mw
.messages
.set(test
.message
);
449 mw
.config
.set( 'wgUserLanguage', test
.lang
) ;
450 var parser
= new mw
.jqueryMsg
.parser( { language
: langClass
} );
452 parser
.parse( test
.integer
? 'formatnum-msg-int' : 'formatnum-msg',
453 [ test
.number
] ).html(),
461 }( mediaWiki
, jQuery
) );