registration: Apply ResourceFileModulePaths to all modules
[lhc/web/wiklou.git] / tests / phpunit / includes / registration / ExtensionProcessorTest.php
1 <?php
2
3 class ExtensionProcessorTest extends MediaWikiTestCase {
4
5 private $dir;
6
7 public function setUp() {
8 parent::setUp();
9 $this->dir = __DIR__ . '/FooBar/extension.json';
10 }
11
12 /**
13 * 'name' is absolutely required
14 *
15 * @var array
16 */
17 static $default = array(
18 'name' => 'FooBar',
19 );
20
21 /**
22 * @covers ExtensionProcessor::extractInfo
23 */
24 public function testExtractInfo() {
25 // Test that attributes that begin with @ are ignored
26 $processor = new ExtensionProcessor();
27 $processor->extractInfo( $this->dir, self::$default + array(
28 '@metadata' => array( 'foobarbaz' ),
29 'AnAttribute' => array( 'omg' ),
30 ) );
31
32 $extracted = $processor->getExtractedInfo();
33 $attributes = $extracted['attributes'];
34 $this->assertArrayHasKey( 'AnAttribute', $attributes );
35 $this->assertArrayNotHasKey( '@metadata', $attributes );
36 }
37
38 public static function provideRegisterHooks() {
39 return array(
40 // No hooks
41 array(
42 array(),
43 self::$default,
44 array(),
45 ),
46 // No current hooks, adding one for "FooBaz"
47 array(
48 array(),
49 array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
50 array( 'FooBaz' => array( 'FooBazCallback' ) ),
51 ),
52 // Hook for "FooBaz", adding another one
53 array(
54 array( 'FooBaz' => array( 'PriorCallback' ) ),
55 array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
56 array( 'FooBaz' => array( 'PriorCallback', 'FooBazCallback' ) ),
57 ),
58 // Hook for "BarBaz", adding one for "FooBaz"
59 array(
60 array( 'BarBaz' => array( 'BarBazCallback' ) ),
61 array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
62 array(
63 'BarBaz' => array( 'BarBazCallback' ),
64 'FooBaz' => array( 'FooBazCallback' ),
65 ),
66 ),
67 );
68 }
69
70 /**
71 * @covers ExtensionProcessor::extractHooks
72 * @dataProvider provideRegisterHooks
73 */
74 public function testRegisterHooks( $pre, $info, $expected ) {
75 $processor = new MockExtensionProcessor( array( 'wgHooks' => $pre ) );
76 $processor->extractInfo( $this->dir, $info );
77 $extracted = $processor->getExtractedInfo();
78 $this->assertEquals( $expected, $extracted['globals']['wgHooks'] );
79 }
80
81 /**
82 * @covers ExtensionProcessor::extractConfig
83 */
84 public function testExtractConfig() {
85 $processor = new ExtensionProcessor;
86 $info = array(
87 'config' => array(
88 'Bar' => 'somevalue',
89 'Foo' => 10,
90 '@IGNORED' => 'yes',
91 ),
92 ) + self::$default;
93 $processor->extractInfo( $this->dir, $info );
94 $extracted = $processor->getExtractedInfo();
95 $this->assertEquals( 'somevalue', $extracted['globals']['wgBar'] );
96 $this->assertEquals( 10, $extracted['globals']['wgFoo'] );
97 $this->assertArrayNotHasKey( 'wg@IGNORED', $extracted['globals'] );
98 }
99
100 public static function provideExtracttExtensionMessagesFiles() {
101 $dir = __DIR__ . '/FooBar/';
102 return array(
103 array(
104 array( 'ExtensionMessagesFiles' => array( 'FooBarAlias' => 'FooBar.alias.php' ) ),
105 array( 'wgExtensionMessagesFiles' => array( 'FooBarAlias' => $dir . 'FooBar.alias.php' ) )
106 ),
107 array(
108 array(
109 'ExtensionMessagesFiles' => array(
110 'FooBarAlias' => 'FooBar.alias.php',
111 'FooBarMagic' => 'FooBar.magic.i18n.php',
112 ),
113 ),
114 array(
115 'wgExtensionMessagesFiles' => array(
116 'FooBarAlias' => $dir . 'FooBar.alias.php',
117 'FooBarMagic' => $dir . 'FooBar.magic.i18n.php',
118 ),
119 ),
120 ),
121 );
122 }
123
124 /**
125 * @covers ExtensionProcessor::extracttExtensionMessagesFiles
126 * @dataProvider provideExtracttExtensionMessagesFiles
127 */
128 public function testExtracttExtensionMessagesFiles( $input, $expected ) {
129 $processor = new ExtensionProcessor();
130 $processor->extractInfo( $this->dir, $input + self::$default );
131 $out = $processor->getExtractedInfo();
132 foreach ( $expected as $key => $value ) {
133 $this->assertEquals( $value, $out['globals'][$key] );
134 }
135 }
136
137
138 public static function provideExtractMessagesDirs() {
139 $dir = __DIR__ . '/FooBar/';
140 return array(
141 array(
142 array( 'MessagesDirs' => array( 'VisualEditor' => 'i18n' ) ),
143 array( 'wgMessagesDirs' => array( 'VisualEditor' => array( $dir . 'i18n' ) ) )
144 ),
145 array(
146 array( 'MessagesDirs' => array( 'VisualEditor' => array( 'i18n', 'foobar' ) ) ),
147 array( 'wgMessagesDirs' => array( 'VisualEditor' => array( $dir . 'i18n', $dir . 'foobar' ) ) )
148 ),
149 );
150 }
151
152 /**
153 * @covers ExtensionProcessor::extractMessagesDirs
154 * @dataProvider provideExtractMessagesDirs
155 */
156 public function testExtractMessagesDirs( $input, $expected ) {
157 $processor = new ExtensionProcessor();
158 $processor->extractInfo( $this->dir, $input + self::$default );
159 $out = $processor->getExtractedInfo();
160 foreach ( $expected as $key => $value ) {
161 $this->assertEquals( $value, $out['globals'][$key] );
162 }
163 }
164
165 /**
166 * @covers ExtensionProcessor::extractResourceLoaderModules
167 * @dataProvider provideExtractResourceLoaderModules
168 */
169 public function testExtractResourceLoaderModules( $input, $expected ) {
170 $processor = new ExtensionProcessor();
171 $processor->extractInfo( $this->dir, $input + self::$default );
172 $out = $processor->getExtractedInfo();
173 foreach ( $expected as $key => $value ) {
174 $this->assertEquals( $value, $out['globals'][$key] );
175 }
176 }
177
178 public static function provideExtractResourceLoaderModules() {
179 $dir = __DIR__ . '/FooBar/';
180 return array(
181 // Generic module with localBasePath/remoteExtPath specified
182 array(
183 // Input
184 array(
185 'ResourceModules' => array(
186 'test.foo' => array(
187 'styles' => 'foobar.js',
188 'localBasePath' => '',
189 'remoteExtPath' => 'FooBar',
190 ),
191 ),
192 ),
193 // Expected
194 array(
195 'wgResourceModules' => array(
196 'test.foo' => array(
197 'styles' => 'foobar.js',
198 'localBasePath' => $dir,
199 'remoteExtPath' => 'FooBar',
200 ),
201 ),
202 ),
203 ),
204 // ResourceFileModulePaths specified:
205 array(
206 // Input
207 array(
208 'ResourceFileModulePaths' => array(
209 'localBasePath' => '',
210 'remoteExtPath' => 'FooBar',
211 ),
212 'ResourceModules' => array(
213 // No paths
214 'test.foo' => array(
215 'styles' => 'foo.js',
216 ),
217 // Different paths set
218 'test.bar' => array(
219 'styles' => 'bar.js',
220 'localBasePath' => 'subdir',
221 'remoteExtPath' => 'FooBar/subdir',
222 ),
223 // Custom class with no paths set
224 'test.class' => array(
225 'class' => 'FooBarModule',
226 'extra' => 'argument',
227 ),
228 // Custom class with a localBasePath
229 'test.class.with.path' => array(
230 'class' => 'FooBarPathModule',
231 'extra' => 'argument',
232 'localBasePath' => '',
233 )
234 ),
235 ),
236 // Expected
237 array(
238 'wgResourceModules' => array(
239 'test.foo' => array(
240 'styles' => 'foo.js',
241 'localBasePath' => $dir,
242 'remoteExtPath' => 'FooBar',
243 ),
244 'test.bar' => array(
245 'styles' => 'bar.js',
246 'localBasePath' => $dir . 'subdir',
247 'remoteExtPath' => 'FooBar/subdir',
248 ),
249 'test.class' => array(
250 'class' => 'FooBarModule',
251 'extra' => 'argument',
252 'localBasePath' => $dir,
253 'remoteExtPath' => 'FooBar',
254 ),
255 'test.class.with.path' => array(
256 'class' => 'FooBarPathModule',
257 'extra' => 'argument',
258 'localBasePath' => $dir,
259 'remoteExtPath' => 'FooBar',
260 )
261 ),
262 ),
263 ),
264 );
265 }
266
267 public static function provideSetToGlobal() {
268 return array(
269 array(
270 array( 'wgAPIModules', 'wgAvailableRights' ),
271 array(),
272 array(
273 'APIModules' => array( 'foobar' => 'ApiFooBar' ),
274 'AvailableRights' => array( 'foobar', 'unfoobar' ),
275 ),
276 array(
277 'wgAPIModules' => array( 'foobar' => 'ApiFooBar' ),
278 'wgAvailableRights' => array( 'foobar', 'unfoobar' ),
279 ),
280 ),
281 array(
282 array( 'wgAPIModules', 'wgAvailableRights' ),
283 array(
284 'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz' ),
285 'wgAvailableRights' => array( 'barbaz' )
286 ),
287 array(
288 'APIModules' => array( 'foobar' => 'ApiFooBar' ),
289 'AvailableRights' => array( 'foobar', 'unfoobar' ),
290 ),
291 array(
292 'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz', 'foobar' => 'ApiFooBar' ),
293 'wgAvailableRights' => array( 'barbaz', 'foobar', 'unfoobar' ),
294 ),
295 ),
296 array(
297 array( 'wgGroupPermissions' ),
298 array(
299 'wgGroupPermissions' => array( 'sysop' => array( 'delete' ) ),
300 ),
301 array(
302 'GroupPermissions' => array( 'sysop' => array( 'undelete' ), 'user' => array( 'edit' ) ),
303 ),
304 array(
305 'wgGroupPermissions' => array( 'sysop' => array( 'delete', 'undelete' ), 'user' => array( 'edit' ) ),
306 )
307 )
308 );
309 }
310 }
311
312
313 /**
314 * Allow overriding the default value of $this->globals
315 * so we can test merging
316 */
317 class MockExtensionProcessor extends ExtensionProcessor {
318 public function __construct( $globals = array() ) {
319 $this->globals = $globals + $this->globals;
320 }
321 }