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