[Html] Follow-up r109990: Add category to example namespaces
[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 $this->assertEquals(
218 '<select id="namespace" name="namespace">' . "\n" .
219 '<option value="0">(Main)</option>' . "\n" .
220 '<option value="1">Talk</option>' . "\n" .
221 '<option value="2">User</option>' . "\n" .
222 '<option value="3">User talk</option>' . "\n" .
223 '<option value="4">MyWiki</option>' . "\n" .
224 '<option value="5">MyWiki Talk</option>' . "\n" .
225 '<option value="6">File</option>' . "\n" .
226 '<option value="7">File talk</option>' . "\n" .
227 '<option value="8">MediaWiki</option>' . "\n" .
228 '<option value="9">MediaWiki talk</option>' . "\n" .
229 '<option value="10">Template</option>' . "\n" .
230 '<option value="11">Template talk</option>' . "\n" .
231 '<option value="14">Category</option>' . "\n" .
232 '<option value="15">Category talk</option>' . "\n" .
233 '<option value="100">Custom</option>' . "\n" .
234 '<option value="101">Custom talk</option>' . "\n" .
235 '</select>',
236 Html::namespaceSelector(),
237 'Basic namespace selector without custom options'
238 );
239 $this->assertEquals(
240 '<label for="mw-test-namespace">Select a namespace:</label>&#160;' .
241 '<select id="mw-test-namespace" name="wpNamespace">' . "\n" .
242 '<option value="all">all</option>' . "\n" .
243 '<option value="0">(Main)</option>' . "\n" .
244 '<option value="1">Talk</option>' . "\n" .
245 '<option value="2" selected="">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 array( 'selected' => '2', 'all' => 'all', 'label' => 'Select a namespace:' ),
262 array( 'name' => 'wpNamespace', 'id' => 'mw-test-namespace' )
263 ),
264 'Basic namespace selector with custom values'
265 );
266 }
267
268 function testNamespaceSelectorIdAndNameDefaultsAttributes() {
269
270 $this->assertNsSelectorIdAndName(
271 'namespace', 'namespace',
272 Html::namespaceSelector( array(), array(
273 # neither 'id' nor 'name' key given
274 )),
275 "Neither 'id' nor 'name' key given"
276 );
277
278 $this->assertNsSelectorIdAndName(
279 'namespace', 'select_name',
280 Html::namespaceSelector( array(), array(
281 'name' => 'select_name',
282 # no 'id' key given
283 )),
284 "No 'id' key given, 'name' given"
285 );
286
287 $this->assertNsSelectorIdAndName(
288 'select_id', 'namespace',
289 Html::namespaceSelector( array(), array(
290 'id' => 'select_id',
291 # no 'name' key given
292 )),
293 "'id' given, no 'name' key given"
294 );
295
296 $this->assertNsSelectorIdAndName(
297 'select_id', 'select_name',
298 Html::namespaceSelector( array(), array(
299 'id' => 'select_id',
300 'name' => 'select_name',
301 )),
302 "Both 'id' and 'name' given"
303 );
304 }
305
306 /**
307 * Helper to verify <select> attributes generated by Html::namespaceSelector()
308 * This helper expect the Html method to use 'namespace' as a default value for
309 * both 'id' and 'name' attributes.
310 *
311 * @param String $expectedId <select> id attribute value
312 * @param String $expectedName <select> name attribute value
313 * @param String $html Output of a call to Html::namespaceSelector()
314 * @param String $msg Optional message (default: '')
315 */
316 function assertNsSelectorIdAndName( $expectedId, $expectedName, $html, $msg = '' ) {
317 $actualId = 'namespace';
318 if( 1 === preg_match( '/id="(.+?)"/', $html, $m ) ) {
319 $actualId = $m[1];
320 }
321
322 $actualName = 'namespace';
323 if( 1 === preg_match( '/name="(.+?)"/', $html, $m ) ) {
324 $actualName = $m[1];
325 }
326 $this->assertEquals(
327 array( #expected
328 'id' => $expectedId,
329 'name' => $expectedName,
330 ),
331 array( #actual
332 'id' => $actualId,
333 'name' => $actualName,
334 ),
335 'Html::namespaceSelector() got wrong id and/or name attribute(s). ' . $msg
336 );
337 }
338
339 }