r87898 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r87897‎ | r87898 | r87899 >
Date:01:34, 12 May 2011
Author:krinkle
Status:ok
Tags:
Comment:
Continue implementation QUnit/TestSwarm integration (bug 28915)
--
For now static html files. I have considered using load.php calls, and tried an in-wiki SpecialPage. However in order for versioned testing to work in TestSwarm it must be possible to do a checkout of a revision, alias or put it in a web-acccesible directory (eg. domain/tmp-svn/r1234/resources/test) and it must work right away (without needing database or LocalConfig or permission rules to avoid the wiki being modified).

For that reason I chose for a static html page for now.

Right now it loads mediawiki.js and mediawiki.util.js modules and I created complete tests for these modules.
Modified paths:
  • /trunk/phase3/resources/test (added) (history)
  • /trunk/phase3/resources/test/index.html (added) (history)
  • /trunk/phase3/resources/test/unit (added) (history)
  • /trunk/phase3/resources/test/unit/main.css (added) (history)
  • /trunk/phase3/resources/test/unit/mediawiki (added) (history)
  • /trunk/phase3/resources/test/unit/mediawiki.util (added) (history)
  • /trunk/phase3/resources/test/unit/mediawiki.util/mediawiki.util.js (added) (history)
  • /trunk/phase3/resources/test/unit/mediawiki/mediawiki.js (added) (history)

Diff [purge]

Index: trunk/phase3/resources/test/unit/mediawiki.util/mediawiki.util.js
@@ -0,0 +1,109 @@
 2+module( 'mediawiki.util.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( mw.util, 'mw.util defined' );
 7+
 8+});
 9+
 10+test( 'rawurlencode', function(){
 11+
 12+ equals( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
 13+
 14+});
 15+
 16+test( 'wikiUrlencode', function(){
 17+
 18+ equals( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
 19+
 20+});
 21+
 22+test( 'addCSS', function(){
 23+
 24+ var a = mw.util.addCSS( '#bodyContent { background-color: rgb(170, 255, 170); }' );
 25+ ok( a, 'function works' );
 26+ same( a.disabled, false, 'property "disabled" is available and set to false' );
 27+
 28+ var $b = $('#bodyContent');
 29+ equals( $b.css('background-color'), 'rgb(170, 255, 170)', 'Style color matches.' );
 30+
 31+});
 32+
 33+test( 'toggleToc', function(){
 34+
 35+ ok( mw.util.toggleToc );
 36+
 37+});
 38+
 39+test( 'wikiGetlink', function(){
 40+
 41+ // Not part of startUp module
 42+ mw.config.set( 'wgArticlePath', '/wiki/$1' );
 43+
 44+ var hrefA = mw.util.wikiGetlink( 'Sandbox' );
 45+
 46+ equals( hrefA, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
 47+
 48+ var hrefB = mw.util.wikiGetlink( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
 49+
 50+ equals( hrefB, '/wiki/Foo:Sandbox_%3F_5%2B5%3D10_%21_%28test%29/subpage', 'Advanced title; Get link for "Foo:Sandbox ? 5+5=10 ! (test)/subpage"' );
 51+
 52+});
 53+
 54+test( 'getParamValue', function(){
 55+
 56+ equals( mw.util.getParamValue( 'foo', 'http://mediawiki.org/?foo=wrong&foo=right#&foo=bad' ), 'right', 'Use latest one, ignore hash' );
 57+ same( mw.util.getParamValue( 'bar', 'http://mediawiki.org/?foo=right' ), null, 'Return null when not found' );
 58+
 59+});
 60+
 61+test( 'tooltipAccessKey', function(){
 62+
 63+ equals( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
 64+ ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
 65+ ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
 66+
 67+});
 68+
 69+test( '$content', function(){
 70+
 71+ ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
 72+ same( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
 73+
 74+});
 75+
 76+test( 'addPortletLink', function(){
 77+
 78+ var a = mw.util.addPortletLink( 'p-tb', 'http://mediawiki.org/wiki/ResourceLoader', 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l', '#t-specialpages' );
 79+
 80+ ok( $.isDomElement(a), 'addPortletLink returns a DomElement' );
 81+
 82+ var b = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/", "MediaWiki.org", "t-mworg", "Go to MediaWiki.org ", "m", "#t-rl" );
 83+
 84+ equals( $(a).text(), 'ResourceLoader', 'Link contains correct text' );
 85+ equals( $(b).next().text(), 'ResourceLoader', 'Link was inserted in correct nextnode position' );
 86+
 87+});
 88+
 89+test( 'jsMessage', function(){
 90+
 91+ var a = mw.util.jsMessage( "MediaWiki is <b>Awesome</b>." );
 92+
 93+ ok( a, 'Basic return value checking' );
 94+
 95+});
 96+
 97+test( 'validateEmail', function(){
 98+
 99+ same( mw.util.validateEmail( "" ), null, 'Empty string should return null' );
 100+ same( mw.util.validateEmail( "user@localhost" ), true );
 101+
 102+ // testEmailWithCommasAreInvalids
 103+ same( mw.util.validateEmail( "user,foo@example.org" ), false, 'Comma' );
 104+ same( mw.util.validateEmail( "userfoo@ex,ample.org" ), false, 'Comma' );
 105+
 106+ // testEmailWithHyphens
 107+ same( mw.util.validateEmail( "user-foo@example.org" ), true, 'Hyphen' );
 108+ same( mw.util.validateEmail( "userfoo@ex-ample.org" ), true, 'Hyphen' );
 109+
 110+});
Property changes on: trunk/phase3/resources/test/unit/mediawiki.util/mediawiki.util.js
___________________________________________________________________
Added: svn:eol-style
1111 + native
Index: trunk/phase3/resources/test/unit/mediawiki/mediawiki.js
@@ -0,0 +1,169 @@
 2+module( 'mediawiki.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( window.jQuery, 'jQuery defined' );
 7+ ok( window.$j, '$j defined' );
 8+ equals( window.$j, window.jQuery, '$j alias to jQuery' );
 9+
 10+ ok( window.mediaWiki, 'mediaWiki defined' );
 11+ ok( window.mw, 'mw defined' );
 12+ equals( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
 13+
 14+});
 15+
 16+test( 'jQuery.extend', function(){
 17+
 18+ equals( $j.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
 19+ equals( $j.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
 20+ equals( $j.ucFirst( 'foo'), 'Foo', 'ucFirst' );
 21+
 22+ equals( $j.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
 23+ '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
 24+ equals( $j.escapeRE( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ),
 25+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
 26+ equals( $j.escapeRE( 'abcdefghijklmnopqrstuvwxyz' ),
 27+ 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
 28+ equals( $j.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
 29+
 30+ same( $j.isDomElement( document.getElementById( 'qunit-header' ) ), true,
 31+ 'isDomElement: #qunit-header Node' );
 32+ same( $j.isDomElement( document.getElementById( 'random-name' ) ), false,
 33+ 'isDomElement: #random-name (null)' );
 34+ same( $j.isDomElement( document.getElementsByTagName( 'div' ) ), false,
 35+ 'isDomElement: getElementsByTagName Array' );
 36+ same( $j.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
 37+ 'isDomElement: getElementsByTagName(..)[0] Node' );
 38+ same( $j.isDomElement( $j( 'div' ) ), false,
 39+ 'isDomElement: jQuery object' );
 40+ same( $j.isDomElement( $j( 'div' ).get(0) ), true,
 41+ 'isDomElement: jQuery object > Get node' );
 42+ same( $j.isDomElement( document.createElement( 'div' ) ), true,
 43+ 'isDomElement: createElement' );
 44+ same( $j.isDomElement( { foo: 1 } ), false,
 45+ 'isDomElement: Object' );
 46+
 47+ equals( $j.isEmpty( 'string' ), false, 'isEmptry: "string"' );
 48+ equals( $j.isEmpty( '0' ), true, 'isEmptry: "0"' );
 49+ equals( $j.isEmpty( [] ), true, 'isEmptry: []' );
 50+ equals( $j.isEmpty( {} ), true, 'isEmptry: {}' );
 51+ // Documented behaviour
 52+ equals( $j.isEmpty( { length: 0 } ), true, 'isEmptry: { length: 0 }' );
 53+
 54+ ok( $j.compareArray( [0, 'a', [], [2, 'b'] ], [0, "a", [], [2, "b"] ] ),
 55+ 'compareArray: Two the same deep arrays' );
 56+ ok( !$j.compareArray( [1], [2] ), 'compareArray: Two different arrays' );
 57+
 58+ ok( $j.compareObject( {}, {} ), 'compareObject: Two empty objects' );
 59+ ok( $j.compareObject( { foo: 1 }, { foo: 1 } ), 'compareObject: Two the same objects' );
 60+ ok( !$j.compareObject( { bar: true }, { baz: false } ),
 61+ 'compareObject: Two different objects' );
 62+
 63+});
 64+
 65+test( 'mw.Map / mw.config', function(){
 66+
 67+ ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
 68+ ok( mw.config.get, 'get' );
 69+ ok( mw.config.set, 'set' );
 70+ ok( mw.config.exists, 'exists' );
 71+
 72+ ok( !mw.config.exists( 'lipsum' ), 'exists: lipsum (inexistant)' );
 73+ ok( mw.config.set( 'lipsum', 'Lorem ipsum' ), 'set: lipsum' );
 74+ ok( mw.config.exists( 'lipsum' ), 'exists: lipsum (existant)' );
 75+
 76+ equals( mw.config.get( 'lipsum' ), 'Lorem ipsum', 'get: lipsum' );
 77+ equals( mw.config.get( ['lipsum'] ).lipsum, 'Lorem ipsum', 'get: lipsum (multiple)' );
 78+
 79+});
 80+
 81+test( 'mw.message / mw.msg / mw.messages', function(){
 82+ ok( mw.message, 'mw.message defined' );
 83+ ok( mw.msg, 'mw.msg defined' );
 84+ ok( mw.messages, 'messages defined' );
 85+ ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
 86+ ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
 87+
 88+ var hello = mw.message( 'hello' );
 89+ ok( hello, 'hello: Instance of Message' );
 90+
 91+ equals( hello.format, 'parse', 'Message property "format" (default value)' );
 92+ equals( hello.key, 'hello', 'Message property "key" (currect key)' );
 93+ same( hello.parameters, [], 'Message property "parameters" (default value)' );
 94+
 95+
 96+ ok( hello.params, 'Message prototype "params"');
 97+ ok( hello.toString, 'Message prototype "toString"');
 98+ ok( hello.parse, 'Message prototype "parse"');
 99+ ok( hello.plain, 'Message prototype "plain"');
 100+ ok( hello.escaped, 'Message prototype "escaped"');
 101+ ok( hello.exists, 'Message prototype "exists"');
 102+
 103+ equals( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString() test');
 104+ equals( hello.escaped(), 'Hello &lt;b&gt;awesome&lt;/b&gt; world', 'Message.escaped() test');
 105+ same( hello.exists(), true, 'Message.exists() test');
 106+
 107+ equals( mw.msg( 'random' ), '<random>', 'square brackets around inexistant messages' );
 108+ equals( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'get message with default options' );
 109+
 110+// params, toString, parse, plain, escaped, exists
 111+});
 112+
 113+test( 'mw.user', function(){
 114+
 115+ ok( mw.user, 'user defined' );
 116+ ok( mw.user.options instanceof mw.Map, 'user.options instance of mw.Map' );
 117+
 118+ same( mw.user.name(), null, 'user.name() Anonymous' );
 119+ ok( mw.user.anonymous(), 'user.anonymous() Anonymous' );
 120+
 121+ // Not part of startUp module
 122+ mw.config.set( 'wgUserName', 'John' );
 123+
 124+ equals( mw.user.name(), 'John', 'user.name() Logged-in' );
 125+ ok( !mw.user.anonymous(), 'user.anonymous() Logged-in' );
 126+
 127+ equals( mw.user.id(), 'John', 'user.id() Logged-in' );
 128+
 129+});
 130+
 131+test( 'mw.loader', function(){
 132+
 133+ // @TODO: More elaborate testing ?
 134+ // Difficult due to modules already being loaded
 135+ // through it at this point
 136+ ok( mw.loader, 'loader defined' );
 137+ ok( mw.loader.work, 'loader.work defined' );
 138+ ok( mw.loader.register, 'loader.register defined' );
 139+ ok( mw.loader.implement, 'loader.implement defined' );
 140+ ok( mw.loader.using, 'loader.using defined' );
 141+ ok( mw.loader.load, 'loader.load defined' );
 142+ ok( mw.loader.go, 'loader.go defined' );
 143+ ok( mw.loader.state, 'loader.state defined' );
 144+ ok( mw.loader.version, 'loader.version defined' );
 145+
 146+});
 147+
 148+test( 'mw.html', function(){
 149+
 150+ equals( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
 151+ '&lt;mw awesome=&quot;awesome&quot; value=&#039;test&#039; /&gt;', 'html.escape()' );
 152+
 153+ equals( mw.html.element( 'div' ), '<div/>', 'mw.html.element() DIV (simple)' );
 154+
 155+ equals( mw.html.element( 'div',
 156+ { id: 'foobar' } ),
 157+ '<div id="foobar"/>',
 158+ 'mw.html.element() DIV (attribs)' );
 159+
 160+ equals( mw.html.element( 'div',
 161+ null, 'a' ),
 162+ '<div>a</div>',
 163+ 'mw.html.element() DIV (content)' );
 164+
 165+ equals( mw.html.element( 'a',
 166+ { href: 'http://mediawiki.org/w/index.php?title=RL&action=history' }, 'a' ),
 167+ '<a href="http://mediawiki.org/w/index.php?title=RL&amp;action=history">a</a>',
 168+ 'mw.html.element() DIV (attribs + content)' );
 169+
 170+});
Property changes on: trunk/phase3/resources/test/unit/mediawiki/mediawiki.js
___________________________________________________________________
Added: svn:eol-style
1171 + native
Index: trunk/phase3/resources/test/unit/main.css
@@ -0,0 +1,5 @@
 2+/* Hide mediawiki elements */
 3+div#mw-js-message,
 4+#mw-content {
 5+ display: none !important;
 6+}
\ No newline at end of file
Property changes on: trunk/phase3/resources/test/unit/main.css
___________________________________________________________________
Added: svn:eol-style
17 + native
Index: trunk/phase3/resources/test/index.html
@@ -0,0 +1,56 @@
 2+<!DOCTYPE html>
 3+<html>
 4+<head>
 5+ <title>MediaWiki JavaScript Test Suite</title>
 6+
 7+ <!-- MediaWiki Includes -->
 8+ <meta name="ResourceLoaderDynamicStyles" content="" />
 9+
 10+ <script src="../jquery/jquery.js"></script>
 11+
 12+ <script> function startUp(){} </script>
 13+ <script src="../mediawiki/mediawiki.js"></script>
 14+ <script> mw.config = new mw.Map( false ); </script>
 15+
 16+ <script src="../jquery/jquery.checkboxShiftClick.js"></script>
 17+ <script src="../jquery/jquery.client.js"></script>
 18+ <script src="../jquery/jquery.cookie.js"></script>
 19+ <script src="../jquery/jquery.messageBox.js"></script>
 20+ <script src="../jquery/jquery.makeCollapsible.js"></script>
 21+ <script src="../jquery/jquery.placeholder.js"></script>
 22+ <script src="../jquery/jquery.tablesorter.js"></script>
 23+ <script src="../mediawiki.util/mediawiki.util.js"></script>
 24+
 25+ <!-- QUnit dependancies and scripts -->
 26+ <link rel="stylesheet" href="../jquery/jquery.qunit.css" />
 27+ <script src="../jquery/jquery.qunit.js"></script>
 28+
 29+ <!-- Your tests styles go here -->
 30+ <link rel="stylesheet" href="unit/main.css" />
 31+
 32+ <!-- Your test suites go here -->
 33+ <script src="unit/mediawiki/mediawiki.js"></script>
 34+ <script src="unit/mediawiki.util/mediawiki.util.js"></script>
 35+
 36+ <!-- TestSwarm -->
 37+ <!-- <script src="http://testswarm.wikimedia.org/js/inject.js"></script> -->
 38+</head>
 39+<body>
 40+ <h1 id="qunit-header">MediaWiki JavaScript Test Suite</h1>
 41+ <h2 id="qunit-banner"></h2>
 42+ <div id="qunit-testrunner-toolbar"></div>
 43+ <h2 id="qunit-userAgent"></h2>
 44+ <ol id="qunit-tests"></ol>
 45+
 46+<div id="mw-content">
 47+ <div id="bodyContent"></div>
 48+ <div id="mw-panel">
 49+ <div id="p-tb" class="portal">
 50+ <ul class="body">
 51+ <li id="t-specialpages"><a href="#">Special pages</a></li>
 52+ </ul>
 53+ </div>
 54+ </div>
 55+</div>
 56+</body>
 57+</html>

Follow-up revisions

RevisionCommit summaryAuthorDate
r87899Follow-up r87898: Using real pathkrinkle06:13, 12 May 2011
r89082Adding or adjusting front-end function and variable documentation per our con...krinkle02:54, 29 May 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r1234Added name attributes to all form elements to facilitate testing.lcrocker22:54, 13 March 2003

Status & tagging log