Don't pass Config to NamespaceInfo
[lhc/web/wiklou.git] / tests / phpunit / includes / title / NamespaceInfoTest.php
1 <?php
2 /**
3 * @author Antoine Musso
4 * @copyright Copyright © 2011, Antoine Musso
5 * @file
6 */
7
8 use MediaWiki\Config\ServiceOptions;
9
10 class NamespaceInfoTest extends MediaWikiTestCase {
11 private function newObj( array $options = [] ) : NamespaceInfo {
12 $defaults = [
13 'AllowImageMoving' => true,
14 'CanonicalNamespaceNames' => [
15 NS_TALK => 'Talk',
16 NS_USER => 'User',
17 NS_USER_TALK => 'User_talk',
18 NS_SPECIAL => 'Special',
19 NS_MEDIA => 'Media',
20 ],
21 'CapitalLinkOverrides' => [],
22 'CapitalLinks' => true,
23 'ContentNamespaces' => [ NS_MAIN ],
24 'ExtraNamespaces' => [],
25 'ExtraSignatureNamespaces' => [],
26 'NamespaceContentModels' => [],
27 'NamespaceProtection' => [],
28 'NamespacesWithSubpages' => [
29 NS_TALK => true,
30 NS_USER => true,
31 NS_USER_TALK => true,
32 ],
33 'NonincludableNamespaces' => [],
34 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop' ],
35 ];
36 return new NamespaceInfo(
37 new ServiceOptions( NamespaceInfo::$constructorOptions, $options, $defaults ) );
38 }
39
40 /**
41 * @todo Write more tests, handle $wgAllowImageMoving setting
42 * @covers NamespaceInfo::isMovable
43 */
44 public function testIsMovable() {
45 $this->assertFalse( $this->newObj()->isMovable( NS_SPECIAL ) );
46 }
47
48 private function assertIsSubject( $ns ) {
49 $this->assertTrue( $this->newObj()->isSubject( $ns ) );
50 }
51
52 private function assertIsNotSubject( $ns ) {
53 $this->assertFalse(
54 $this->newObj()->isSubject( $ns ) );
55 }
56
57 /**
58 * @param int $ns
59 * @param bool $expected
60 * @dataProvider provideIsSubject
61 * @covers NamespaceInfo::isSubject
62 */
63 public function testIsSubject( $ns, $expected ) {
64 $this->assertSame( $expected, $this->newObj()->isSubject( $ns ) );
65 }
66
67 /**
68 * @param int $ns
69 * @param bool $expected
70 * @dataProvider provideIsSubject
71 * @covers NamespaceInfo::isTalk
72 */
73 public function testIsTalk( $ns, $expected ) {
74 $this->assertSame( !$expected, $this->newObj()->isTalk( $ns ) );
75 }
76
77 public function provideIsSubject() {
78 return [
79 // Special namespaces
80 [ NS_MEDIA, true ],
81 [ NS_SPECIAL, true ],
82
83 // Subject pages
84 [ NS_MAIN, true ],
85 [ NS_USER, true ],
86 [ 100, true ],
87
88 // Talk pages
89 [ NS_TALK, false ],
90 [ NS_USER_TALK, false ],
91 [ 101, false ],
92 ];
93 }
94
95 /**
96 * @covers NamespaceInfo::getSubject
97 */
98 public function testGetSubject() {
99 // Special namespaces are their own subjects
100 $obj = $this->newObj();
101 $this->assertEquals( NS_MEDIA, $obj->getSubject( NS_MEDIA ) );
102 $this->assertEquals( NS_SPECIAL, $obj->getSubject( NS_SPECIAL ) );
103
104 $this->assertEquals( NS_MAIN, $obj->getSubject( NS_TALK ) );
105 $this->assertEquals( NS_USER, $obj->getSubject( NS_USER_TALK ) );
106 }
107
108 /**
109 * Regular getTalk() calls
110 * Namespaces without a talk page (NS_MEDIA, NS_SPECIAL) are tested in
111 * the function testGetTalkExceptions()
112 * @covers NamespaceInfo::getTalk
113 */
114 public function testGetTalk() {
115 $obj = $this->newObj();
116 $this->assertEquals( NS_TALK, $obj->getTalk( NS_MAIN ) );
117 $this->assertEquals( NS_TALK, $obj->getTalk( NS_TALK ) );
118 $this->assertEquals( NS_USER_TALK, $obj->getTalk( NS_USER ) );
119 $this->assertEquals( NS_USER_TALK, $obj->getTalk( NS_USER_TALK ) );
120 }
121
122 /**
123 * Exceptions with getTalk()
124 * NS_MEDIA does not have talk pages. MediaWiki raise an exception for them.
125 * @expectedException MWException
126 * @covers NamespaceInfo::getTalk
127 */
128 public function testGetTalkExceptionsForNsMedia() {
129 $this->assertNull( $this->newObj()->getTalk( NS_MEDIA ) );
130 }
131
132 /**
133 * Exceptions with getTalk()
134 * NS_SPECIAL does not have talk pages. MediaWiki raise an exception for them.
135 * @expectedException MWException
136 * @covers NamespaceInfo::getTalk
137 */
138 public function testGetTalkExceptionsForNsSpecial() {
139 $this->assertNull( $this->newObj()->getTalk( NS_SPECIAL ) );
140 }
141
142 /**
143 * Regular getAssociated() calls
144 * Namespaces without an associated page (NS_MEDIA, NS_SPECIAL) are tested in
145 * the function testGetAssociatedExceptions()
146 * @covers NamespaceInfo::getAssociated
147 */
148 public function testGetAssociated() {
149 $this->assertEquals( NS_TALK, $this->newObj()->getAssociated( NS_MAIN ) );
150 $this->assertEquals( NS_MAIN, $this->newObj()->getAssociated( NS_TALK ) );
151 }
152
153 # ## Exceptions with getAssociated()
154 # ## NS_MEDIA and NS_SPECIAL do not have talk pages. MediaWiki raises
155 # ## an exception for them.
156 /**
157 * @expectedException MWException
158 * @covers NamespaceInfo::getAssociated
159 */
160 public function testGetAssociatedExceptionsForNsMedia() {
161 $this->assertNull( $this->newObj()->getAssociated( NS_MEDIA ) );
162 }
163
164 /**
165 * @expectedException MWException
166 * @covers NamespaceInfo::getAssociated
167 */
168 public function testGetAssociatedExceptionsForNsSpecial() {
169 $this->assertNull( $this->newObj()->getAssociated( NS_SPECIAL ) );
170 }
171
172 /**
173 * Note if we add a namespace registration system with keys like 'MAIN'
174 * we should add tests here for equivilance on things like 'MAIN' == 0
175 * and 'MAIN' == NS_MAIN.
176 * @covers NamespaceInfo::equals
177 */
178 public function testEquals() {
179 $obj = $this->newObj();
180 $this->assertTrue( $obj->equals( NS_MAIN, NS_MAIN ) );
181 $this->assertTrue( $obj->equals( NS_MAIN, 0 ) ); // In case we make NS_MAIN 'MAIN'
182 $this->assertTrue( $obj->equals( NS_USER, NS_USER ) );
183 $this->assertTrue( $obj->equals( NS_USER, 2 ) );
184 $this->assertTrue( $obj->equals( NS_USER_TALK, NS_USER_TALK ) );
185 $this->assertTrue( $obj->equals( NS_SPECIAL, NS_SPECIAL ) );
186 $this->assertFalse( $obj->equals( NS_MAIN, NS_TALK ) );
187 $this->assertFalse( $obj->equals( NS_USER, NS_USER_TALK ) );
188 $this->assertFalse( $obj->equals( NS_PROJECT, NS_TEMPLATE ) );
189 }
190
191 /**
192 * @param int $ns1
193 * @param int $ns2
194 * @param bool $expected
195 * @dataProvider provideSubjectEquals
196 * @covers NamespaceInfo::subjectEquals
197 */
198 public function testSubjectEquals( $ns1, $ns2, $expected ) {
199 $this->assertSame( $expected, $this->newObj()->subjectEquals( $ns1, $ns2 ) );
200 }
201
202 public function provideSubjectEquals() {
203 return [
204 [ NS_MAIN, NS_MAIN, true ],
205 // In case we make NS_MAIN 'MAIN'
206 [ NS_MAIN, 0, true ],
207 [ NS_USER, NS_USER, true ],
208 [ NS_USER, 2, true ],
209 [ NS_USER_TALK, NS_USER_TALK, true ],
210 [ NS_SPECIAL, NS_SPECIAL, true ],
211 [ NS_MAIN, NS_TALK, true ],
212 [ NS_USER, NS_USER_TALK, true ],
213
214 [ NS_PROJECT, NS_TEMPLATE, false ],
215 [ NS_SPECIAL, NS_MAIN, false ],
216 [ NS_MEDIA, NS_SPECIAL, false ],
217 [ NS_SPECIAL, NS_MEDIA, false ],
218 ];
219 }
220
221 /**
222 * @dataProvider provideHasTalkNamespace
223 * @covers NamespaceInfo::hasTalkNamespace
224 *
225 * @param int $ns
226 * @param bool $expected
227 */
228 public function testHasTalkNamespace( $ns, $expected ) {
229 $this->assertSame( $expected, $this->newObj()->hasTalkNamespace( $ns ) );
230 }
231
232 public function provideHasTalkNamespace() {
233 return [
234 [ NS_MEDIA, false ],
235 [ NS_SPECIAL, false ],
236
237 [ NS_MAIN, true ],
238 [ NS_TALK, true ],
239 [ NS_USER, true ],
240 [ NS_USER_TALK, true ],
241
242 [ 100, true ],
243 [ 101, true ],
244 ];
245 }
246
247 /**
248 * @param int $ns
249 * @param bool $expected
250 * @param array $contentNamespaces
251 * @covers NamespaceInfo::isContent
252 * @dataProvider provideIsContent
253 */
254 public function testIsContent( $ns, $expected, $contentNamespaces = [ NS_MAIN ] ) {
255 $obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
256 $this->assertSame( $expected, $obj->isContent( $ns ) );
257 }
258
259 public function provideIsContent() {
260 return [
261 [ NS_MAIN, true ],
262 [ NS_MEDIA, false ],
263 [ NS_SPECIAL, false ],
264 [ NS_TALK, false ],
265 [ NS_USER, false ],
266 [ NS_CATEGORY, false ],
267 [ 100, false ],
268 [ 100, true, [ NS_MAIN, 100, 252 ] ],
269 [ 252, true, [ NS_MAIN, 100, 252 ] ],
270 [ NS_MAIN, true, [ NS_MAIN, 100, 252 ] ],
271 // NS_MAIN is always content
272 [ NS_MAIN, true, [] ],
273 ];
274 }
275
276 /**
277 * @param int $ns
278 * @param bool $expected
279 * @covers NamespaceInfo::isWatchable
280 * @dataProvider provideIsWatchable
281 */
282 public function testIsWatchable( $ns, $expected ) {
283 $this->assertSame( $expected, $this->newObj()->isWatchable( $ns ) );
284 }
285
286 public function provideIsWatchable() {
287 return [
288 // Specials namespaces are not watchable
289 [ NS_MEDIA, false ],
290 [ NS_SPECIAL, false ],
291
292 // Core defined namespaces are watchables
293 [ NS_MAIN, true ],
294 [ NS_TALK, true ],
295
296 // Additional, user defined namespaces are watchables
297 [ 100, true ],
298 [ 101, true ],
299 ];
300 }
301
302 /**
303 * @param int $ns
304 * @param int $expected
305 * @param array|null $namespacesWithSubpages To pass to constructor
306 * @covers NamespaceInfo::hasSubpages
307 * @dataProvider provideHasSubpages
308 */
309 public function testHasSubpages( $ns, $expected, array $namespacesWithSubpages = null ) {
310 $obj = $this->newObj( $namespacesWithSubpages
311 ? [ 'NamespacesWithSubpages' => $namespacesWithSubpages ]
312 : [] );
313 $this->assertSame( $expected, $obj->hasSubpages( $ns ) );
314 }
315
316 public function provideHasSubpages() {
317 return [
318 // Special namespaces:
319 [ NS_MEDIA, false ],
320 [ NS_SPECIAL, false ],
321
322 // Namespaces without subpages
323 [ NS_MAIN, false ],
324 [ NS_MAIN, true, [ NS_MAIN => true ] ],
325 [ NS_MAIN, false, [ NS_MAIN => false ] ],
326
327 // Some namespaces with subpages
328 [ NS_TALK, true ],
329 [ NS_USER, true ],
330 [ NS_USER_TALK, true ],
331 ];
332 }
333
334 /**
335 * @param $contentNamespaces To pass to constructor
336 * @param array $expected
337 * @dataProvider provideGetContentNamespaces
338 * @covers NamespaceInfo::getContentNamespaces
339 */
340 public function testGetContentNamespaces( $contentNamespaces, array $expected ) {
341 $obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
342 $this->assertSame( $expected, $obj->getContentNamespaces() );
343 }
344
345 public function provideGetContentNamespaces() {
346 return [
347 // Non-array
348 [ '', [ NS_MAIN ] ],
349 [ false, [ NS_MAIN ] ],
350 [ null, [ NS_MAIN ] ],
351 [ 5, [ NS_MAIN ] ],
352
353 // Empty array
354 [ [], [ NS_MAIN ] ],
355
356 // NS_MAIN is forced to be content even if unwanted
357 [ [ NS_USER, NS_CATEGORY ], [ NS_MAIN, NS_USER, NS_CATEGORY ] ],
358
359 // In other cases, return as-is
360 [ [ NS_MAIN ], [ NS_MAIN ] ],
361 [ [ NS_MAIN, NS_USER, NS_CATEGORY ], [ NS_MAIN, NS_USER, NS_CATEGORY ] ],
362 ];
363 }
364
365 /**
366 * @covers NamespaceInfo::getSubjectNamespaces
367 */
368 public function testGetSubjectNamespaces() {
369 $subjectsNS = $this->newObj()->getSubjectNamespaces();
370 $this->assertContains( NS_MAIN, $subjectsNS,
371 "Talk namespaces should have NS_MAIN" );
372 $this->assertNotContains( NS_TALK, $subjectsNS,
373 "Talk namespaces should have NS_TALK" );
374
375 $this->assertNotContains( NS_MEDIA, $subjectsNS,
376 "Talk namespaces should not have NS_MEDIA" );
377 $this->assertNotContains( NS_SPECIAL, $subjectsNS,
378 "Talk namespaces should not have NS_SPECIAL" );
379 }
380
381 /**
382 * @covers NamespaceInfo::getTalkNamespaces
383 */
384 public function testGetTalkNamespaces() {
385 $talkNS = $this->newObj()->getTalkNamespaces();
386 $this->assertContains( NS_TALK, $talkNS,
387 "Subject namespaces should have NS_TALK" );
388 $this->assertNotContains( NS_MAIN, $talkNS,
389 "Subject namespaces should not have NS_MAIN" );
390
391 $this->assertNotContains( NS_MEDIA, $talkNS,
392 "Subject namespaces should not have NS_MEDIA" );
393 $this->assertNotContains( NS_SPECIAL, $talkNS,
394 "Subject namespaces should not have NS_SPECIAL" );
395 }
396
397 /**
398 * @param int $ns
399 * @param bool $expected
400 * @param bool $capitalLinks To pass to constructor
401 * @param array $capitalLinkOverrides To pass to constructor
402 * @dataProvider provideIsCapitalized
403 * @covers NamespaceInfo::isCapitalized
404 */
405 public function testIsCapitalized(
406 $ns, $expected, $capitalLinks = true, array $capitalLinkOverrides = []
407 ) {
408 $obj = $this->newObj( [
409 'CapitalLinks' => $capitalLinks,
410 'CapitalLinkOverrides' => $capitalLinkOverrides,
411 ] );
412 $this->assertSame( $expected, $obj->isCapitalized( $ns ) );
413 }
414
415 public function provideIsCapitalized() {
416 return [
417 // Test default settings
418 [ NS_PROJECT, true ],
419 [ NS_PROJECT_TALK, true ],
420 [ NS_MEDIA, true ],
421 [ NS_FILE, true ],
422
423 // Always capitalized no matter what
424 [ NS_SPECIAL, true, false ],
425 [ NS_USER, true, false ],
426 [ NS_MEDIAWIKI, true, false ],
427
428 // Even with an override too
429 [ NS_SPECIAL, true, false, [ NS_SPECIAL => false ] ],
430 [ NS_USER, true, false, [ NS_USER => false ] ],
431 [ NS_MEDIAWIKI, true, false, [ NS_MEDIAWIKI => false ] ],
432
433 // Overrides work for other namespaces
434 [ NS_PROJECT, false, true, [ NS_PROJECT => false ] ],
435 [ NS_PROJECT, true, false, [ NS_PROJECT => true ] ],
436
437 // NS_MEDIA is treated like NS_FILE, and ignores NS_MEDIA overrides
438 [ NS_MEDIA, false, true, [ NS_FILE => false, NS_MEDIA => true ] ],
439 [ NS_MEDIA, true, false, [ NS_FILE => true, NS_MEDIA => false ] ],
440 [ NS_FILE, false, true, [ NS_FILE => false, NS_MEDIA => true ] ],
441 [ NS_FILE, true, false, [ NS_FILE => true, NS_MEDIA => false ] ],
442 ];
443 }
444
445 /**
446 * @covers NamespaceInfo::hasGenderDistinction
447 */
448 public function testHasGenderDistinction() {
449 $obj = $this->newObj();
450
451 // Namespaces with gender distinctions
452 $this->assertTrue( $obj->hasGenderDistinction( NS_USER ) );
453 $this->assertTrue( $obj->hasGenderDistinction( NS_USER_TALK ) );
454
455 // Other ones, "genderless"
456 $this->assertFalse( $obj->hasGenderDistinction( NS_MEDIA ) );
457 $this->assertFalse( $obj->hasGenderDistinction( NS_SPECIAL ) );
458 $this->assertFalse( $obj->hasGenderDistinction( NS_MAIN ) );
459 $this->assertFalse( $obj->hasGenderDistinction( NS_TALK ) );
460 }
461
462 /**
463 * @covers NamespaceInfo::isNonincludable
464 */
465 public function testIsNonincludable() {
466 $obj = $this->newObj( [ 'NonincludableNamespaces' => [ NS_USER ] ] );
467 $this->assertTrue( $obj->isNonincludable( NS_USER ) );
468 $this->assertFalse( $obj->isNonincludable( NS_TEMPLATE ) );
469 }
470
471 /**
472 * @dataProvider provideGetCategoryLinkType
473 * @covers NamespaceInfo::getCategoryLinkType
474 *
475 * @param int $ns
476 * @param string $expected
477 */
478 public function testGetCategoryLinkType( $ns, $expected ) {
479 $this->assertSame( $expected, $this->newObj()->getCategoryLinkType( $ns ) );
480 }
481
482 public function provideGetCategoryLinkType() {
483 return [
484 [ NS_MAIN, 'page' ],
485 [ NS_TALK, 'page' ],
486 [ NS_USER, 'page' ],
487 [ NS_USER_TALK, 'page' ],
488
489 [ NS_FILE, 'file' ],
490 [ NS_FILE_TALK, 'page' ],
491
492 [ NS_CATEGORY, 'subcat' ],
493 [ NS_CATEGORY_TALK, 'page' ],
494
495 [ 100, 'page' ],
496 [ 101, 'page' ],
497 ];
498 }
499 }