Merge "fix docu for ApiCheckCanExecute"
[lhc/web/wiklou.git] / includes / specials / SpecialJavaScriptTest.php
1 <?php
2 /**
3 * Implements Special:JavaScriptTest
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup SpecialPage
22 */
23
24 /**
25 * @ingroup SpecialPage
26 */
27 class SpecialJavaScriptTest extends SpecialPage {
28
29 /**
30 * @var $frameworks Array: Mapping of framework ids and their initilizer methods
31 * in this class. If a framework is requested but not in this array,
32 * the 'unknownframework' error is served.
33 */
34 static $frameworks = array(
35 'qunit' => 'initQUnitTesting',
36 );
37
38 public function __construct() {
39 parent::__construct( 'JavaScriptTest' );
40 }
41
42 public function execute( $par ) {
43 global $wgEnableJavaScriptTest;
44
45 $out = $this->getOutput();
46
47 $this->setHeaders();
48 $out->disallowUserJs();
49
50 // Abort early if we're disabled
51 if ( $wgEnableJavaScriptTest !== true ) {
52 $out->addWikiMsg( 'javascripttest-disabled' );
53 return;
54 }
55
56 $out->addModules( 'mediawiki.special.javaScriptTest' );
57
58 // Determine framework
59 $pars = explode( '/', $par );
60 $framework = strtolower( $pars[0] );
61
62 // No framework specified
63 if ( $par == '' ) {
64 $out->setPageTitle( $this->msg( 'javascripttest' ) );
65 $summary = $this->wrapSummaryHtml(
66 $this->msg( 'javascripttest-pagetext-noframework' )->escaped() . $this->getFrameworkListHtml(),
67 'noframework'
68 );
69 $out->addHtml( $summary );
70
71 // Matched! Display proper title and initialize the framework
72 } elseif ( isset( self::$frameworks[$framework] ) ) {
73 $out->setPageTitle( $this->msg( 'javascripttest-title', $this->msg( "javascripttest-$framework-name" )->plain() ) );
74 $out->setSubtitle( $this->msg( 'javascripttest-backlink' )->rawParams( Linker::linkKnown( $this->getTitle() ) ) );
75 $this->{self::$frameworks[$framework]}();
76
77 // Framework not found, display error
78 } else {
79 $out->setPageTitle( $this->msg( 'javascripttest' ) );
80 $summary = $this->wrapSummaryHtml( '<p class="error">'
81 . $this->msg( 'javascripttest-pagetext-unknownframework', $par )->escaped()
82 . '</p>'
83 . $this->getFrameworkListHtml(),
84 'unknownframework'
85 );
86 $out->addHtml( $summary );
87 }
88 }
89
90 /**
91 * Get a list of frameworks (including introduction paragraph and links to the framework run pages)
92 * @return String: HTML
93 */
94 private function getFrameworkListHtml() {
95 $list = '<ul>';
96 foreach( self::$frameworks as $framework => $initFn ) {
97 $list .= Html::rawElement(
98 'li',
99 array(),
100 Linker::link( $this->getTitle( $framework ), $this->msg( "javascripttest-$framework-name" )->escaped() )
101 );
102 }
103 $list .= '</ul>';
104 $msg = $this->msg( 'javascripttest-pagetext-frameworks' )->rawParams( $list )->parseAsBlock();
105
106 return $msg;
107 }
108
109 /**
110 * Function to wrap the summary.
111 * It must be given a valid state as a second parameter or an exception will
112 * be thrown.
113 * @param $html String: The raw HTML.
114 * @param $state String: State, one of 'noframework', 'unknownframework' or 'frameworkfound'
115 * @return string
116 */
117 private function wrapSummaryHtml( $html, $state ) {
118 $validStates = array( 'noframework', 'unknownframework', 'frameworkfound' );
119 if( !in_array( $state, $validStates ) ) {
120 throw new MWException( __METHOD__
121 . ' given an invalid state. Must be one of "'
122 . join( '", "', $validStates) . '".'
123 );
124 }
125 return "<div id=\"mw-javascripttest-summary\" class=\"mw-javascripttest-$state\">$html</div>";
126 }
127
128 /**
129 * Initialize the page for QUnit.
130 */
131 private function initQUnitTesting() {
132 global $wgJavaScriptTestConfig;
133
134 $out = $this->getOutput();
135
136 $out->addModules( 'mediawiki.tests.qunit.testrunner' );
137 $qunitTestModules = $out->getResourceLoader()->getTestModuleNames( 'qunit' );
138 $out->addModules( $qunitTestModules );
139
140 $summary = $this->msg( 'javascripttest-qunit-intro' )
141 ->params( $wgJavaScriptTestConfig['qunit']['documentation'] )
142 ->parseAsBlock();
143 $header = $this->msg( 'javascripttest-qunit-heading' )->escaped();
144 $userDir = $this->getLanguage()->getDir();
145
146 $baseHtml = <<<HTML
147 <div class="mw-content-ltr">
148 <div id="qunit-header"><span dir="$userDir">$header</span></div>
149 <div id="qunit-banner"></div>
150 <div id="qunit-testrunner-toolbar"></div>
151 <div id="qunit-userAgent"></div>
152 <ol id="qunit-tests"></ol>
153 <div id="qunit-fixture">test markup, will be hidden</div>
154 </div>
155 HTML;
156 $out->addHtml( $this->wrapSummaryHtml( $summary, 'frameworkfound' ) . $baseHtml );
157
158 // This special page is disabled by default ($wgEnableJavaScriptTest), and contains
159 // no sensitive data. In order to allow TestSwarm to embed it into a test client window,
160 // we need to allow iframing of this page.
161 $out->allowClickjacking();
162
163 // Used in ./tests/qunit/data/testrunner.js, see also documentation of
164 // $wgJavaScriptTestConfig in DefaultSettings.php
165 $out->addJsConfigVars( 'QUnitTestSwarmInjectJSPath', $wgJavaScriptTestConfig['qunit']['testswarm-injectjs'] );
166 }
167
168 public function isListed(){
169 global $wgEnableJavaScriptTest;
170 return $wgEnableJavaScriptTest === true;
171 }
172
173 }