Merge "WebRequest: Use getRawVal instead of getGPCVal where possible"
[lhc/web/wiklou.git] / tests / phpunit / includes / resourceloader / ResourceLoaderFileModuleTest.php
1 <?php
2
3 /**
4 * @group Database
5 * @group ResourceLoader
6 */
7 class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
8
9 protected function setUp() {
10 parent::setUp();
11
12 // The return value of the closure shouldn't matter since this test should
13 // never call it
14 SkinFactory::getDefaultInstance()->register(
15 'fakeskin',
16 'FakeSkin',
17 function () {
18 }
19 );
20 }
21
22 private static function getModules() {
23 $base = [
24 'localBasePath' => realpath( __DIR__ ),
25 ];
26
27 return [
28 'noTemplateModule' => [],
29
30 'deprecatedModule' => $base + [
31 'deprecated' => true,
32 ],
33 'deprecatedTomorrow' => $base + [
34 'deprecated' => [
35 'message' => 'Will be removed tomorrow.'
36 ],
37 ],
38
39 'htmlTemplateModule' => $base + [
40 'templates' => [
41 'templates/template.html',
42 'templates/template2.html',
43 ]
44 ],
45
46 'aliasedHtmlTemplateModule' => $base + [
47 'templates' => [
48 'foo.html' => 'templates/template.html',
49 'bar.html' => 'templates/template2.html',
50 ]
51 ],
52
53 'templateModuleHandlebars' => $base + [
54 'templates' => [
55 'templates/template_awesome.handlebars',
56 ],
57 ],
58
59 'aliasFooFromBar' => $base + [
60 'templates' => [
61 'foo.foo' => 'templates/template.bar',
62 ],
63 ],
64 ];
65 }
66
67 public static function providerTemplateDependencies() {
68 $modules = self::getModules();
69
70 return [
71 [
72 $modules['noTemplateModule'],
73 [],
74 ],
75 [
76 $modules['htmlTemplateModule'],
77 [
78 'mediawiki.template',
79 ],
80 ],
81 [
82 $modules['templateModuleHandlebars'],
83 [
84 'mediawiki.template',
85 'mediawiki.template.handlebars',
86 ],
87 ],
88 [
89 $modules['aliasFooFromBar'],
90 [
91 'mediawiki.template',
92 'mediawiki.template.foo',
93 ],
94 ],
95 ];
96 }
97
98 /**
99 * @dataProvider providerTemplateDependencies
100 * @covers ResourceLoaderFileModule::__construct
101 * @covers ResourceLoaderFileModule::getDependencies
102 */
103 public function testTemplateDependencies( $module, $expected ) {
104 $rl = new ResourceLoaderFileModule( $module );
105 $rl->setName( 'testing' );
106 $this->assertEquals( $rl->getDependencies(), $expected );
107 }
108
109 public static function providerDeprecatedModules() {
110 return [
111 [
112 'deprecatedModule',
113 'mw.log.warn("This page is using the deprecated ResourceLoader module \"deprecatedModule\".");',
114 ],
115 [
116 'deprecatedTomorrow',
117 'mw.log.warn(' .
118 '"This page is using the deprecated ResourceLoader module \"deprecatedTomorrow\".\\n' .
119 "Will be removed tomorrow." .
120 '");'
121 ]
122 ];
123 }
124
125 /**
126 * @dataProvider providerDeprecatedModules
127 * @covers ResourceLoaderFileModule::getScript
128 */
129 public function testDeprecatedModules( $name, $expected ) {
130 $modules = self::getModules();
131 $rl = new ResourceLoaderFileModule( $modules[$name] );
132 $rl->setName( $name );
133 $ctx = $this->getResourceLoaderContext( 'en', 'ltr' );
134 $this->assertEquals( $rl->getScript( $ctx ), $expected );
135 }
136
137 /**
138 * @covers ResourceLoaderFileModule::getAllStyleFiles
139 * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
140 * @covers ResourceLoaderFileModule::getSkinStyleFiles
141 */
142 public function testGetAllSkinStyleFiles() {
143 $baseParams = [
144 'scripts' => [
145 'foo.js',
146 'bar.js',
147 ],
148 'styles' => [
149 'foo.css',
150 'bar.css' => [ 'media' => 'print' ],
151 'screen.less' => [ 'media' => 'screen' ],
152 'screen-query.css' => [ 'media' => 'screen and (min-width: 400px)' ],
153 ],
154 'skinStyles' => [
155 'default' => 'quux-fallback.less',
156 'fakeskin' => [
157 'baz-vector.css',
158 'quux-vector.less',
159 ],
160 ],
161 'messages' => [
162 'hello',
163 'world',
164 ],
165 ];
166
167 $module = new ResourceLoaderFileModule( $baseParams );
168 $module->setName( 'testing' );
169
170 $this->assertEquals(
171 [
172 'foo.css',
173 'baz-vector.css',
174 'quux-vector.less',
175 'quux-fallback.less',
176 'bar.css',
177 'screen.less',
178 'screen-query.css',
179 ],
180 array_map( 'basename', $module->getAllStyleFiles() )
181 );
182 }
183
184 /**
185 * Strip @noflip annotations from CSS code.
186 * @param string $css
187 * @return string
188 */
189 private static function stripNoflip( $css ) {
190 return str_replace( '/*@noflip*/ ', '', $css );
191 }
192
193 /**
194 * What happens when you mix @embed and @noflip?
195 * This really is an integration test, but oh well.
196 *
197 * @covers ResourceLoaderFileModule::getStyles
198 * @covers ResourceLoaderFileModule::getStyleFiles
199 */
200 public function testMixedCssAnnotations() {
201 $basePath = __DIR__ . '/../../data/css';
202 $testModule = new ResourceLoaderFileModule( [
203 'localBasePath' => $basePath,
204 'styles' => [ 'test.css' ],
205 ] );
206 $testModule->setName( 'testing' );
207 $expectedModule = new ResourceLoaderFileModule( [
208 'localBasePath' => $basePath,
209 'styles' => [ 'expected.css' ],
210 ] );
211 $expectedModule->setName( 'testing' );
212
213 $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
214 $contextRtl = $this->getResourceLoaderContext( 'he', 'rtl' );
215
216 // Since we want to compare the effect of @noflip+@embed against the effect of just @embed, and
217 // the @noflip annotations are always preserved, we need to strip them first.
218 $this->assertEquals(
219 $expectedModule->getStyles( $contextLtr ),
220 self::stripNoflip( $testModule->getStyles( $contextLtr ) ),
221 "/*@noflip*/ with /*@embed*/ gives correct results in LTR mode"
222 );
223 $this->assertEquals(
224 $expectedModule->getStyles( $contextLtr ),
225 self::stripNoflip( $testModule->getStyles( $contextRtl ) ),
226 "/*@noflip*/ with /*@embed*/ gives correct results in RTL mode"
227 );
228 }
229
230 public static function providerGetTemplates() {
231 $modules = self::getModules();
232
233 return [
234 [
235 $modules['noTemplateModule'],
236 [],
237 ],
238 [
239 $modules['templateModuleHandlebars'],
240 [
241 'templates/template_awesome.handlebars' => "wow\n",
242 ],
243 ],
244 [
245 $modules['htmlTemplateModule'],
246 [
247 'templates/template.html' => "<strong>hello</strong>\n",
248 'templates/template2.html' => "<div>goodbye</div>\n",
249 ],
250 ],
251 [
252 $modules['aliasedHtmlTemplateModule'],
253 [
254 'foo.html' => "<strong>hello</strong>\n",
255 'bar.html' => "<div>goodbye</div>\n",
256 ],
257 ],
258 ];
259 }
260
261 /**
262 * @dataProvider providerGetTemplates
263 * @covers ResourceLoaderFileModule::getTemplates
264 */
265 public function testGetTemplates( $module, $expected ) {
266 $rl = new ResourceLoaderFileModule( $module );
267 $rl->setName( 'testing' );
268
269 $this->assertEquals( $rl->getTemplates(), $expected );
270 }
271
272 public function testBomConcatenation() {
273 $basePath = __DIR__ . '/../../data/css';
274 $testModule = new ResourceLoaderFileModule( [
275 'localBasePath' => $basePath,
276 'styles' => [ 'bom.css' ],
277 ] );
278 $testModule->setName( 'testing' );
279 $this->assertEquals(
280 substr( file_get_contents( "$basePath/bom.css" ), 0, 10 ),
281 "\xef\xbb\xbf.efbbbf",
282 'File has leading BOM'
283 );
284
285 $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
286 $this->assertEquals(
287 $testModule->getStyles( $contextLtr ),
288 [ 'all' => ".efbbbf_bom_char_at_start_of_file {}\n" ],
289 'Leading BOM removed when concatenating files'
290 );
291 }
292 }