Merge "Follow-up Idb1202579: Add special-characters-group-greekextended to RL module"
[lhc/web/wiklou.git] / tests / phpunit / includes / resourceloader / ResourceLoaderTest.php
1 <?php
2
3 class ResourceLoaderTest extends ResourceLoaderTestCase {
4
5 protected function setUp() {
6 parent::setUp();
7
8 $this->setMwGlobals( [
9 'wgResourceLoaderLESSImportPaths' => [
10 dirname( dirname( __DIR__ ) ) . '/data/less/common',
11 ],
12 'wgResourceLoaderLESSVars' => [
13 'foo' => '2px',
14 'Foo' => '#eeeeee',
15 'bar' => 5,
16 ],
17 ] );
18 }
19
20 public static function provideValidModules() {
21 return [
22 [ 'TEST.validModule1', new ResourceLoaderTestModule() ],
23 ];
24 }
25
26 /**
27 * Ensures that the ResourceLoaderRegisterModules hook is called when a new
28 * ResourceLoader object is constructed.
29 * @covers ResourceLoader::__construct
30 */
31 public function testCreatingNewResourceLoaderCallsRegistrationHook() {
32 $resourceLoaderRegisterModulesHook = false;
33
34 $this->setMwGlobals( 'wgHooks', [
35 'ResourceLoaderRegisterModules' => [
36 function ( &$resourceLoader ) use ( &$resourceLoaderRegisterModulesHook ) {
37 $resourceLoaderRegisterModulesHook = true;
38 }
39 ]
40 ] );
41
42 $resourceLoader = new ResourceLoader();
43 $this->assertTrue(
44 $resourceLoaderRegisterModulesHook,
45 'Hook ResourceLoaderRegisterModules called'
46 );
47
48 return $resourceLoader;
49 }
50
51 /**
52 * @dataProvider provideValidModules
53 * @depends testCreatingNewResourceLoaderCallsRegistrationHook
54 * @covers ResourceLoader::register
55 * @covers ResourceLoader::getModule
56 */
57 public function testRegisteredValidModulesAreAccessible(
58 $name, ResourceLoaderModule $module, ResourceLoader $resourceLoader
59 ) {
60 $resourceLoader->register( $name, $module );
61 $this->assertEquals( $module, $resourceLoader->getModule( $name ) );
62 }
63
64 /**
65 * @covers ResourceLoaderFileModule::compileLessFile
66 */
67 public function testLessFileCompilation() {
68 $context = $this->getResourceLoaderContext();
69 $basePath = __DIR__ . '/../../data/less/module';
70 $module = new ResourceLoaderFileModule( [
71 'localBasePath' => $basePath,
72 'styles' => [ 'styles.less' ],
73 ] );
74 $module->setName( 'test.less' );
75 $styles = $module->getStyles( $context );
76 $this->assertStringEqualsFile( $basePath . '/styles.css', $styles['all'] );
77 }
78
79 /**
80 * Strip @noflip annotations from CSS code.
81 * @param string $css
82 * @return string
83 */
84 private static function stripNoflip( $css ) {
85 return str_replace( '/*@noflip*/ ', '', $css );
86 }
87
88 /**
89 * @dataProvider providePackedModules
90 * @covers ResourceLoader::makePackedModulesString
91 */
92 public function testMakePackedModulesString( $desc, $modules, $packed ) {
93 $this->assertEquals( $packed, ResourceLoader::makePackedModulesString( $modules ), $desc );
94 }
95
96 /**
97 * @dataProvider providePackedModules
98 * @covers ResourceLoaderContext::expandModuleNames
99 */
100 public function testexpandModuleNames( $desc, $modules, $packed ) {
101 $this->assertEquals( $modules, ResourceLoaderContext::expandModuleNames( $packed ), $desc );
102 }
103
104 public static function providePackedModules() {
105 return [
106 [
107 'Example from makePackedModulesString doc comment',
108 [ 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ],
109 'foo.bar,baz|bar.baz,quux',
110 ],
111 [
112 'Example from expandModuleNames doc comment',
113 [ 'jquery.foo', 'jquery.bar', 'jquery.ui.baz', 'jquery.ui.quux' ],
114 'jquery.foo,bar|jquery.ui.baz,quux',
115 ],
116 [
117 'Regression fixed in r88706 with dotless names',
118 [ 'foo', 'bar', 'baz' ],
119 'foo,bar,baz',
120 ],
121 [
122 'Prefixless modules after a prefixed module',
123 [ 'single.module', 'foobar', 'foobaz' ],
124 'single.module|foobar,foobaz',
125 ],
126 ];
127 }
128
129 public static function provideAddSource() {
130 return [
131 [ 'examplewiki', '//example.org/w/load.php', 'examplewiki' ],
132 [ 'example2wiki', [ 'loadScript' => '//example.com/w/load.php' ], 'example2wiki' ],
133 [
134 [ 'foowiki' => '//foo.org/w/load.php', 'bazwiki' => '//baz.org/w/load.php' ],
135 null,
136 [ 'foowiki', 'bazwiki' ]
137 ],
138 [
139 [ 'foowiki' => '//foo.org/w/load.php' ],
140 null,
141 false,
142 ],
143 ];
144 }
145
146 /**
147 * @dataProvider provideAddSource
148 * @covers ResourceLoader::addSource
149 * @covers ResourceLoader::getSources
150 */
151 public function testAddSource( $name, $info, $expected ) {
152 $rl = new ResourceLoader;
153 if ( $expected === false ) {
154 $this->setExpectedException( 'MWException', 'ResourceLoader duplicate source addition error' );
155 $rl->addSource( $name, $info );
156 }
157 $rl->addSource( $name, $info );
158 if ( is_array( $expected ) ) {
159 foreach ( $expected as $source ) {
160 $this->assertArrayHasKey( $source, $rl->getSources() );
161 }
162 } else {
163 $this->assertArrayHasKey( $expected, $rl->getSources() );
164 }
165 }
166
167 public static function fakeSources() {
168 return [
169 'examplewiki' => [
170 'loadScript' => '//example.org/w/load.php',
171 'apiScript' => '//example.org/w/api.php',
172 ],
173 'example2wiki' => [
174 'loadScript' => '//example.com/w/load.php',
175 'apiScript' => '//example.com/w/api.php',
176 ],
177 ];
178 }
179
180 public static function provideLoaderImplement() {
181 return [
182 [ [
183 'title' => 'Implement scripts, styles and messages',
184
185 'name' => 'test.example',
186 'scripts' => 'mw.example();',
187 'styles' => [ 'css' => [ '.mw-example {}' ] ],
188 'messages' => [ 'example' => '' ],
189 'templates' => [],
190
191 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery, require, module ) {
192 mw.example();
193 }, {
194 "css": [
195 ".mw-example {}"
196 ]
197 }, {
198 "example": ""
199 } );',
200 ] ],
201 [ [
202 'title' => 'Implement scripts',
203
204 'name' => 'test.example',
205 'scripts' => 'mw.example();',
206 'styles' => [],
207 'messages' => new XmlJsCode( '{}' ),
208 'templates' => [],
209
210 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery, require, module ) {
211 mw.example();
212 } );',
213 ] ],
214 [ [
215 'title' => 'Implement styles',
216
217 'name' => 'test.example',
218 'scripts' => [],
219 'styles' => [ 'css' => [ '.mw-example {}' ] ],
220 'messages' => new XmlJsCode( '{}' ),
221 'templates' => [],
222
223 'expected' => 'mw.loader.implement( "test.example", [], {
224 "css": [
225 ".mw-example {}"
226 ]
227 } );',
228 ] ],
229 [ [
230 'title' => 'Implement scripts and messages',
231
232 'name' => 'test.example',
233 'scripts' => 'mw.example();',
234 'styles' => [],
235 'messages' => [ 'example' => '' ],
236 'templates' => [],
237
238 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery, require, module ) {
239 mw.example();
240 }, {}, {
241 "example": ""
242 } );',
243 ] ],
244 [ [
245 'title' => 'Implement scripts and templates',
246
247 'name' => 'test.example',
248 'scripts' => 'mw.example();',
249 'styles' => [],
250 'messages' => new XmlJsCode( '{}' ),
251 'templates' => [ 'example.html' => '' ],
252
253 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery, require, module ) {
254 mw.example();
255 }, {}, {}, {
256 "example.html": ""
257 } );',
258 ] ],
259 ];
260 }
261
262 /**
263 * @dataProvider provideLoaderImplement
264 * @covers ResourceLoader::makeLoaderImplementScript
265 */
266 public function testMakeLoaderImplementScript( $case ) {
267 $this->assertEquals(
268 $case['expected'],
269 ResourceLoader::makeLoaderImplementScript(
270 $case['name'],
271 $case['scripts'],
272 $case['styles'],
273 $case['messages'],
274 $case['templates']
275 )
276 );
277 }
278
279 /**
280 * @covers ResourceLoader::getLoadScript
281 */
282 public function testGetLoadScript() {
283 $this->setMwGlobals( 'wgResourceLoaderSources', [] );
284 $rl = new ResourceLoader();
285 $sources = self::fakeSources();
286 $rl->addSource( $sources );
287 foreach ( [ 'examplewiki', 'example2wiki' ] as $name ) {
288 $this->assertEquals( $rl->getLoadScript( $name ), $sources[$name]['loadScript'] );
289 }
290
291 try {
292 $rl->getLoadScript( 'thiswasneverreigstered' );
293 $this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' );
294 } catch ( MWException $e ) {
295 $this->assertTrue( true );
296 }
297 }
298
299 /**
300 * @covers ResourceLoader::isModuleRegistered
301 */
302 public function testIsModuleRegistered() {
303 $rl = new ResourceLoader();
304 $rl->register( 'test.module', new ResourceLoaderTestModule() );
305 $this->assertTrue( $rl->isModuleRegistered( 'test.module' ) );
306 $this->assertFalse( $rl->isModuleRegistered( 'test.modulenotregistered' ) );
307 }
308 }