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