566152e4c14ff935132cf22becfc8d500b897b20
[lhc/web/wiklou.git] / tests / phpunit / includes / HtmlTest.php
1 <?php
2 /** tests for includes/Html.php */
3
4 class HtmlTest extends MediaWikiTestCase {
5 private static $oldLang;
6 private static $oldContLang;
7 private static $oldLanguageCode;
8 private static $oldNamespaces;
9
10 public function setUp() {
11 global $wgLang, $wgContLang, $wgLanguageCode;
12
13 self::$oldLang = $wgLang;
14 self::$oldContLang = $wgContLang;
15 self::$oldNamespaces = $wgContLang->getNamespaces();
16 self::$oldLanguageCode = $wgLanguageCode;
17
18 $wgLanguageCode = 'en';
19 $wgContLang = $wgLang = Language::factory( $wgLanguageCode );
20
21 // Hardcode namespaces during test runs,
22 // so that html output based on existing namespaces
23 // can be properly evaluated.
24 $wgContLang->setNamespaces( array(
25 -2 => 'Media',
26 -1 => 'Special',
27 0 => '',
28 1 => 'Talk',
29 2 => 'User',
30 3 => 'User_talk',
31 4 => 'MyWiki',
32 5 => 'MyWiki_Talk',
33 6 => 'File',
34 7 => 'File_talk',
35 8 => 'MediaWiki',
36 9 => 'MediaWiki_talk',
37 10 => 'Template',
38 11 => 'Template_talk',
39 14 => 'Category',
40 15 => 'Category_talk',
41 100 => 'Custom',
42 101 => 'Custom_talk',
43 ) );
44 }
45
46 public function tearDown() {
47 global $wgLang, $wgContLang, $wgLanguageCode;
48
49 $wgContLang->setNamespaces( self::$oldNamespaces );
50 $wgLang = self::$oldLang;
51 $wgContLang = self::$oldContLang;
52 $wgLanguageCode = self::$oldLanguageCode;
53 }
54
55 public function testExpandAttributesSkipsNullAndFalse() {
56
57 ### EMPTY ########
58 $this->AssertEmpty(
59 Html::expandAttributes( array( 'foo' => null ) ),
60 'skip keys with null value'
61 );
62 $this->AssertEmpty(
63 Html::expandAttributes( array( 'foo' => false ) ),
64 'skip keys with false value'
65 );
66 $this->AssertNotEmpty(
67 Html::expandAttributes( array( 'foo' => '' ) ),
68 'keep keys with an empty string'
69 );
70 }
71
72 public function testExpandAttributesForBooleans() {
73 global $wgHtml5;
74 $this->AssertEquals(
75 '',
76 Html::expandAttributes( array( 'selected' => false ) ),
77 'Boolean attributes do not generates output when value is false'
78 );
79 $this->AssertEquals(
80 '',
81 Html::expandAttributes( array( 'selected' => null ) ),
82 'Boolean attributes do not generates output when value is null'
83 );
84
85 $this->AssertEquals(
86 $wgHtml5 ? ' selected=""' : ' selected="selected"',
87 Html::expandAttributes( array( 'selected' => true ) ),
88 'Boolean attributes skip value output'
89 );
90 $this->AssertEquals(
91 $wgHtml5 ? ' selected=""' : ' selected="selected"',
92 Html::expandAttributes( array( 'selected' ) ),
93 'Boolean attributes (ex: selected) do not need a value'
94 );
95 }
96
97 /**
98 * Test for Html::expandAttributes()
99 * Please note it output a string prefixed with a space!
100 */
101 public function testExpandAttributesVariousExpansions() {
102 ### NOT EMPTY ####
103 $this->AssertEquals(
104 ' empty_string=""',
105 Html::expandAttributes( array( 'empty_string' => '' ) ),
106 'Value with an empty string'
107 );
108 $this->AssertEquals(
109 ' key="value"',
110 Html::expandAttributes( array( 'key' => 'value' ) ),
111 'Value is a string'
112 );
113 $this->AssertEquals(
114 ' one="1"',
115 Html::expandAttributes( array( 'one' => 1 ) ),
116 'Value is a numeric one'
117 );
118 $this->AssertEquals(
119 ' zero="0"',
120 Html::expandAttributes( array( 'zero' => 0 ) ),
121 'Value is a numeric zero'
122 );
123 }
124
125 /**
126 * Html::expandAttributes has special features for HTML
127 * attributes that use space separated lists and also
128 * allows arrays to be used as values.
129 */
130 public function testExpandAttributesListValueAttributes() {
131 ### STRING VALUES
132 $this->AssertEquals(
133 ' class="redundant spaces here"',
134 Html::expandAttributes( array( 'class' => ' redundant spaces here ' ) ),
135 'Normalization should strip redundant spaces'
136 );
137 $this->AssertEquals(
138 ' class="foo bar"',
139 Html::expandAttributes( array( 'class' => 'foo bar foo bar bar' ) ),
140 'Normalization should remove duplicates in string-lists'
141 );
142 ### "EMPTY" ARRAY VALUES
143 $this->AssertEquals(
144 ' class=""',
145 Html::expandAttributes( array( 'class' => array() ) ),
146 'Value with an empty array'
147 );
148 $this->AssertEquals(
149 ' class=""',
150 Html::expandAttributes( array( 'class' => array( null, '', ' ', ' ' ) ) ),
151 'Array with null, empty string and spaces'
152 );
153 ### NON-EMPTY ARRAY VALUES
154 $this->AssertEquals(
155 ' class="foo bar"',
156 Html::expandAttributes( array( 'class' => array(
157 'foo',
158 'bar',
159 'foo',
160 'bar',
161 'bar',
162 ) ) ),
163 'Normalization should remove duplicates in the array'
164 );
165 $this->AssertEquals(
166 ' class="foo bar"',
167 Html::expandAttributes( array( 'class' => array(
168 'foo bar',
169 'bar foo',
170 'foo',
171 'bar bar',
172 ) ) ),
173 'Normalization should remove duplicates in string-lists in the array'
174 );
175 }
176
177 /**
178 * Test feature added by r96188, let pass attributes values as
179 * a PHP array. Restricted to class,rel, accesskey.
180 */
181 function testExpandAttributesSpaceSeparatedAttributesWithBoolean() {
182 $this->assertEquals(
183 ' class="booltrue one"',
184 Html::expandAttributes( array( 'class' => array(
185 'booltrue' => true,
186 'one' => 1,
187
188 # Method use isset() internally, make sure we do discard
189 # attributes values which have been assigned well known values
190 'emptystring' => '',
191 'boolfalse' => false,
192 'zero' => 0,
193 'null' => null,
194 )))
195 );
196 }
197
198 /**
199 * How do we handle duplicate keys in HTML attributes expansion?
200 * We could pass a "class" the values: 'GREEN' and array( 'GREEN' => false )
201 * The later will take precedence.
202 *
203 * Feature added by r96188
204 */
205 function testValueIsAuthoritativeInSpaceSeparatedAttributesArrays() {
206 $this->assertEquals(
207 ' class=""',
208 Html::expandAttributes( array( 'class' => array(
209 'GREEN',
210 'GREEN' => false,
211 'GREEN',
212 )))
213 );
214 }
215
216 function testNamespaceSelector() {
217 global $wgContLang;
218
219 $this->assertEquals(
220 '<select id="namespace" name="namespace">' . "\n" .
221 '<option value="0">(Main)</option>' . "\n" .
222 '<option value="1">Talk</option>' . "\n" .
223 '<option value="2">User</option>' . "\n" .
224 '<option value="3">User talk</option>' . "\n" .
225 '<option value="4">MyWiki</option>' . "\n" .
226 '<option value="5">MyWiki Talk</option>' . "\n" .
227 '<option value="6">File</option>' . "\n" .
228 '<option value="7">File talk</option>' . "\n" .
229 '<option value="8">MediaWiki</option>' . "\n" .
230 '<option value="9">MediaWiki talk</option>' . "\n" .
231 '<option value="10">Template</option>' . "\n" .
232 '<option value="11">Template talk</option>' . "\n" .
233 '<option value="14">Category</option>' . "\n" .
234 '<option value="15">Category talk</option>' . "\n" .
235 '<option value="100">Custom</option>' . "\n" .
236 '<option value="101">Custom talk</option>' . "\n" .
237 '</select>',
238 Html::namespaceSelector(),
239 'Basic namespace selector without custom options'
240 );
241 $this->assertEquals(
242 '<label for="mw-test-namespace">Select a namespace:</label>&#160;' .
243 '<select id="mw-test-namespace" name="wpNamespace">' . "\n" .
244 '<option value="all">all</option>' . "\n" .
245 '<option value="0">(Main)</option>' . "\n" .
246 '<option value="1">Talk</option>' . "\n" .
247 '<option value="2" selected="">User</option>' . "\n" .
248 '<option value="3">User talk</option>' . "\n" .
249 '<option value="4">MyWiki</option>' . "\n" .
250 '<option value="5">MyWiki Talk</option>' . "\n" .
251 '<option value="6">File</option>' . "\n" .
252 '<option value="7">File talk</option>' . "\n" .
253 '<option value="8">MediaWiki</option>' . "\n" .
254 '<option value="9">MediaWiki talk</option>' . "\n" .
255 '<option value="10">Template</option>' . "\n" .
256 '<option value="11">Template talk</option>' . "\n" .
257 '<option value="14">Category</option>' . "\n" .
258 '<option value="15">Category talk</option>' . "\n" .
259 '<option value="100">Custom</option>' . "\n" .
260 '<option value="101">Custom talk</option>' . "\n" .
261 '</select>',
262 Html::namespaceSelector(
263 array( 'selected' => '2', 'all' => 'all', 'label' => 'Select a namespace:' ),
264 array( 'name' => 'wpNamespace', 'id' => 'mw-test-namespace' )
265 ),
266 'Basic namespace selector with custom values'
267 );
268 $immovable = array();
269 $namespaces = $wgContLang->getNamespaces();
270 foreach ( $namespaces as $nsId => $nsName ) {
271 if ( !MWNamespace::isMovable( intval( $nsId ) ) ) {
272 $immovable[] = $nsId;
273 }
274 }
275 $this->assertEquals(
276 '<select id="namespace" name="namespace">' . "\n" .
277 '<option value="0">(Main)</option>' . "\n" .
278 '<option value="1">Talk</option>' . "\n" .
279 '<option value="2">User</option>' . "\n" .
280 '<option value="3">User talk</option>' . "\n" .
281 '<option value="4">MyWiki</option>' . "\n" .
282 '<option value="5">MyWiki Talk</option>' . "\n" .
283 '<option value="6">File</option>' . "\n" .
284 '<option value="7">File talk</option>' . "\n" .
285 '<option value="8">MediaWiki</option>' . "\n" .
286 '<option value="9">MediaWiki talk</option>' . "\n" .
287 '<option value="10">Template</option>' . "\n" .
288 '<option value="11">Template talk</option>' . "\n" .
289 '<option disabled="" value="14">Category</option>' . "\n" .
290 '<option value="15">Category talk</option>' . "\n" .
291 '</select>',
292 Html::namespaceSelector(
293 array( 'exclude' => array( 100, 101 ), 'disable' => $immovable )
294 ),
295 'Namespace selector without the custom namespace and immovable namespaces disabled.'
296 );
297 }
298
299 function testNamespaceSelectorIdAndNameDefaultsAttributes() {
300
301 $this->assertNsSelectorIdAndName(
302 'namespace', 'namespace',
303 Html::namespaceSelector( array(), array(
304 # neither 'id' nor 'name' key given
305 )),
306 "Neither 'id' nor 'name' key given"
307 );
308
309 $this->assertNsSelectorIdAndName(
310 'namespace', 'select_name',
311 Html::namespaceSelector( array(), array(
312 'name' => 'select_name',
313 # no 'id' key given
314 )),
315 "No 'id' key given, 'name' given"
316 );
317
318 $this->assertNsSelectorIdAndName(
319 'select_id', 'namespace',
320 Html::namespaceSelector( array(), array(
321 'id' => 'select_id',
322 # no 'name' key given
323 )),
324 "'id' given, no 'name' key given"
325 );
326
327 $this->assertNsSelectorIdAndName(
328 'select_id', 'select_name',
329 Html::namespaceSelector( array(), array(
330 'id' => 'select_id',
331 'name' => 'select_name',
332 )),
333 "Both 'id' and 'name' given"
334 );
335 }
336
337 /**
338 * Helper to verify <select> attributes generated by Html::namespaceSelector()
339 * This helper expect the Html method to use 'namespace' as a default value for
340 * both 'id' and 'name' attributes.
341 *
342 * @param String $expectedId <select> id attribute value
343 * @param String $expectedName <select> name attribute value
344 * @param String $html Output of a call to Html::namespaceSelector()
345 * @param String $msg Optional message (default: '')
346 */
347 function assertNsSelectorIdAndName( $expectedId, $expectedName, $html, $msg = '' ) {
348 $actualId = 'namespace';
349 if( 1 === preg_match( '/id="(.+?)"/', $html, $m ) ) {
350 $actualId = $m[1];
351 }
352
353 $actualName = 'namespace';
354 if( 1 === preg_match( '/name="(.+?)"/', $html, $m ) ) {
355 $actualName = $m[1];
356 }
357 $this->assertEquals(
358 array( #expected
359 'id' => $expectedId,
360 'name' => $expectedName,
361 ),
362 array( #actual
363 'id' => $actualId,
364 'name' => $actualName,
365 ),
366 'Html::namespaceSelector() got wrong id and/or name attribute(s). ' . $msg
367 );
368 }
369
370 }