diff options
Diffstat (limited to 'tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js')
-rw-r--r-- | tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js | 337 |
1 files changed, 226 insertions, 111 deletions
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js index 0a9df966..be362e22 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js @@ -1,20 +1,17 @@ ( function ( mw, $ ) { - var mwLanguageCache = {}, oldGetOuterHtml, formatnumTests, specialCharactersPageName, + var mwLanguageCache = {}, formatText, formatParse, formatnumTests, specialCharactersPageName, expectedListUsers, expectedEntrypoints; + // When the expected result is the same in both modes + function assertBothModes( assert, parserArguments, expectedResult, assertMessage ) { + assert.equal( formatText.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'text\'' ); + assert.equal( formatParse.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'parse\'' ); + } + QUnit.module( 'mediawiki.jqueryMsg', QUnit.newMwEnvironment( { setup: function () { this.orgMwLangauge = mw.language; mw.language = $.extend( true, {}, this.orgMwLangauge ); - oldGetOuterHtml = $.fn.getOuterHtml; - $.fn.getOuterHtml = function () { - var $div = $( '<div>' ), html; - $div.append( $( this ).eq( 0 ).clone() ); - html = $div.html(); - $div.empty(); - $div = undefined; - return html; - }; // Messages that are reused in multiple tests mw.messages.set( { @@ -39,18 +36,26 @@ 'external-link-replace': 'Foo [$1 bar]' } ); + mw.config.set( { + wgArticlePath: '/wiki/$1' + } ); + specialCharactersPageName = '"Who" wants to be a millionaire & live on \'Exotic Island\'?'; - expectedListUsers = '注册' + $( '<a>' ).attr( { - title: 'Special:ListUsers', - href: mw.util.wikiGetlink( 'Special:ListUsers' ) - } ).text( '用户' ).getOuterHtml(); + expectedListUsers = '注册<a title="Special:ListUsers" href="/wiki/Special:ListUsers">用户</a>'; expectedEntrypoints = '<a href="https://www.mediawiki.org/wiki/Manual:index.php">index.php</a>'; + + formatText = mw.jqueryMsg.getMessageFunction( { + format: 'text' + } ); + + formatParse = mw.jqueryMsg.getMessageFunction( { + format: 'parse' + } ); }, teardown: function () { mw.language = this.orgMwLangauge; - $.fn.getOuterHtml = oldGetOuterHtml; } } ) ); @@ -82,18 +87,16 @@ } QUnit.test( 'Replace', 9, function ( assert ) { - var parser = mw.jqueryMsg.getMessageFunction(); - mw.messages.set( 'simple', 'Foo $1 baz $2' ); - assert.equal( parser( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' ); - assert.equal( parser( 'simple', 'bar' ), 'Foo bar baz $2', 'Replacements with less substitutes' ); - assert.equal( parser( 'simple', 'bar', 'quux' ), 'Foo bar baz quux', 'Replacements with all substitutes' ); + assert.equal( formatParse( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' ); + assert.equal( formatParse( 'simple', 'bar' ), 'Foo bar baz $2', 'Replacements with less substitutes' ); + assert.equal( formatParse( 'simple', 'bar', 'quux' ), 'Foo bar baz quux', 'Replacements with all substitutes' ); mw.messages.set( 'plain-input', '<foo foo="foo">x$1y<</foo>z' ); assert.equal( - parser( 'plain-input', 'bar' ), + formatParse( 'plain-input', 'bar' ), '<foo foo="foo">xbary&lt;</foo>z', 'Input is not considered html' ); @@ -101,7 +104,7 @@ mw.messages.set( 'plain-replace', 'Foo $1' ); assert.equal( - parser( 'plain-replace', '<bar bar="bar">></bar>' ), + formatParse( 'plain-replace', '<bar bar="bar">></bar>' ), 'Foo <bar bar="bar">&gt;</bar>', 'Replacement is not considered html' ); @@ -109,71 +112,68 @@ mw.messages.set( 'object-replace', 'Foo $1' ); assert.equal( - parser( 'object-replace', $( '<div class="bar">></div>' ) ), + formatParse( 'object-replace', $( '<div class="bar">></div>' ) ), 'Foo <div class="bar">></div>', 'jQuery objects are preserved as raw html' ); assert.equal( - parser( 'object-replace', $( '<div class="bar">></div>' ).get( 0 ) ), + formatParse( 'object-replace', $( '<div class="bar">></div>' ).get( 0 ) ), 'Foo <div class="bar">></div>', 'HTMLElement objects are preserved as raw html' ); assert.equal( - parser( 'object-replace', $( '<div class="bar">></div>' ).toArray() ), + formatParse( 'object-replace', $( '<div class="bar">></div>' ).toArray() ), 'Foo <div class="bar">></div>', 'HTMLElement[] arrays are preserved as raw html' ); assert.equal( - parser( 'external-link-replace', 'http://example.org/?x=y&z' ), + formatParse( 'external-link-replace', 'http://example.org/?x=y&z' ), 'Foo <a href="http://example.org/?x=y&z">bar</a>', 'Href is not double-escaped in wikilink function' ); } ); QUnit.test( 'Plural', 3, function ( assert ) { - var parser = mw.jqueryMsg.getMessageFunction(); - - assert.equal( parser( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' ); - assert.equal( parser( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' ); - assert.equal( parser( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' ); + assert.equal( formatParse( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' ); + assert.equal( formatParse( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' ); + assert.equal( formatParse( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' ); } ); QUnit.test( 'Gender', 11, function ( assert ) { // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg // TODO: English may not be the best language for these tests. Use a language like Arabic or Russian - var user = mw.user, - parser = mw.jqueryMsg.getMessageFunction(); + var user = mw.user; user.options.set( 'gender', 'male' ); assert.equal( - parser( 'gender-msg', 'Bob', 'male' ), + formatParse( 'gender-msg', 'Bob', 'male' ), 'Bob: blue', 'Masculine from string "male"' ); assert.equal( - parser( 'gender-msg', 'Bob', user ), + formatParse( 'gender-msg', 'Bob', user ), 'Bob: blue', 'Masculine from mw.user object' ); user.options.set( 'gender', 'unknown' ); assert.equal( - parser( 'gender-msg', 'Foo', user ), + formatParse( 'gender-msg', 'Foo', user ), 'Foo: green', 'Neutral from mw.user object' ); assert.equal( - parser( 'gender-msg', 'Alice', 'female' ), + formatParse( 'gender-msg', 'Alice', 'female' ), 'Alice: pink', 'Feminine from string "female"' ); assert.equal( - parser( 'gender-msg', 'User' ), + formatParse( 'gender-msg', 'User' ), 'User: green', 'Neutral when no parameter given' ); assert.equal( - parser( 'gender-msg', 'User', 'unknown' ), + formatParse( 'gender-msg', 'User', 'unknown' ), 'User: green', 'Neutral from string "unknown"' ); @@ -181,43 +181,41 @@ mw.messages.set( 'gender-msg-one-form', '{{GENDER:$1|User}}: $2 {{PLURAL:$2|edit|edits}}' ); assert.equal( - parser( 'gender-msg-one-form', 'male', 10 ), + formatParse( 'gender-msg-one-form', 'male', 10 ), 'User: 10 edits', 'Gender neutral and plural form' ); assert.equal( - parser( 'gender-msg-one-form', 'female', 1 ), + formatParse( 'gender-msg-one-form', 'female', 1 ), 'User: 1 edit', 'Gender neutral and singular form' ); mw.messages.set( 'gender-msg-lowercase', '{{gender:$1|he|she}} is awesome' ); assert.equal( - parser( 'gender-msg-lowercase', 'male' ), + formatParse( 'gender-msg-lowercase', 'male' ), 'he is awesome', 'Gender masculine' ); assert.equal( - parser( 'gender-msg-lowercase', 'female' ), + formatParse( 'gender-msg-lowercase', 'female' ), 'she is awesome', 'Gender feminine' ); mw.messages.set( 'gender-msg-wrong', '{{gender}} test' ); assert.equal( - parser( 'gender-msg-wrong', 'female' ), + formatParse( 'gender-msg-wrong', 'female' ), ' test', 'Invalid syntax should result in {{gender}} simply being stripped away' ); } ); QUnit.test( 'Grammar', 2, function ( assert ) { - var parser = mw.jqueryMsg.getMessageFunction(); - - assert.equal( parser( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar Test with sitename' ); + assert.equal( formatParse( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar Test with sitename' ); mw.messages.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' ); - assert.equal( parser( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ', 'Grammar Test with wrong grammar template syntax' ); + assert.equal( formatParse( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ', 'Grammar Test with wrong grammar template syntax' ); } ); QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) { @@ -242,8 +240,7 @@ } ); QUnit.test( 'Links', 6, function ( assert ) { - var parser = mw.jqueryMsg.getMessageFunction(), - expectedDisambiguationsText, + var expectedDisambiguationsText, expectedMultipleBars, expectedSpecialCharacters; @@ -252,26 +249,24 @@ the bold was removed because it is not yet implemented. */ - assert.equal( - parser( 'jquerymsg-test-statistics-users' ), + assert.htmlEqual( + formatParse( 'jquerymsg-test-statistics-users' ), expectedListUsers, 'Piped wikilink' ); 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 ' + - $( '<a>' ).attr( { - title: 'MediaWiki:Disambiguationspage', - href: mw.util.wikiGetlink( 'MediaWiki:Disambiguationspage' ) - } ).text( 'MediaWiki:Disambiguationspage' ).getOuterHtml() + '.'; + '<a title="MediaWiki:Disambiguationspage" href="/wiki/MediaWiki:Disambiguationspage">MediaWiki:Disambiguationspage</a>.'; + 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]].' ); - assert.equal( - parser( 'disambiguations-text' ), + assert.htmlEqual( + formatParse( 'disambiguations-text' ), expectedDisambiguationsText, 'Wikilink without pipe' ); - assert.equal( - parser( 'jquerymsg-test-version-entrypoints-index-php' ), + assert.htmlEqual( + formatParse( 'jquerymsg-test-version-entrypoints-index-php' ), expectedEntrypoints, 'External link' ); @@ -279,30 +274,24 @@ // Pipe trick is not supported currently, but should not parse as text either. mw.messages.set( 'pipe-trick', '[[Tampa, Florida|]]' ); assert.equal( - parser( 'pipe-trick' ), + formatParse( 'pipe-trick' ), 'pipe-trick: Parse error at position 0 in input: [[Tampa, Florida|]]', 'Pipe trick should return error string.' ); - expectedMultipleBars = $( '<a>' ).attr( { - title: 'Main Page', - href: mw.util.wikiGetlink( 'Main Page' ) - } ).text( 'Main|Page' ).getOuterHtml(); + expectedMultipleBars = '<a title="Main Page" href="/wiki/Main_Page">Main|Page</a>'; mw.messages.set( 'multiple-bars', '[[Main Page|Main|Page]]' ); - assert.equal( - parser( 'multiple-bars' ), + assert.htmlEqual( + formatParse( 'multiple-bars' ), expectedMultipleBars, 'Bar in anchor' ); - expectedSpecialCharacters = $( '<a>' ).attr( { - title: specialCharactersPageName, - href: mw.util.wikiGetlink( specialCharactersPageName ) - } ).text( specialCharactersPageName ).getOuterHtml(); + expectedSpecialCharacters = '<a title=""Who" wants to be a millionaire & live on 'Exotic Island'?" href="/wiki/%22Who%22_wants_to_be_a_millionaire_%26_live_on_%27Exotic_Island%27%3F">"Who" wants to be a millionaire & live on 'Exotic Island'?</a>'; mw.messages.set( 'special-characters', '[[' + specialCharactersPageName + ']]' ); - assert.equal( - parser( 'special-characters' ), + assert.htmlEqual( + formatParse( 'special-characters' ), expectedSpecialCharacters, 'Special characters' ); @@ -310,32 +299,16 @@ // Tests that {{-transformation vs. general parsing are done as requested QUnit.test( 'Curly brace transformation', 14, function ( assert ) { - var formatText, formatParse, oldUserLang; - - oldUserLang = mw.config.get( 'wgUserLanguage' ); - - formatText = mw.jqueryMsg.getMessageFunction( { - format: 'text' - } ); - - formatParse = mw.jqueryMsg.getMessageFunction( { - format: 'parse' - } ); - - // When the expected result is the same in both modes - function assertBothModes( parserArguments, expectedResult, assertMessage ) { - assert.equal( formatText.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'text\'' ); - assert.equal( formatParse.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'parse\'' ); - } + var oldUserLang = mw.config.get( 'wgUserLanguage' ); - assertBothModes( ['gender-msg', 'Bob', 'male'], 'Bob: blue', 'gender is resolved' ); + assertBothModes( assert, ['gender-msg', 'Bob', 'male'], 'Bob: blue', 'gender is resolved' ); - assertBothModes( ['plural-msg', 5], 'Found 5 items', 'plural is resolved' ); + assertBothModes( assert, ['plural-msg', 5], 'Found 5 items', 'plural is resolved' ); - assertBothModes( ['grammar-msg'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'grammar is resolved' ); + assertBothModes( assert, ['grammar-msg'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'grammar is resolved' ); mw.config.set( 'wgUserLanguage', 'en' ); - assertBothModes( ['formatnum-msg', '987654321.654321'], '987,654,321.654', 'formatnum is resolved' ); + assertBothModes( assert, ['formatnum-msg', '987654321.654321'], '987,654,321.654', 'formatnum is resolved' ); // Test non-{{ wikitext, where behavior differs @@ -345,7 +318,7 @@ mw.messages.get( 'jquerymsg-test-statistics-users' ), 'Internal link message unchanged when format is \'text\'' ); - assert.equal( + assert.htmlEqual( formatParse( 'jquerymsg-test-statistics-users' ), expectedListUsers, 'Internal link message parsed when format is \'parse\'' @@ -357,7 +330,7 @@ mw.messages.get( 'jquerymsg-test-version-entrypoints-index-php' ), 'External link message unchanged when format is \'text\'' ); - assert.equal( + assert.htmlEqual( formatParse( 'jquerymsg-test-version-entrypoints-index-php' ), expectedEntrypoints, 'External link message processed when format is \'parse\'' @@ -369,7 +342,7 @@ 'Foo [http://example.com bar]', 'External link message only substitutes parameter when format is \'text\'' ); - assert.equal( + assert.htmlEqual( formatParse( 'external-link-replace', 'http://example.com' ), 'Foo <a href="http://example.com">bar</a>', 'External link message processed when format is \'parse\'' @@ -379,28 +352,25 @@ } ); QUnit.test( 'Int', 4, function ( assert ) { - var parser = mw.jqueryMsg.getMessageFunction(), - 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.', - expectedNewarticletext; + var 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.', + expectedNewarticletext, + helpPageTitle = 'Help:Contents'; - mw.messages.set( 'helppage', 'Help:Contents' ); + mw.messages.set( 'helppage', helpPageTitle ); 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 ' + - $( '<a>' ).attr( { - title: mw.msg( 'helppage' ), - href: mw.util.wikiGetlink( mw.msg( 'helppage' ) ) - } ).text( 'help page' ).getOuterHtml() + ' for more info). If you are here by mistake, click your browser\'s back button.'; + '<a title="Help:Contents" href="/wiki/Help:Contents">help page</a> for more info). If you are here by mistake, click your browser\'s back button.'; mw.messages.set( 'newarticletext', newarticletextSource ); - assert.equal( - parser( 'newarticletext' ), + assert.htmlEqual( + formatParse( 'newarticletext' ), expectedNewarticletext, 'Link with nested message' ); assert.equal( - parser( 'see-portal-url' ), + formatParse( 'see-portal-url' ), 'Project:Community portal is an important community page.', 'Nested message' ); @@ -408,8 +378,8 @@ mw.messages.set( 'newarticletext-lowercase', newarticletextSource.replace( 'Int:Helppage', 'int:helppage' ) ); - assert.equal( - parser( 'newarticletext-lowercase' ), + assert.htmlEqual( + formatParse( 'newarticletext-lowercase' ), expectedNewarticletext, 'Link with nested message, lowercase include' ); @@ -417,7 +387,7 @@ mw.messages.set( 'uses-missing-int', '{{int:doesnt-exist}}' ); assert.equal( - parser( 'uses-missing-int' ), + formatParse( 'uses-missing-int' ), '[doesnt-exist]', 'int: where nested message does not exist' ); @@ -596,4 +566,149 @@ QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) { } ); } ); +// HTML in wikitext +QUnit.test( 'HTML', 26, function ( assert ) { + mw.messages.set( 'jquerymsg-italics-msg', '<i>Very</i> important' ); + + assertBothModes( assert, ['jquerymsg-italics-msg'], mw.messages.get( 'jquerymsg-italics-msg' ), 'Simple italics unchanged' ); + + mw.messages.set( 'jquerymsg-bold-msg', '<b>Strong</b> speaker' ); + assertBothModes( assert, ['jquerymsg-bold-msg'], mw.messages.get( 'jquerymsg-bold-msg' ), 'Simple bold unchanged' ); + + mw.messages.set( 'jquerymsg-bold-italics-msg', 'It is <b><i>key</i></b>' ); + assertBothModes( assert, ['jquerymsg-bold-italics-msg'], mw.messages.get( 'jquerymsg-bold-italics-msg' ), 'Bold and italics nesting order preserved' ); + + mw.messages.set( 'jquerymsg-italics-bold-msg', 'It is <i><b>vital</b></i>' ); + assertBothModes( assert, ['jquerymsg-italics-bold-msg'], mw.messages.get( 'jquerymsg-italics-bold-msg' ), 'Italics and bold nesting order preserved' ); + + mw.messages.set( 'jquerymsg-italics-with-link', 'An <i>italicized [[link|wiki-link]]</i>' ); + + assert.htmlEqual( + formatParse( 'jquerymsg-italics-with-link' ), + 'An <i>italicized <a title="link" href="' + mw.html.escape( mw.util.getUrl( 'link' ) ) + '">wiki-link</i>', + 'Italics with link inside in parse mode' + ); + + assert.equal( + formatText( 'jquerymsg-italics-with-link' ), + mw.messages.get( 'jquerymsg-italics-with-link' ), + 'Italics with link unchanged in text mode' + ); + + mw.messages.set( 'jquerymsg-italics-id-class', '<i id="foo" class="bar">Foo</i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-italics-id-class' ), + mw.messages.get( 'jquerymsg-italics-id-class' ), + 'ID and class are allowed' + ); + + mw.messages.set( 'jquerymsg-italics-onclick', '<i onclick="alert(\'foo\')">Foo</i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-italics-onclick' ), + '<i onclick="alert(\'foo\')">Foo</i>', + 'element with onclick is escaped because it is not allowed' + ); + + mw.messages.set( 'jquerymsg-script-msg', '<script >alert( "Who put this tag here?" );</script>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-script-msg' ), + '<script >alert( "Who put this tag here?" );</script>', + 'Tag outside whitelist escaped in parse mode' + ); + + assert.equal( + formatText( 'jquerymsg-script-msg' ), + mw.messages.get( 'jquerymsg-script-msg' ), + 'Tag outside whitelist unchanged in text mode' + ); + + mw.messages.set( 'jquerymsg-script-link-msg', '<script>[[Foo|bar]]</script>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-script-link-msg' ), + '<script><a title="Foo" href="' + mw.html.escape( mw.util.getUrl( 'Foo' ) ) + '">bar</a></script>', + 'Script tag text is escaped because that element is not allowed, but link inside is still HTML' + ); + + mw.messages.set( 'jquerymsg-mismatched-html', '<i class="important">test</b>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-mismatched-html' ), + '<i class="important">test</b>', + 'Mismatched HTML start and end tag treated as text' + ); + + // TODO (mattflaschen, 2013-03-18): It's not a security issue, but there's no real + // reason the htmlEmitter span needs to be here. It's an artifact of how emitting works. + mw.messages.set( 'jquerymsg-script-and-external-link', '<script>alert( "jquerymsg-script-and-external-link test" );</script> [http://example.com <i>Foo</i> bar]' ); + assert.htmlEqual( + formatParse( 'jquerymsg-script-and-external-link' ), + '<script>alert( "jquerymsg-script-and-external-link test" );</script> <a href="http://example.com"><span class="mediaWiki_htmlEmitter"><i>Foo</i> bar</span></a>', + 'HTML tags in external links not interfering with escaping of other tags' + ); + + mw.messages.set( 'jquerymsg-link-script', '[http://example.com <script>alert( "jquerymsg-link-script test" );</script>]' ); + assert.htmlEqual( + formatParse( 'jquerymsg-link-script' ), + '<a href="http://example.com"><span class="mediaWiki_htmlEmitter"><script>alert( "jquerymsg-link-script test" );</script></span></a>', + 'Non-whitelisted HTML tag in external link anchor treated as text' + ); + + // Intentionally not using htmlEqual for the quote tests + mw.messages.set( 'jquerymsg-double-quotes-preserved', '<i id="double">Double</i>' ); + assert.equal( + formatParse( 'jquerymsg-double-quotes-preserved' ), + mw.messages.get( 'jquerymsg-double-quotes-preserved' ), + 'Attributes with double quotes are preserved as such' + ); + + mw.messages.set( 'jquerymsg-single-quotes-normalized-to-double', '<i id=\'single\'>Single</i>' ); + assert.equal( + formatParse( 'jquerymsg-single-quotes-normalized-to-double' ), + '<i id="single">Single</i>', + 'Attributes with single quotes are normalized to double' + ); + + mw.messages.set( 'jquerymsg-escaped-double-quotes-attribute', '<i style="font-family:"Arial"">Styled</i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-escaped-double-quotes-attribute' ), + mw.messages.get( 'jquerymsg-escaped-double-quotes-attribute' ), + 'Escaped attributes are parsed correctly' + ); + + mw.messages.set( 'jquerymsg-escaped-single-quotes-attribute', '<i style=\'font-family:'Arial'\'>Styled</i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-escaped-single-quotes-attribute' ), + mw.messages.get( 'jquerymsg-escaped-single-quotes-attribute' ), + 'Escaped attributes are parsed correctly' + ); + + + mw.messages.set( 'jquerymsg-wikitext-contents-parsed', '<i>[http://example.com Example]</i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-wikitext-contents-parsed' ), + '<i><a href="http://example.com">Example</a></i>', + 'Contents of valid tag are treated as wikitext, so external link is parsed' + ); + + mw.messages.set( 'jquerymsg-wikitext-contents-script', '<i><script>Script inside</script></i>' ); + assert.htmlEqual( + formatParse( 'jquerymsg-wikitext-contents-script' ), + '<i><span class="mediaWiki_htmlEmitter"><script>Script inside</script></span></i>', + 'Contents of valid tag are treated as wikitext, so invalid HTML element is treated as text' + ); + + mw.messages.set( 'jquerymsg-unclosed-tag', 'Foo<tag>bar' ); + assert.htmlEqual( + formatParse( 'jquerymsg-unclosed-tag' ), + 'Foo<tag>bar', + 'Nonsupported unclosed tags are escaped' + ); + + mw.messages.set( 'jquerymsg-self-closing-tag', 'Foo<tag/>bar' ); + assert.htmlEqual( + formatParse( 'jquerymsg-self-closing-tag' ), + 'Foo<tag/>bar', + 'Self-closing tags don\'t cause a parse error' + ); +} ); + }( mediaWiki, jQuery ) ); |