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