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