3 * @author Antoine Musso
4 * @copyright Copyright © 2011, Antoine Musso
8 use MediaWiki\Config\ServiceOptions
;
10 class NamespaceInfoTest
extends MediaWikiTestCase
{
11 private function newObj( array $options = [] ) : NamespaceInfo
{
13 'AllowImageMoving' => true,
14 'CanonicalNamespaceNames' => [
17 NS_USER_TALK
=> 'User_talk',
18 NS_SPECIAL
=> 'Special',
21 'CapitalLinkOverrides' => [],
22 'CapitalLinks' => true,
23 'ContentNamespaces' => [ NS_MAIN
],
24 'ExtraNamespaces' => [],
25 'ExtraSignatureNamespaces' => [],
26 'NamespaceContentModels' => [],
27 'NamespaceProtection' => [],
28 'NamespacesWithSubpages' => [
33 'NonincludableNamespaces' => [],
34 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop' ],
36 return new NamespaceInfo(
37 new ServiceOptions( NamespaceInfo
::$constructorOptions, $options, $defaults ) );
41 * @todo Write more tests, handle $wgAllowImageMoving setting
42 * @covers NamespaceInfo::isMovable
44 public function testIsMovable() {
45 $this->assertFalse( $this->newObj()->isMovable( NS_SPECIAL
) );
48 private function assertIsSubject( $ns ) {
49 $this->assertTrue( $this->newObj()->isSubject( $ns ) );
52 private function assertIsNotSubject( $ns ) {
54 $this->newObj()->isSubject( $ns ) );
59 * @param bool $expected
60 * @dataProvider provideIsSubject
61 * @covers NamespaceInfo::isSubject
63 public function testIsSubject( $ns, $expected ) {
64 $this->assertSame( $expected, $this->newObj()->isSubject( $ns ) );
69 * @param bool $expected
70 * @dataProvider provideIsSubject
71 * @covers NamespaceInfo::isTalk
73 public function testIsTalk( $ns, $expected ) {
74 $this->assertSame( !$expected, $this->newObj()->isTalk( $ns ) );
77 public function provideIsSubject() {
90 [ NS_USER_TALK
, false ],
96 * @covers NamespaceInfo::getSubject
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
) );
104 $this->assertEquals( NS_MAIN
, $obj->getSubject( NS_TALK
) );
105 $this->assertEquals( NS_USER
, $obj->getSubject( NS_USER_TALK
) );
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
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
) );
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
128 public function testGetTalkExceptionsForNsMedia() {
129 $this->assertNull( $this->newObj()->getTalk( NS_MEDIA
) );
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
138 public function testGetTalkExceptionsForNsSpecial() {
139 $this->assertNull( $this->newObj()->getTalk( NS_SPECIAL
) );
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
148 public function testGetAssociated() {
149 $this->assertEquals( NS_TALK
, $this->newObj()->getAssociated( NS_MAIN
) );
150 $this->assertEquals( NS_MAIN
, $this->newObj()->getAssociated( NS_TALK
) );
153 # ## Exceptions with getAssociated()
154 # ## NS_MEDIA and NS_SPECIAL do not have talk pages. MediaWiki raises
155 # ## an exception for them.
157 * @expectedException MWException
158 * @covers NamespaceInfo::getAssociated
160 public function testGetAssociatedExceptionsForNsMedia() {
161 $this->assertNull( $this->newObj()->getAssociated( NS_MEDIA
) );
165 * @expectedException MWException
166 * @covers NamespaceInfo::getAssociated
168 public function testGetAssociatedExceptionsForNsSpecial() {
169 $this->assertNull( $this->newObj()->getAssociated( NS_SPECIAL
) );
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
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
) );
194 * @param bool $expected
195 * @dataProvider provideSubjectEquals
196 * @covers NamespaceInfo::subjectEquals
198 public function testSubjectEquals( $ns1, $ns2, $expected ) {
199 $this->assertSame( $expected, $this->newObj()->subjectEquals( $ns1, $ns2 ) );
202 public function provideSubjectEquals() {
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 ],
214 [ NS_PROJECT
, NS_TEMPLATE
, false ],
215 [ NS_SPECIAL
, NS_MAIN
, false ],
216 [ NS_MEDIA
, NS_SPECIAL
, false ],
217 [ NS_SPECIAL
, NS_MEDIA
, false ],
222 * @dataProvider provideHasTalkNamespace
223 * @covers NamespaceInfo::hasTalkNamespace
226 * @param bool $expected
228 public function testHasTalkNamespace( $ns, $expected ) {
229 $this->assertSame( $expected, $this->newObj()->hasTalkNamespace( $ns ) );
232 public function provideHasTalkNamespace() {
235 [ NS_SPECIAL
, false ],
240 [ NS_USER_TALK
, true ],
249 * @param bool $expected
250 * @param array $contentNamespaces
251 * @covers NamespaceInfo::isContent
252 * @dataProvider provideIsContent
254 public function testIsContent( $ns, $expected, $contentNamespaces = [ NS_MAIN
] ) {
255 $obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
256 $this->assertSame( $expected, $obj->isContent( $ns ) );
259 public function provideIsContent() {
263 [ NS_SPECIAL
, false ],
266 [ NS_CATEGORY
, 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, [] ],
278 * @param bool $expected
279 * @covers NamespaceInfo::isWatchable
280 * @dataProvider provideIsWatchable
282 public function testIsWatchable( $ns, $expected ) {
283 $this->assertSame( $expected, $this->newObj()->isWatchable( $ns ) );
286 public function provideIsWatchable() {
288 // Specials namespaces are not watchable
290 [ NS_SPECIAL
, false ],
292 // Core defined namespaces are watchables
296 // Additional, user defined namespaces are watchables
304 * @param int $expected
305 * @param array|null $namespacesWithSubpages To pass to constructor
306 * @covers NamespaceInfo::hasSubpages
307 * @dataProvider provideHasSubpages
309 public function testHasSubpages( $ns, $expected, array $namespacesWithSubpages = null ) {
310 $obj = $this->newObj( $namespacesWithSubpages
311 ?
[ 'NamespacesWithSubpages' => $namespacesWithSubpages ]
313 $this->assertSame( $expected, $obj->hasSubpages( $ns ) );
316 public function provideHasSubpages() {
318 // Special namespaces:
320 [ NS_SPECIAL
, false ],
322 // Namespaces without subpages
324 [ NS_MAIN
, true, [ NS_MAIN
=> true ] ],
325 [ NS_MAIN
, false, [ NS_MAIN
=> false ] ],
327 // Some namespaces with subpages
330 [ NS_USER_TALK
, true ],
335 * @param $contentNamespaces To pass to constructor
336 * @param array $expected
337 * @dataProvider provideGetContentNamespaces
338 * @covers NamespaceInfo::getContentNamespaces
340 public function testGetContentNamespaces( $contentNamespaces, array $expected ) {
341 $obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
342 $this->assertSame( $expected, $obj->getContentNamespaces() );
345 public function provideGetContentNamespaces() {
349 [ false, [ NS_MAIN
] ],
350 [ null, [ NS_MAIN
] ],
356 // NS_MAIN is forced to be content even if unwanted
357 [ [ NS_USER
, NS_CATEGORY
], [ NS_MAIN
, NS_USER
, NS_CATEGORY
] ],
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
] ],
366 * @covers NamespaceInfo::getSubjectNamespaces
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" );
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" );
382 * @covers NamespaceInfo::getTalkNamespaces
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" );
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" );
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
405 public function testIsCapitalized(
406 $ns, $expected, $capitalLinks = true, array $capitalLinkOverrides = []
408 $obj = $this->newObj( [
409 'CapitalLinks' => $capitalLinks,
410 'CapitalLinkOverrides' => $capitalLinkOverrides,
412 $this->assertSame( $expected, $obj->isCapitalized( $ns ) );
415 public function provideIsCapitalized() {
417 // Test default settings
418 [ NS_PROJECT
, true ],
419 [ NS_PROJECT_TALK
, true ],
423 // Always capitalized no matter what
424 [ NS_SPECIAL
, true, false ],
425 [ NS_USER
, true, false ],
426 [ NS_MEDIAWIKI
, true, false ],
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 ] ],
433 // Overrides work for other namespaces
434 [ NS_PROJECT
, false, true, [ NS_PROJECT
=> false ] ],
435 [ NS_PROJECT
, true, false, [ NS_PROJECT
=> true ] ],
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 ] ],
446 * @covers NamespaceInfo::hasGenderDistinction
448 public function testHasGenderDistinction() {
449 $obj = $this->newObj();
451 // Namespaces with gender distinctions
452 $this->assertTrue( $obj->hasGenderDistinction( NS_USER
) );
453 $this->assertTrue( $obj->hasGenderDistinction( NS_USER_TALK
) );
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
) );
463 * @covers NamespaceInfo::isNonincludable
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
) );
472 * @dataProvider provideGetCategoryLinkType
473 * @covers NamespaceInfo::getCategoryLinkType
476 * @param string $expected
478 public function testGetCategoryLinkType( $ns, $expected ) {
479 $this->assertSame( $expected, $this->newObj()->getCategoryLinkType( $ns ) );
482 public function provideGetCategoryLinkType() {
487 [ NS_USER_TALK
, 'page' ],
490 [ NS_FILE_TALK
, 'page' ],
492 [ NS_CATEGORY
, 'subcat' ],
493 [ NS_CATEGORY_TALK
, 'page' ],