]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / resourceloader / ResourceLoaderWikiModuleTest.php
1 <?php
2
3 use MediaWiki\MediaWikiServices;
4 use Wikimedia\Rdbms\IDatabase;
5 use Wikimedia\TestingAccessWrapper;
6
7 class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
8
9         /**
10          * @covers ResourceLoaderWikiModule::__construct
11          * @dataProvider provideConstructor
12          */
13         public function testConstructor( $params ) {
14                 $module = new ResourceLoaderWikiModule( $params );
15                 $this->assertInstanceOf( 'ResourceLoaderWikiModule', $module );
16         }
17
18         public static function provideConstructor() {
19                 return [
20                         // Nothing
21                         [ null ],
22                         [ [] ],
23                         // Unrecognized settings
24                         [ [ 'foo' => 'baz' ] ],
25                         // Real settings
26                         [ [ 'scripts' => [ 'MediaWiki:Common.js' ] ] ],
27                 ];
28         }
29
30         /**
31          * @dataProvider provideGetPages
32          * @covers ResourceLoaderWikiModule::getPages
33          */
34         public function testGetPages( $params, Config $config, $expected ) {
35                 $module = new ResourceLoaderWikiModule( $params );
36                 $module->setConfig( $config );
37
38                 // Because getPages is protected..
39                 $getPages = new ReflectionMethod( $module, 'getPages' );
40                 $getPages->setAccessible( true );
41                 $out = $getPages->invoke( $module, ResourceLoaderContext::newDummyContext() );
42                 $this->assertEquals( $expected, $out );
43         }
44
45         public static function provideGetPages() {
46                 $settings = self::getSettings() + [
47                         'UseSiteJs' => true,
48                         'UseSiteCss' => true,
49                 ];
50
51                 $params = [
52                         'styles' => [ 'MediaWiki:Common.css' ],
53                         'scripts' => [ 'MediaWiki:Common.js' ],
54                 ];
55
56                 return [
57                         [ [], new HashConfig( $settings ), [] ],
58                         [ $params, new HashConfig( $settings ), [
59                                 'MediaWiki:Common.js' => [ 'type' => 'script' ],
60                                 'MediaWiki:Common.css' => [ 'type' => 'style' ]
61                         ] ],
62                         [ $params, new HashConfig( [ 'UseSiteCss' => false ] + $settings ), [
63                                 'MediaWiki:Common.js' => [ 'type' => 'script' ],
64                         ] ],
65                         [ $params, new HashConfig( [ 'UseSiteJs' => false ] + $settings ), [
66                                 'MediaWiki:Common.css' => [ 'type' => 'style' ],
67                         ] ],
68                         [ $params,
69                                 new HashConfig(
70                                         [ 'UseSiteJs' => false, 'UseSiteCss' => false ]
71                                 ),
72                                 []
73                         ],
74                 ];
75         }
76
77         /**
78          * @covers ResourceLoaderWikiModule::getGroup
79          * @dataProvider provideGetGroup
80          */
81         public function testGetGroup( $params, $expected ) {
82                 $module = new ResourceLoaderWikiModule( $params );
83                 $this->assertEquals( $expected, $module->getGroup() );
84         }
85
86         public static function provideGetGroup() {
87                 return [
88                         // No group specified
89                         [ [], null ],
90                         // A random group
91                         [ [ 'group' => 'foobar' ], 'foobar' ],
92                 ];
93         }
94
95         /**
96          * @covers ResourceLoaderWikiModule::isKnownEmpty
97          * @dataProvider provideIsKnownEmpty
98          */
99         public function testIsKnownEmpty( $titleInfo, $group, $expected ) {
100                 $module = $this->getMockBuilder( 'ResourceLoaderWikiModule' )
101                         ->setMethods( [ 'getTitleInfo', 'getGroup' ] )
102                         ->getMock();
103                 $module->expects( $this->any() )
104                         ->method( 'getTitleInfo' )
105                         ->will( $this->returnValue( $titleInfo ) );
106                 $module->expects( $this->any() )
107                         ->method( 'getGroup' )
108                         ->will( $this->returnValue( $group ) );
109                 $context = $this->getMockBuilder( 'ResourceLoaderContext' )
110                         ->disableOriginalConstructor()
111                         ->getMock();
112                 $this->assertEquals( $expected, $module->isKnownEmpty( $context ) );
113         }
114
115         public static function provideIsKnownEmpty() {
116                 return [
117                         // No valid pages
118                         [ [], 'test1', true ],
119                         // 'site' module with a non-empty page
120                         [
121                                 [ 'MediaWiki:Common.js' => [ 'page_len' => 1234 ] ],
122                                 'site',
123                                 false,
124                         ],
125                         // 'site' module with an empty page
126                         [
127                                 [ 'MediaWiki:Foo.js' => [ 'page_len' => 0 ] ],
128                                 'site',
129                                 false,
130                         ],
131                         // 'user' module with a non-empty page
132                         [
133                                 [ 'User:Example/common.js' => [ 'page_len' => 25 ] ],
134                                 'user',
135                                 false,
136                         ],
137                         // 'user' module with an empty page
138                         [
139                                 [ 'User:Example/foo.js' => [ 'page_len' => 0 ] ],
140                                 'user',
141                                 true,
142                         ],
143                 ];
144         }
145
146         /**
147          * @covers ResourceLoaderWikiModule::getTitleInfo
148          */
149         public function testGetTitleInfo() {
150                 $pages = [
151                         'MediaWiki:Common.css' => [ 'type' => 'styles' ],
152                         'mediawiki: fallback.css' => [ 'type' => 'styles' ],
153                 ];
154                 $titleInfo = [
155                         'MediaWiki:Common.css' => [ 'page_len' => 1234 ],
156                         'MediaWiki:Fallback.css' => [ 'page_len' => 0 ],
157                 ];
158                 $expected = $titleInfo;
159
160                 $module = $this->getMockBuilder( 'TestResourceLoaderWikiModule' )
161                         ->setMethods( [ 'getPages' ] )
162                         ->getMock();
163                 $module->method( 'getPages' )->willReturn( $pages );
164                 // Can't mock static methods
165                 $module::$returnFetchTitleInfo = $titleInfo;
166
167                 $context = $this->getMockBuilder( 'ResourceLoaderContext' )
168                         ->disableOriginalConstructor()
169                         ->getMock();
170
171                 $module = TestingAccessWrapper::newFromObject( $module );
172                 $this->assertEquals( $expected, $module->getTitleInfo( $context ), 'Title info' );
173         }
174
175         /**
176          * @covers ResourceLoaderWikiModule::getTitleInfo
177          * @covers ResourceLoaderWikiModule::setTitleInfo
178          * @covers ResourceLoaderWikiModule::preloadTitleInfo
179          */
180         public function testGetPreloadedTitleInfo() {
181                 $pages = [
182                         'MediaWiki:Common.css' => [ 'type' => 'styles' ],
183                         // Regression against T145673. It's impossible to statically declare page names in
184                         // a canonical way since the canonical prefix is localised. As such, the preload
185                         // cache computed the right cache key, but failed to find the results when
186                         // doing an intersect on the canonical result, producing an empty array.
187                         'mediawiki: fallback.css' => [ 'type' => 'styles' ],
188                 ];
189                 $titleInfo = [
190                         'MediaWiki:Common.css' => [ 'page_len' => 1234 ],
191                         'MediaWiki:Fallback.css' => [ 'page_len' => 0 ],
192                 ];
193                 $expected = $titleInfo;
194
195                 $module = $this->getMockBuilder( 'TestResourceLoaderWikiModule' )
196                         ->setMethods( [ 'getPages' ] )
197                         ->getMock();
198                 $module->method( 'getPages' )->willReturn( $pages );
199                 // Can't mock static methods
200                 $module::$returnFetchTitleInfo = $titleInfo;
201
202                 $rl = new EmptyResourceLoader();
203                 $rl->register( 'testmodule', $module );
204                 $context = new ResourceLoaderContext( $rl, new FauxRequest() );
205
206                 TestResourceLoaderWikiModule::invalidateModuleCache(
207                         Title::newFromText( 'MediaWiki:Common.css' ),
208                         null,
209                         null,
210                         wfWikiID()
211                 );
212                 TestResourceLoaderWikiModule::preloadTitleInfo(
213                         $context,
214                         wfGetDB( DB_REPLICA ),
215                         [ 'testmodule' ]
216                 );
217
218                 $module = TestingAccessWrapper::newFromObject( $module );
219                 $this->assertEquals( $expected, $module->getTitleInfo( $context ), 'Title info' );
220         }
221
222         /**
223          * @covers ResourceLoaderWikiModule::preloadTitleInfo
224          */
225         public function testGetPreloadedBadTitle() {
226                 // Mock values
227                 $pages = [
228                         // Covers else branch for invalid page name
229                         '[x]' => [ 'type' => 'styles' ],
230                 ];
231                 $titleInfo = [];
232
233                 // Set up objects
234                 $module = $this->getMockBuilder( 'TestResourceLoaderWikiModule' )
235                         ->setMethods( [ 'getPages' ] ) ->getMock();
236                 $module->method( 'getPages' )->willReturn( $pages );
237                 $module::$returnFetchTitleInfo = $titleInfo;
238                 $rl = new EmptyResourceLoader();
239                 $rl->register( 'testmodule', $module );
240                 $context = new ResourceLoaderContext( $rl, new FauxRequest() );
241
242                 // Act
243                 TestResourceLoaderWikiModule::preloadTitleInfo(
244                         $context,
245                         wfGetDB( DB_REPLICA ),
246                         [ 'testmodule' ]
247                 );
248
249                 // Assert
250                 $module = TestingAccessWrapper::newFromObject( $module );
251                 $this->assertEquals( $titleInfo, $module->getTitleInfo( $context ), 'Title info' );
252         }
253
254         /**
255          * @covers ResourceLoaderWikiModule::preloadTitleInfo
256          */
257         public function testGetPreloadedTitleInfoEmpty() {
258                 $context = new ResourceLoaderContext( new EmptyResourceLoader(), new FauxRequest() );
259                 // Covers early return
260                 $this->assertSame(
261                         null,
262                         ResourceLoaderWikiModule::preloadTitleInfo(
263                                 $context,
264                                 wfGetDB( DB_REPLICA ),
265                                 []
266                         )
267                 );
268         }
269
270         public static function provideGetContent() {
271                 return [
272                         'Bad title' => [ null, '[x]' ],
273                         'Dead redirect' => [ null, [
274                                 'text' => 'Dead redirect',
275                                 'title' => 'Dead_redirect',
276                                 'redirect' => 1,
277                         ] ],
278                         'Bad content model' => [ null, [
279                                 'text' => 'MediaWiki:Wikitext',
280                                 'ns' => NS_MEDIAWIKI,
281                                 'title' => 'Wikitext',
282                         ] ],
283                         'No JS content found' => [ null, [
284                                 'text' => 'MediaWiki:Script.js',
285                                 'ns' => NS_MEDIAWIKI,
286                                 'title' => 'Script.js',
287                         ] ],
288                         'No CSS content found' => [ null, [
289                                 'text' => 'MediaWiki:Styles.css',
290                                 'ns' => NS_MEDIAWIKI,
291                                 'title' => 'Script.css',
292                         ] ],
293                 ];
294         }
295
296         /**
297          * @covers ResourceLoaderWikiModule::getContent
298          * @dataProvider provideGetContent
299          */
300         public function testGetContent( $expected, $title ) {
301                 $context = $this->getResourceLoaderContext( [], new EmptyResourceLoader );
302                 $module = $this->getMockBuilder( 'ResourceLoaderWikiModule' )
303                         ->setMethods( [ 'getContentObj' ] ) ->getMock();
304                 $module->expects( $this->any() )
305                         ->method( 'getContentObj' )->willReturn( null );
306
307                 if ( is_array( $title ) ) {
308                         $title += [ 'ns' => NS_MAIN, 'id' => 1, 'len' => 1, 'redirect' => 0 ];
309                         $titleText = $title['text'];
310                         // Mock Title db access via LinkCache
311                         MediaWikiServices::getInstance()->getLinkCache()->addGoodLinkObj(
312                                 $title['id'],
313                                 new TitleValue( $title['ns'], $title['title'] ),
314                                 $title['len'],
315                                 $title['redirect']
316                         );
317                 } else {
318                         $titleText = $title;
319                 }
320
321                 $module = TestingAccessWrapper::newFromObject( $module );
322                 $this->assertEquals(
323                         $expected,
324                         $module->getContent( $titleText )
325                 );
326         }
327
328         /**
329          * @covers ResourceLoaderWikiModule::getContent
330          */
331         public function testGetContentForRedirects() {
332                 // Set up context and module object
333                 $context = $this->getResourceLoaderContext( [], new EmptyResourceLoader );
334                 $module = $this->getMockBuilder( 'ResourceLoaderWikiModule' )
335                         ->setMethods( [ 'getPages', 'getContentObj' ] )
336                         ->getMock();
337                 $module->expects( $this->any() )
338                         ->method( 'getPages' )
339                         ->will( $this->returnValue( [
340                                 'MediaWiki:Redirect.js' => [ 'type' => 'script' ]
341                         ] ) );
342                 $module->expects( $this->any() )
343                         ->method( 'getContentObj' )
344                         ->will( $this->returnCallback( function ( Title $title ) {
345                                 if ( $title->getPrefixedText() === 'MediaWiki:Redirect.js' ) {
346                                         $handler = new JavaScriptContentHandler();
347                                         return $handler->makeRedirectContent(
348                                                 Title::makeTitle( NS_MEDIAWIKI, 'Target.js' )
349                                         );
350                                 } elseif ( $title->getPrefixedText() === 'MediaWiki:Target.js' ) {
351                                         return new JavaScriptContent( 'target;' );
352                                 } else {
353                                         return null;
354                                 }
355                         } ) );
356
357                 // Mock away Title's db queries with LinkCache
358                 MediaWikiServices::getInstance()->getLinkCache()->addGoodLinkObj(
359                         1, // id
360                         new TitleValue( NS_MEDIAWIKI, 'Redirect.js' ),
361                         1, // len
362                         1 // redirect
363                 );
364
365                 $this->assertEquals(
366                         "/*\nMediaWiki:Redirect.js\n*/\ntarget;\n",
367                         $module->getScript( $context ),
368                         'Redirect resolved by getContent'
369                 );
370         }
371 }
372
373 class TestResourceLoaderWikiModule extends ResourceLoaderWikiModule {
374         public static $returnFetchTitleInfo = null;
375         protected static function fetchTitleInfo( IDatabase $db, array $pages, $fname = null ) {
376                 $ret = self::$returnFetchTitleInfo;
377                 self::$returnFetchTitleInfo = null;
378                 return $ret;
379         }
380 }