Index: branches/JSTesting/RELEASE-NOTES-1.19 |
— | — | @@ -72,6 +72,9 @@ |
73 | 73 | * (bug 31297) Add support for namespaces in Special:RecentChanges subpage filter syntax. |
74 | 74 | * The default user signature now contains a talk link in addition to the user link. |
75 | 75 | * (bug 25306) Add link of old page title to MediaWiki:Delete_and_move_reason |
| 76 | +* (bug 30339) Implement SpecialPage for running javascript tests. Disabled by default, due to |
| 77 | + tests potentially being harmful, not to be run on a production wiki. |
| 78 | + Enable by setting $wgEnableJavaScriptTest to true. |
76 | 79 | |
77 | 80 | === Bug fixes in 1.19 === |
78 | 81 | * $wgUploadNavigationUrl should be used for file redlinks if |
Index: branches/JSTesting/tests/qunit/QUnitTestResources.php |
— | — | @@ -0,0 +1,56 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +return array( |
| 5 | + |
| 6 | + /* Test suites for MediaWiki core modules */ |
| 7 | + |
| 8 | + 'mediawiki.tests.qunit.suites' => array( |
| 9 | + 'scripts' => array( |
| 10 | + 'tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js', |
| 11 | + 'tests/qunit/suites/resources/jquery/jquery.byteLength.test.js', |
| 12 | + 'tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js', // has mw-config def |
| 13 | + 'tests/qunit/suites/resources/jquery/jquery.client.test.js', |
| 14 | + 'tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js', |
| 15 | + 'tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js', |
| 16 | + 'tests/qunit/suites/resources/jquery/jquery.localize.test.js', |
| 17 | + 'tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js', |
| 18 | + 'tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js', |
| 19 | + # jquery.tablesorter.test.js: Broken |
| 20 | + #'tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js', // has mw-config def |
| 21 | + 'tests/qunit/suites/resources/jquery/jquery.textSelection.test.js', |
| 22 | + # mediawiki.test.js: Tries to load from /data/ directory, fails when ran from the |
| 23 | + # SpecialPage since it uses regex to get the current path and loads from that + /data/ |
| 24 | + # (index.php/Data in this case..) |
| 25 | + #'tests/qunit/suites/resources/mediawiki/mediawiki.test.js', |
| 26 | + 'tests/qunit/suites/resources/mediawiki/mediawiki.title.test.js', // has mw-config def |
| 27 | + 'tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js', |
| 28 | + 'tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js', |
| 29 | + 'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js', |
| 30 | + |
| 31 | + // *has mw-config def: |
| 32 | + // This means the module overwrites/stes mw.config variables, reason being that |
| 33 | + // the static /qunit/index.html has an empty mw.config since it's static. |
| 34 | + // Until /qunit/index.html is fully replaceable and WMF's TestSwarm is up and running |
| 35 | + // with Special:JavaScriptTest, untill it is important that tests do not depend on anything |
| 36 | + // being in mw.config (not even wgServer). |
| 37 | + ), |
| 38 | + 'dependencies' => array( |
| 39 | + 'jquery.autoEllipsis', |
| 40 | + 'jquery.byteLength', |
| 41 | + 'jquery.byteLimit', |
| 42 | + 'jquery.client', |
| 43 | + 'jquery.colorUtil', |
| 44 | + 'jquery.getAttrs', |
| 45 | + 'jquery.localize', |
| 46 | + 'jquery.mwExtension', |
| 47 | + 'jquery.tabIndex', |
| 48 | + 'jquery.tablesorter', |
| 49 | + 'jquery.textSelection', |
| 50 | + 'mediawiki', |
| 51 | + 'mediawiki.Title', |
| 52 | + 'mediawiki.user', |
| 53 | + 'mediawiki.util', |
| 54 | + 'mediawiki.special.recentchanges', |
| 55 | + ), |
| 56 | + ) |
| 57 | +); |
Index: branches/JSTesting/includes/SpecialPageFactory.php |
— | — | @@ -138,6 +138,7 @@ |
139 | 139 | 'Blankpage' => 'SpecialBlankpage', |
140 | 140 | 'Blockme' => 'SpecialBlockme', |
141 | 141 | 'Emailuser' => 'SpecialEmailUser', |
| 142 | + 'JavaScriptTest' => 'SpecialJavaScriptTest', |
142 | 143 | 'Movepage' => 'MovePageForm', |
143 | 144 | 'Mycontributions' => 'SpecialMycontributions', |
144 | 145 | 'Mypage' => 'SpecialMypage', |
Index: branches/JSTesting/includes/resourceloader/ResourceLoader.php |
— | — | @@ -37,6 +37,10 @@ |
38 | 38 | |
39 | 39 | /** Associative array mapping module name to info associative array */ |
40 | 40 | protected $moduleInfos = array(); |
| 41 | + |
| 42 | + /** Associative array mapping framework ids to a list of names of test suite modules */ |
| 43 | + /** like array( 'qunit' => array( 'mediawiki.tests.qunit.suites', 'ext.foo.tests', .. ), .. ) */ |
| 44 | + protected $testModuleNames = array(); |
41 | 45 | |
42 | 46 | /** array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) ) **/ |
43 | 47 | protected $sources = array(); |
— | — | @@ -183,7 +187,7 @@ |
184 | 188 | * Registers core modules and runs registration hooks. |
185 | 189 | */ |
186 | 190 | public function __construct() { |
187 | | - global $IP, $wgResourceModules, $wgResourceLoaderSources, $wgLoadScript; |
| 191 | + global $IP, $wgResourceModules, $wgResourceLoaderSources, $wgLoadScript, $wgEnableJavaScriptTest; |
188 | 192 | |
189 | 193 | wfProfileIn( __METHOD__ ); |
190 | 194 | |
— | — | @@ -199,6 +203,32 @@ |
200 | 204 | wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) ); |
201 | 205 | $this->register( $wgResourceModules ); |
202 | 206 | |
| 207 | + if ( $wgEnableJavaScriptTest === true ) { |
| 208 | + |
| 209 | + // Get core test suites |
| 210 | + $testModules = array(); |
| 211 | + $testModules['qunit'] = include( "$IP/tests/qunit/QUnitTestResources.php" ); |
| 212 | + // Get other test suites (e.g. from extensions) |
| 213 | + wfRunHooks( 'ResourceLoaderTestModules', array( &$testModules, &$this ) ); |
| 214 | + |
| 215 | + // Add the testrunner (which configures QUnit) to the dependencies. |
| 216 | + // Since it must be ready before any of the test suites are executed. |
| 217 | + foreach( $testModules['qunit'] as $moduleName => $moduleProps ) { |
| 218 | + $testModules['qunit'][$moduleName]['dependencies'][] = 'mediawiki.tests.qunit.testrunner'; |
| 219 | + } |
| 220 | + |
| 221 | + foreach( $testModules as $id => $names ) { |
| 222 | + // Register test modules |
| 223 | + $this->register( $testModules[$id] ); |
| 224 | + |
| 225 | + // Keep track of their names so that they can be loaded together |
| 226 | + $this->testModuleNames[$id] = array_keys( $testModules[$id] ); |
| 227 | + } |
| 228 | + |
| 229 | + } |
| 230 | + |
| 231 | + |
| 232 | + |
203 | 233 | wfProfileOut( __METHOD__ ); |
204 | 234 | } |
205 | 235 | |
— | — | @@ -305,6 +335,25 @@ |
306 | 336 | public function getModuleNames() { |
307 | 337 | return array_keys( $this->moduleInfos ); |
308 | 338 | } |
| 339 | + |
| 340 | + /** |
| 341 | + * Get a list of test module names for one (or all) frameworks. |
| 342 | + * If the given framework id is unknkown, or if the in-object variable is not an array, |
| 343 | + * then it will return an empty array. |
| 344 | + * |
| 345 | + * @param $framework String: Optional. Get only the test module names for one |
| 346 | + * particular framework. |
| 347 | + * @return Array |
| 348 | + */ |
| 349 | + public function getTestModuleNames( $framework = 'all' ) { |
| 350 | + if ( $framework == 'all' ) { |
| 351 | + return $this->testModuleNames; |
| 352 | + } elseif ( isset( $this->testModuleNames[$framework] ) && is_array( $this->testModuleNames[$framework] ) ) { |
| 353 | + return $this->testModuleNames[$framework]; |
| 354 | + } else { |
| 355 | + return array(); |
| 356 | + } |
| 357 | + } |
309 | 358 | |
310 | 359 | /** |
311 | 360 | * Get the ResourceLoaderModule object for a given module name. |
Index: branches/JSTesting/includes/AutoLoader.php |
— | — | @@ -777,6 +777,7 @@ |
778 | 778 | 'SpecialExport' => 'includes/specials/SpecialExport.php', |
779 | 779 | 'SpecialFilepath' => 'includes/specials/SpecialFilepath.php', |
780 | 780 | 'SpecialImport' => 'includes/specials/SpecialImport.php', |
| 781 | + 'SpecialJavaScriptTest' => 'includes/specials/SpecialJavaScriptTest.php', |
781 | 782 | 'SpecialListFiles' => 'includes/specials/SpecialListfiles.php', |
782 | 783 | 'SpecialListGroupRights' => 'includes/specials/SpecialListgrouprights.php', |
783 | 784 | 'SpecialListUsers' => 'includes/specials/SpecialListusers.php', |
Index: branches/JSTesting/includes/DefaultSettings.php |
— | — | @@ -4151,8 +4151,22 @@ |
4152 | 4152 | * ); |
4153 | 4153 | */ |
4154 | 4154 | $wgParserTestRemote = false; |
| 4155 | + |
| 4156 | +/** |
| 4157 | + * Allow running of javascript test suites via [[Special:JavaScriptTest]] (such as QUnit). |
| 4158 | + */ |
| 4159 | +$wgEnableJavaScriptTest = false; |
4155 | 4160 | |
| 4161 | +/** |
| 4162 | + * Configuration for javascript testing. |
| 4163 | + */ |
| 4164 | +$wgJavaScriptTestConfig = array( |
| 4165 | + 'qunit' => array( |
| 4166 | + 'documentation' => '//www.mediawiki.org/wiki/Manual:JavaScript_unit_testing', |
| 4167 | + ), |
| 4168 | +); |
4156 | 4169 | |
| 4170 | + |
4157 | 4171 | /** |
4158 | 4172 | * Overwrite the caching key prefix with custom value. Do not set if using |
4159 | 4173 | * load balancer, since it depends on the key being in certain format. |
— | — | @@ -5203,6 +5217,7 @@ |
5204 | 5218 | 'Specialpages' => 'other', |
5205 | 5219 | 'Blockme' => 'other', |
5206 | 5220 | 'Booksources' => 'other', |
| 5221 | + 'JavaScriptTest' => 'other', |
5207 | 5222 | ); |
5208 | 5223 | |
5209 | 5224 | /** Whether or not to sort special pages in Special:Specialpages */ |
Index: branches/JSTesting/includes/specials/SpecialJavaScriptTest.php |
— | — | @@ -0,0 +1,124 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class SpecialJavaScriptTest extends SpecialPage { |
| 5 | + |
| 6 | + /** |
| 7 | + * @var $frameworks Array: Mapping of framework ids and their initilizer methods |
| 8 | + * in this class. If a framework is requested but not in this array, |
| 9 | + * the 'unknownframework' error is served. |
| 10 | + */ |
| 11 | + static $frameworks = array( |
| 12 | + 'qunit' => 'initQUnitTesting', |
| 13 | + ); |
| 14 | + |
| 15 | + public function __construct() { |
| 16 | + parent::__construct( 'JavaScriptTest' ); |
| 17 | + } |
| 18 | + |
| 19 | + public function execute( $par ) { |
| 20 | + global $wgEnableJavaScriptTest; |
| 21 | + |
| 22 | + $out = $this->getOutput(); |
| 23 | + |
| 24 | + $this->setHeaders(); |
| 25 | + $out->disallowUserJs(); |
| 26 | + |
| 27 | + // Abort early if we're disabled |
| 28 | + if ( $wgEnableJavaScriptTest !== true ) { |
| 29 | + $out->addWikiMsg( 'javascripttest-disabled' ); |
| 30 | + return; |
| 31 | + } |
| 32 | + |
| 33 | + $out->addModules( 'mediawiki.special.javaScriptTest' ); |
| 34 | + |
| 35 | + // Determine framework |
| 36 | + $pars = explode( '/', $par ); |
| 37 | + $framework = strtolower( $pars[0] ); |
| 38 | + |
| 39 | + // No framework specified |
| 40 | + if ( $par == '' ) { |
| 41 | + $out->setPagetitle( wfMsg( 'javascripttest' ) ); |
| 42 | + $summary = $this->wrapSummaryHtml( |
| 43 | + wfMsg( 'javascripttest-pagetext-noframework' ) . $this->getFrameworkListHtml(), |
| 44 | + 'noframework' |
| 45 | + ); |
| 46 | + $out->addHtml( $summary ); |
| 47 | + |
| 48 | + // Matched! Display proper title and initialize the framework |
| 49 | + } elseif ( isset( self::$frameworks[$framework] ) ) { |
| 50 | + $out->setPagetitle( wfMsg( 'javascripttest-title', wfMsg( "javascripttest-$framework-name" ) ) ); |
| 51 | + $this->{self::$frameworks[$framework]}(); |
| 52 | + |
| 53 | + // Framework not found, display error |
| 54 | + } else { |
| 55 | + $out->setPagetitle( wfMsg( 'javascripttest' ) ); |
| 56 | + $summary = $this->wrapSummaryHtml( '<p class="error">' |
| 57 | + . wfMsg( 'javascripttest-pagetext-unknownframework', $par ) |
| 58 | + . '</p>' |
| 59 | + . $this->getFrameworkListHtml() ); |
| 60 | + $out->addHtml( $summary, 'unknownframework' ); |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Get a list of frameworks (including introduction paragraph and links to the framework run pages) |
| 66 | + * @return String: HTML |
| 67 | + */ |
| 68 | + private function getFrameworkListHtml() { |
| 69 | + $list = '<ul>'; |
| 70 | + foreach( self::$frameworks as $framework => $initFn ) { |
| 71 | + $list .= Html::rawElement( |
| 72 | + 'li', |
| 73 | + array(), |
| 74 | + Linker::link( $this->getTitle( $framework ), wfMsg( "javascripttest-$framework-name" ) ) |
| 75 | + ); |
| 76 | + } |
| 77 | + $list .= '</ul>'; |
| 78 | + $msg = wfMessage( 'javascripttest-pagetext-frameworks' )->rawParams( $list )->parseAsBlock(); |
| 79 | + |
| 80 | + return $msg; |
| 81 | + } |
| 82 | + |
| 83 | + /** |
| 84 | + * Function to wrap the summary. |
| 85 | + * @param $html String: The raw HTML. |
| 86 | + * @param $state String: State, one of 'noframework', 'unknownframework' or 'frameworkfound' |
| 87 | + */ |
| 88 | + private function wrapSummaryHtml( $html = '', $state ) { |
| 89 | + return "<div id=\"mw-javascripttest-summary\" class=\"mw-javascripttest-$state\">$html</div>"; |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Initialize the page for QUnit. |
| 94 | + */ |
| 95 | + private function initQUnitTesting() { |
| 96 | + global $wgJavaScriptTestConfig; |
| 97 | + |
| 98 | + $out = $this->getOutput(); |
| 99 | + |
| 100 | + $out->addModules( 'mediawiki.tests.qunit.testrunner' ); |
| 101 | + $qunitTestModules = $out->getResourceLoader()->getTestModuleNames( 'qunit' ); |
| 102 | + $out->addModules( $qunitTestModules ); |
| 103 | + |
| 104 | + $summary = wfMessage( 'javascripttest-qunit-intro' ) |
| 105 | + ->params( $wgJavaScriptTestConfig['qunit']['documentation'] ) |
| 106 | + ->parseAsBlock(); |
| 107 | + $header = wfMessage( 'javascripttest-qunit-heading' )->escaped(); |
| 108 | + |
| 109 | + $baseHtml = <<<HTML |
| 110 | +<div id="qunit-header">$header</div> |
| 111 | +<div id="qunit-banner"></div> |
| 112 | +<div id="qunit-testrunner-toolbar"></div> |
| 113 | +<div id="qunit-userAgent"></div> |
| 114 | +<ol id="qunit-tests"></ol> |
| 115 | +HTML; |
| 116 | + $out->addHtml( $this->wrapSummaryHtml( $summary, 'frameworkfound' ) . $baseHtml ); |
| 117 | + |
| 118 | + } |
| 119 | + |
| 120 | + public function isListed(){ |
| 121 | + global $wgEnableJavaScriptTest; |
| 122 | + return $wgEnableJavaScriptTest === true; |
| 123 | + } |
| 124 | + |
| 125 | +} |
Index: branches/JSTesting/includes/Skin.php |
— | — | @@ -22,7 +22,7 @@ |
23 | 23 | |
24 | 24 | /** |
25 | 25 | * Fetch the set of available skins. |
26 | | - * @return array of strings |
| 26 | + * @return associative array of strings |
27 | 27 | */ |
28 | 28 | static function getSkinNames() { |
29 | 29 | global $wgValidSkinNames; |
— | — | @@ -55,6 +55,18 @@ |
56 | 56 | } |
57 | 57 | return $wgValidSkinNames; |
58 | 58 | } |
| 59 | + |
| 60 | + /** |
| 61 | + * Fetch the skinname messages for available skins. |
| 62 | + * @return array of strings |
| 63 | + */ |
| 64 | + static function getSkinNameMessages() { |
| 65 | + $messages = array(); |
| 66 | + foreach( self::getSkinNames() as $skinKey => $skinName ) { |
| 67 | + $messages[] = "skinname-$skinKey"; |
| 68 | + } |
| 69 | + return $messages; |
| 70 | + } |
59 | 71 | |
60 | 72 | /** |
61 | 73 | * Fetch the list of usable skins in regards to $wgSkipSkins. |
Index: branches/JSTesting/languages/messages/MessagesQqq.php |
— | — | @@ -2970,6 +2970,16 @@ |
2971 | 2971 | 'import-logentry-upload' => 'This is the text of an entry in the Import log (and Recent Changes), after hour (and date, only in the Import log) and sysop name: |
2972 | 2972 | * $1 is the name of the imported file', |
2973 | 2973 | |
| 2974 | +# JavaScriptTest |
| 2975 | +'javascripttest' => 'Title of the special page', |
| 2976 | +'javascripttest-disabled' => '{{Identical|Function disabled}}.', |
| 2977 | +'javascripttest-title' => 'Title of the special page when running a test suite. $1 is the name of the framework.', |
| 2978 | +'javascripttest-pagetext-unknownframework' => 'Error message when given framework id is not found. $1 is the if of the framework.', |
| 2979 | +'javascripttest-pagetext-frameworks' => '$1 is the if of the framework.', |
| 2980 | +'javascripttest-qunit-name' => '{{Ignore}}', |
| 2981 | +'javascripttest-qunit-intro' => '$1 is the configured url to the documentation.', |
| 2982 | +'javascripttest-qunit-heading' => '{{Optional}}', |
| 2983 | + |
2974 | 2984 | # Tooltip help for the actions |
2975 | 2985 | 'tooltip-pt-userpage' => 'This text appears in the tool-tip when you hover the mouse over your the tab with you User name on it', |
2976 | 2986 | 'tooltip-pt-mytalk' => 'Tooltip shown when hovering over the "my talk" link in your personal toolbox (upper right side).', |
Index: branches/JSTesting/languages/messages/MessagesEn.php |
— | — | @@ -392,6 +392,7 @@ |
393 | 393 | 'Filepath' => array( 'FilePath' ), |
394 | 394 | 'Import' => array( 'Import' ), |
395 | 395 | 'Invalidateemail' => array( 'InvalidateEmail' ), |
| 396 | + 'JavaScriptTest' => array( 'JavaScriptTest' ), |
396 | 397 | 'BlockList' => array( 'BlockList', 'ListBlocks', 'IPBlockList' ), |
397 | 398 | 'LinkSearch' => array( 'LinkSearch' ), |
398 | 399 | 'Listadmins' => array( 'ListAdmins' ), |
— | — | @@ -3368,6 +3369,18 @@ |
3369 | 3370 | 'import-logentry-upload-detail' => '$1 {{PLURAL:$1|revision|revisions}}', |
3370 | 3371 | 'import-logentry-interwiki' => 'transwikied $1', |
3371 | 3372 | 'import-logentry-interwiki-detail' => '$1 {{PLURAL:$1|revision|revisions}} from $2', |
| 3373 | + |
| 3374 | +# JavaScriptTest |
| 3375 | +'javascripttest' => 'JavaScript Test', |
| 3376 | +'javascripttest-disabled' => 'This function is disabled.', |
| 3377 | +'javascripttest-title' => 'Running $1 tests', |
| 3378 | +'javascripttest-pagetext-noframework' => 'This page is reserved for running javascript tests.', |
| 3379 | +'javascripttest-pagetext-unknownframework' => 'Unknown framework "$1".', |
| 3380 | +'javascripttest-pagetext-frameworks' => 'Please choose one of the following frameworks: $1', |
| 3381 | +'javascripttest-pagetext-skins' => 'Available skins', |
| 3382 | +'javascripttest-qunit-name' => 'QUnit', // Ignore, do not translate |
| 3383 | +'javascripttest-qunit-intro' => 'See [$1 testing documentation] on mediawiki.org.', |
| 3384 | +'javascripttest-qunit-heading' => 'MediaWiki JavaScript QUnit Test Suite', // Optional, only translate if needed |
3372 | 3385 | |
3373 | 3386 | # Keyboard access keys for power users |
3374 | 3387 | 'accesskey-pt-userpage' => '.', # do not translate or duplicate this message to other languages |
Index: branches/JSTesting/resources/Resources.php |
— | — | @@ -173,6 +173,7 @@ |
174 | 174 | ), |
175 | 175 | 'jquery.qunit.completenessTest' => array( |
176 | 176 | 'scripts' => 'resources/jquery/jquery.qunit.completenessTest.js', |
| 177 | + 'dependencies' => 'jquery.qunit', |
177 | 178 | ), |
178 | 179 | 'jquery.spinner' => array( |
179 | 180 | 'scripts' => 'resources/jquery/jquery.spinner.js', |
— | — | @@ -688,7 +689,26 @@ |
689 | 690 | ), |
690 | 691 | 'dependencies' => array( 'mediawiki.libs.jpegmeta' ), |
691 | 692 | ), |
| 693 | + 'mediawiki.special.javaScriptTest' => array( |
| 694 | + 'scripts' => 'resources/mediawiki.special/mediawiki.special.javaScriptTest.js', |
| 695 | + 'messages' => array_merge( Skin::getSkinNameMessages(), array( |
| 696 | + 'colon-separator', |
| 697 | + 'javascripttest-pagetext-skins', |
| 698 | + ) ), |
| 699 | + 'dependencies' => array( 'jquery.qunit' ), |
| 700 | + ), |
692 | 701 | |
| 702 | + /* Tests */ |
| 703 | + |
| 704 | + 'mediawiki.tests.qunit.testrunner' => array( |
| 705 | + 'scripts' => 'tests/qunit/data/testrunner.js', |
| 706 | + 'dependencies' => array( |
| 707 | + 'jquery.qunit', |
| 708 | + 'jquery.qunit.completenessTest', |
| 709 | + ), |
| 710 | + 'position' => 'top', |
| 711 | + ), |
| 712 | + |
693 | 713 | /* MediaWiki Legacy */ |
694 | 714 | |
695 | 715 | 'mediawiki.legacy.ajax' => array( |
Index: branches/JSTesting/resources/mediawiki.special/mediawiki.special.javaScriptTest.js |
— | — | @@ -0,0 +1,33 @@ |
| 2 | +/* |
| 3 | + * JavaScript for Special:JavaScriptTest |
| 4 | + */ |
| 5 | +jQuery( document ).ready( function( $ ) { |
| 6 | + |
| 7 | + // Create useskin dropdown menu and reload onchange to the selected skin |
| 8 | + // (only if a framework was found, not on error pages). |
| 9 | + $( '#mw-javascripttest-summary.mw-javascripttest-frameworkfound' ).append( function() { |
| 10 | + |
| 11 | + var $html = $( '<p><label for="useskin">' |
| 12 | + + mw.message( 'javascripttest-pagetext-skins' ).escaped() |
| 13 | + + mw.message( 'colon-separator' ).plain() |
| 14 | + + '</label></p>' ), |
| 15 | + select = '<select name="useskin" id="useskin">'; |
| 16 | + |
| 17 | + // Build <select> further |
| 18 | + $.each( mw.config.get( 'wgAvailableSkins' ), function( id ) { |
| 19 | + select += '<option value="' + id + '"' |
| 20 | + + ( mw.config.get( 'skin' ) === id ? ' selected="selected"' : '' ) |
| 21 | + + '>' + mw.message( 'skinname-' + id ).escaped() + '</option>'; |
| 22 | + } ); |
| 23 | + select += '</select>'; |
| 24 | + |
| 25 | + // Bind onchange event handler and append to form |
| 26 | + $html.append( |
| 27 | + $( select ).change( function() { |
| 28 | + window.location = QUnit.url( { useskin: $(this).val() } ); |
| 29 | + } ) |
| 30 | + ); |
| 31 | + |
| 32 | + return $html; |
| 33 | + } ); |
| 34 | +} ); |