Merge "Remove a hack, and a hack for the hack, for MediaWiki UI input fields"
[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 // $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths; $wgResourceLoaderLESSVars;
9
10 $this->setMwGlobals( array(
11 'wgResourceLoaderLESSFunctions' => array(
12 'test-sum' => function ( $frame, $less ) {
13 $sum = 0;
14 foreach ( $frame[2] as $arg ) {
15 $sum += (int)$arg[1];
16 }
17 return $sum;
18 },
19 ),
20 'wgResourceLoaderLESSImportPaths' => array(
21 dirname( dirname( __DIR__ ) ) . '/data/less/common',
22 ),
23 'wgResourceLoaderLESSVars' => array(
24 'foo' => '2px',
25 'Foo' => '#eeeeee',
26 'bar' => 5,
27 ),
28 ) );
29 }
30
31 /* Provider Methods */
32 public static function provideValidModules() {
33 return array(
34 array( 'TEST.validModule1', new ResourceLoaderTestModule() ),
35 );
36 }
37
38 /* Test Methods */
39
40 /**
41 * Ensures that the ResourceLoaderRegisterModules hook is called when a new
42 * ResourceLoader object is constructed.
43 * @covers ResourceLoader::__construct
44 */
45 public function testCreatingNewResourceLoaderCallsRegistrationHook() {
46 $resourceLoaderRegisterModulesHook = false;
47
48 $this->setMwGlobals( 'wgHooks', array(
49 'ResourceLoaderRegisterModules' => array(
50 function ( &$resourceLoader ) use ( &$resourceLoaderRegisterModulesHook ) {
51 $resourceLoaderRegisterModulesHook = true;
52 }
53 )
54 ) );
55
56 $resourceLoader = new ResourceLoader();
57 $this->assertTrue(
58 $resourceLoaderRegisterModulesHook,
59 'Hook ResourceLoaderRegisterModules called'
60 );
61
62 return $resourceLoader;
63 }
64
65 /**
66 * @dataProvider provideValidModules
67 * @depends testCreatingNewResourceLoaderCallsRegistrationHook
68 * @covers ResourceLoader::register
69 * @covers ResourceLoader::getModule
70 */
71 public function testRegisteredValidModulesAreAccessible(
72 $name, ResourceLoaderModule $module, ResourceLoader $resourceLoader
73 ) {
74 $resourceLoader->register( $name, $module );
75 $this->assertEquals( $module, $resourceLoader->getModule( $name ) );
76 }
77
78 /**
79 * @covers ResourceLoaderFileModule::compileLessFile
80 */
81 public function testLessFileCompilation() {
82 $context = $this->getResourceLoaderContext();
83 $basePath = __DIR__ . '/../../data/less/module';
84 $module = new ResourceLoaderFileModule( array(
85 'localBasePath' => $basePath,
86 'styles' => array( 'styles.less' ),
87 ) );
88 $module->setName( 'test.less' );
89 $styles = $module->getStyles( $context );
90 $this->assertStringEqualsFile( $basePath . '/styles.css', $styles['all'] );
91 }
92
93 /**
94 * Strip @noflip annotations from CSS code.
95 * @param string $css
96 * @return string
97 */
98 private function stripNoflip( $css ) {
99 return str_replace( '/*@noflip*/ ', '', $css );
100 }
101
102 /**
103 * What happens when you mix @embed and @noflip?
104 * This really is an integration test, but oh well.
105 */
106 public function testMixedCssAnnotations( ) {
107 $basePath = __DIR__ . '/../../data/css';
108 $testModule = new ResourceLoaderFileModule( array(
109 'localBasePath' => $basePath,
110 'styles' => array( 'test.css' ),
111 ) );
112 $expectedModule = new ResourceLoaderFileModule( array(
113 'localBasePath' => $basePath,
114 'styles' => array( 'expected.css' ),
115 ) );
116
117 $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
118 $contextRtl = $this->getResourceLoaderContext( 'he', 'rtl' );
119
120 // Since we want to compare the effect of @noflip+@embed against the effect of just @embed, and
121 // the @noflip annotations are always preserved, we need to strip them first.
122 $this->assertEquals(
123 $expectedModule->getStyles( $contextLtr ),
124 $this->stripNoflip( $testModule->getStyles( $contextLtr ) ),
125 "/*@noflip*/ with /*@embed*/ gives correct results in LTR mode"
126 );
127 $this->assertEquals(
128 $expectedModule->getStyles( $contextLtr ),
129 $this->stripNoflip( $testModule->getStyles( $contextRtl ) ),
130 "/*@noflip*/ with /*@embed*/ gives correct results in RTL mode"
131 );
132 }
133
134 /**
135 * @dataProvider providePackedModules
136 * @covers ResourceLoader::makePackedModulesString
137 */
138 public function testMakePackedModulesString( $desc, $modules, $packed ) {
139 $this->assertEquals( $packed, ResourceLoader::makePackedModulesString( $modules ), $desc );
140 }
141
142 /**
143 * @dataProvider providePackedModules
144 * @covers ResourceLoaderContext::expandModuleNames
145 */
146 public function testexpandModuleNames( $desc, $modules, $packed ) {
147 $this->assertEquals( $modules, ResourceLoaderContext::expandModuleNames( $packed ), $desc );
148 }
149
150 public static function providePackedModules() {
151 return array(
152 array(
153 'Example from makePackedModulesString doc comment',
154 array( 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ),
155 'foo.bar,baz|bar.baz,quux',
156 ),
157 array(
158 'Example from expandModuleNames doc comment',
159 array( 'jquery.foo', 'jquery.bar', 'jquery.ui.baz', 'jquery.ui.quux' ),
160 'jquery.foo,bar|jquery.ui.baz,quux',
161 ),
162 array(
163 'Regression fixed in r88706 with dotless names',
164 array( 'foo', 'bar', 'baz' ),
165 'foo,bar,baz',
166 ),
167 array(
168 'Prefixless modules after a prefixed module',
169 array( 'single.module', 'foobar', 'foobaz' ),
170 'single.module|foobar,foobaz',
171 ),
172 );
173 }
174
175 public static function provideAddSource() {
176 return array(
177 array( 'examplewiki', '//example.org/w/load.php', 'examplewiki' ),
178 array( 'example2wiki', array( 'loadScript' => '//example.com/w/load.php' ), 'example2wiki' ),
179 array(
180 array( 'foowiki' => '//foo.org/w/load.php', 'bazwiki' => '//baz.org/w/load.php' ),
181 null,
182 array( 'foowiki', 'bazwiki' )
183 ),
184 array(
185 array( 'foowiki' => '//foo.org/w/load.php' ),
186 null,
187 false,
188 ),
189 );
190 }
191
192 /**
193 * @dataProvider provideAddSource
194 * @covers ResourceLoader::addSource
195 */
196 public function testAddSource( $name, $info, $expected ) {
197 $rl = new ResourceLoader;
198 if ( $expected === false ) {
199 $this->setExpectedException( 'MWException', 'ResourceLoader duplicate source addition error' );
200 $rl->addSource( $name, $info );
201 }
202 $rl->addSource( $name, $info );
203 if ( is_array( $expected ) ) {
204 foreach ( $expected as $source ) {
205 $this->assertArrayHasKey( $source, $rl->getSources() );
206 }
207 } else {
208 $this->assertArrayHasKey( $expected, $rl->getSources() );
209 }
210 }
211
212 public static function fakeSources() {
213 return array(
214 'examplewiki' => array(
215 'loadScript' => '//example.org/w/load.php',
216 'apiScript' => '//example.org/w/api.php',
217 ),
218 'example2wiki' => array(
219 'loadScript' => '//example.com/w/load.php',
220 'apiScript' => '//example.com/w/api.php',
221 ),
222 );
223 }
224
225 /**
226 * @covers ResourceLoader::getLoadScript
227 */
228 public function testGetLoadScript() {
229 $this->setMwGlobals( 'wgResourceLoaderSources', array() );
230 $rl = new ResourceLoader();
231 $sources = self::fakeSources();
232 $rl->addSource( $sources );
233 foreach ( array( 'examplewiki', 'example2wiki' ) as $name ) {
234 $this->assertEquals( $rl->getLoadScript( $name ), $sources[$name]['loadScript'] );
235 }
236
237 try {
238 $rl->getLoadScript( 'thiswasneverreigstered' );
239 $this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' );
240 } catch ( MWException $e ) {
241 $this->assertTrue( true );
242 }
243 }
244
245 /**
246 * @covers ResourceLoader::isModuleRegistered
247 */
248 public function testIsModuleRegistered() {
249 $rl = new ResourceLoader();
250 $rl->register( 'test.module', new ResourceLoaderTestModule() );
251 $this->assertTrue( $rl->isModuleRegistered( 'test.module' ) );
252 $this->assertFalse( $rl->isModuleRegistered( 'test.modulenotregistered' ) );
253 }
254 }