Merge "Move up devunt's name to Developers"
[lhc/web/wiklou.git] / tests / phpunit / includes / specialpage / SpecialPageFactoryTest.php
1 <?php
2 /**
3 * Factory for handling the special page list and generating SpecialPage objects.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @covers SpecialPageFactory
21 * @group SpecialPage
22 */
23 class SpecialPageFactoryTest extends MediaWikiTestCase {
24
25 protected function tearDown() {
26 parent::tearDown();
27
28 SpecialPageFactory::resetList();
29 }
30
31 public function testResetList() {
32 SpecialPageFactory::resetList();
33 $this->assertContains( 'Specialpages', SpecialPageFactory::getNames() );
34 }
35
36 public function testHookNotCalledTwice() {
37 $count = 0;
38 $this->mergeMwGlobalArrayValue( 'wgHooks', [
39 'SpecialPage_initList' => [
40 function () use ( &$count ) {
41 $count++;
42 }
43 ] ] );
44 SpecialPageFactory::resetList();
45 SpecialPageFactory::getNames();
46 SpecialPageFactory::getNames();
47 $this->assertEquals( 1, $count );
48 }
49
50 public function newSpecialAllPages() {
51 return new SpecialAllPages();
52 }
53
54 public function specialPageProvider() {
55 $specialPageTestHelper = new SpecialPageTestHelper();
56
57 return [
58 'class name' => [ 'SpecialAllPages' ],
59 'closure' => [ function () {
60 return new SpecialAllPages();
61 } ],
62 'function' => [ [ $this, 'newSpecialAllPages' ] ],
63 'callback string' => [ 'SpecialPageTestHelper::newSpecialAllPages' ],
64 'callback with object' => [
65 [ $specialPageTestHelper, 'newSpecialAllPages' ]
66 ],
67 'callback array' => [
68 [ 'SpecialPageTestHelper', 'newSpecialAllPages' ]
69 ]
70 ];
71 }
72
73 /**
74 * @covers SpecialPageFactory::getPage
75 * @dataProvider specialPageProvider
76 */
77 public function testGetPage( $spec ) {
78 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => $spec ] );
79 SpecialPageFactory::resetList();
80
81 $page = SpecialPageFactory::getPage( 'testdummy' );
82 $this->assertInstanceOf( 'SpecialPage', $page );
83
84 $page2 = SpecialPageFactory::getPage( 'testdummy' );
85 $this->assertEquals( true, $page2 === $page, "Should re-use instance:" );
86 }
87
88 /**
89 * @covers SpecialPageFactory::getNames
90 */
91 public function testGetNames() {
92 $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => 'SpecialAllPages' ] );
93 SpecialPageFactory::resetList();
94
95 $names = SpecialPageFactory::getNames();
96 $this->assertInternalType( 'array', $names );
97 $this->assertContains( 'testdummy', $names );
98 }
99
100 /**
101 * @covers SpecialPageFactory::resolveAlias
102 */
103 public function testResolveAlias() {
104 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
105 SpecialPageFactory::resetList();
106
107 list( $name, $param ) = SpecialPageFactory::resolveAlias( 'Spezialseiten/Foo' );
108 $this->assertEquals( 'Specialpages', $name );
109 $this->assertEquals( 'Foo', $param );
110 }
111
112 /**
113 * @covers SpecialPageFactory::getLocalNameFor
114 */
115 public function testGetLocalNameFor() {
116 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
117 SpecialPageFactory::resetList();
118
119 $name = SpecialPageFactory::getLocalNameFor( 'Specialpages', 'Foo' );
120 $this->assertEquals( 'Spezialseiten/Foo', $name );
121 }
122
123 /**
124 * @covers SpecialPageFactory::getTitleForAlias
125 */
126 public function testGetTitleForAlias() {
127 $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
128 SpecialPageFactory::resetList();
129
130 $title = SpecialPageFactory::getTitleForAlias( 'Specialpages/Foo' );
131 $this->assertEquals( 'Spezialseiten/Foo', $title->getText() );
132 $this->assertEquals( NS_SPECIAL, $title->getNamespace() );
133 }
134
135 /**
136 * @dataProvider provideTestConflictResolution
137 */
138 public function testConflictResolution(
139 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
140 ) {
141 global $wgContLang;
142 $lang = clone $wgContLang;
143 $lang->mExtendedSpecialPageAliases = $aliasesList;
144 $this->setMwGlobals( 'wgContLang', $lang );
145 $this->setMwGlobals( 'wgSpecialPages',
146 array_combine( array_keys( $aliasesList ), array_keys( $aliasesList ) )
147 );
148 SpecialPageFactory::resetList();
149
150 // Catch the warnings we expect to be raised
151 $warnings = [];
152 $this->setMwGlobals( 'wgDevelopmentWarnings', true );
153 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
154 if ( preg_match( '/First alias \'[^\']*\' for .*/', $errstr ) ||
155 preg_match( '/Did not find a usable alias for special page .*/', $errstr )
156 ) {
157 $warnings[] = $errstr;
158 return true;
159 }
160 return false;
161 } );
162 $reset = new ScopedCallback( 'restore_error_handler' );
163
164 list( $name, /*...*/ ) = SpecialPageFactory::resolveAlias( $alias );
165 $this->assertEquals( $expectedName, $name, "$test: Alias to name" );
166 $result = SpecialPageFactory::getLocalNameFor( $name );
167 $this->assertEquals( $expectedAlias, $result, "$test: Alias to name to alias" );
168
169 $gotWarnings = count( $warnings );
170 if ( $gotWarnings !== $expectWarnings ) {
171 $this->fail( "Expected $expectWarnings warning(s), but got $gotWarnings:\n" .
172 implode( "\n", $warnings )
173 );
174 }
175 }
176
177 /**
178 * @dataProvider provideTestConflictResolution
179 */
180 public function testConflictResolutionReversed(
181 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
182 ) {
183 // Make sure order doesn't matter by reversing the list
184 $aliasesList = array_reverse( $aliasesList );
185 return $this->testConflictResolution(
186 $test, $aliasesList, $alias, $expectedName, $expectedAlias, $expectWarnings
187 );
188 }
189
190 public function provideTestConflictResolution() {
191 return [
192 [
193 'Canonical name wins',
194 [ 'Foo' => [ 'Foo', 'Bar' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
195 'Foo',
196 'Foo',
197 'Foo',
198 1,
199 ],
200
201 [
202 'Doesn\'t redirect to a different special page\'s canonical name',
203 [ 'Foo' => [ 'Foo', 'Bar' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
204 'Baz',
205 'Baz',
206 'BazPage',
207 1,
208 ],
209
210 [
211 'Canonical name wins even if not aliased',
212 [ 'Foo' => [ 'FooPage' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
213 'Foo',
214 'Foo',
215 'FooPage',
216 1,
217 ],
218
219 [
220 'Doesn\'t redirect to a different special page\'s canonical name even if not aliased',
221 [ 'Foo' => [ 'FooPage' ], 'Baz' => [ 'Foo', 'BazPage', 'Baz2' ] ],
222 'Baz',
223 'Baz',
224 'BazPage',
225 1,
226 ],
227
228 [
229 'First local name beats non-first',
230 [ 'First' => [ 'Foo' ], 'NonFirst' => [ 'Bar', 'Foo' ] ],
231 'Foo',
232 'First',
233 'Foo',
234 0,
235 ],
236
237 [
238 'Doesn\'t redirect to a different special page\'s first alias',
239 [
240 'Foo' => [ 'Foo' ],
241 'First' => [ 'Bar' ],
242 'Baz' => [ 'Foo', 'Bar', 'BazPage', 'Baz2' ]
243 ],
244 'Baz',
245 'Baz',
246 'BazPage',
247 1,
248 ],
249
250 [
251 'Doesn\'t redirect wrong even if all aliases conflict',
252 [
253 'Foo' => [ 'Foo' ],
254 'First' => [ 'Bar' ],
255 'Baz' => [ 'Foo', 'Bar' ]
256 ],
257 'Baz',
258 'Baz',
259 'Baz',
260 2,
261 ],
262
263 ];
264 }
265
266 public function testGetAliasListRecursion() {
267 $called = false;
268 $this->mergeMwGlobalArrayValue( 'wgHooks', [
269 'SpecialPage_initList' => [
270 function () use ( &$called ) {
271 SpecialPageFactory::getLocalNameFor( 'Specialpages' );
272 $called = true;
273 }
274 ],
275 ] );
276 SpecialPageFactory::resetList();
277 SpecialPageFactory::getLocalNameFor( 'Specialpages' );
278 $this->assertTrue( $called, 'Recursive call succeeded' );
279 }
280
281 }