LocalisationCache: try harder to use LCStoreCDB
[lhc/web/wiklou.git] / tests / phpunit / includes / MessageTest.php
1 <?php
2
3 class MessageTest extends MediaWikiLangTestCase {
4
5 protected function setUp() {
6 parent::setUp();
7
8 $this->setMwGlobals( array(
9 'wgLang' => Language::factory( 'en' ),
10 'wgForceUIMsgAsContentMsg' => array(),
11 ) );
12 }
13
14 /**
15 * @covers Message::__construct
16 * @dataProvider provideConstructor
17 */
18 public function testConstructor( $expectedLang, $key, $params, $language ) {
19 $message = new Message( $key, $params, $language );
20
21 $this->assertEquals( $key, $message->getKey() );
22 $this->assertEquals( $params, $message->getParams() );
23 $this->assertEquals( $expectedLang, $message->getLanguage() );
24
25 $messageSpecifier = $this->getMockForAbstractClass( 'MessageSpecifier' );
26 $messageSpecifier->expects( $this->any() )
27 ->method( 'getKey' )->will( $this->returnValue( $key ) );
28 $messageSpecifier->expects( $this->any() )
29 ->method( 'getParams' )->will( $this->returnValue( $params ) );
30 $message = new Message( $messageSpecifier, array(), $language );
31
32 $this->assertEquals( $key, $message->getKey() );
33 $this->assertEquals( $params, $message->getParams() );
34 $this->assertEquals( $expectedLang, $message->getLanguage() );
35 }
36
37 public static function provideConstructor() {
38 $langDe = Language::factory( 'de' );
39 $langEn = Language::factory( 'en' );
40
41 return array(
42 array( $langDe, 'foo', array(), $langDe ),
43 array( $langDe, 'foo', array( 'bar' ), $langDe ),
44 array( $langEn, 'foo', array( 'bar' ), null )
45 );
46 }
47
48 public static function provideConstructorParams() {
49 return array(
50 array(
51 array(),
52 array(),
53 ),
54 array(
55 array( 'foo' ),
56 array( 'foo' ),
57 ),
58 array(
59 array( 'foo', 'bar' ),
60 array( 'foo', 'bar' ),
61 ),
62 array(
63 array( 'baz' ),
64 array( array( 'baz' ) ),
65 ),
66 array(
67 array( 'baz', 'foo' ),
68 array( array( 'baz', 'foo' ) ),
69 ),
70 array(
71 array( 'baz', 'foo' ),
72 array( array( 'baz', 'foo' ), 'hhh' ),
73 ),
74 array(
75 array( 'baz', 'foo' ),
76 array( array( 'baz', 'foo' ), 'hhh', array( 'ahahahahha' ) ),
77 ),
78 array(
79 array( 'baz', 'foo' ),
80 array( array( 'baz', 'foo' ), array( 'ahahahahha' ) ),
81 ),
82 array(
83 array( 'baz' ),
84 array( array( 'baz' ), array( 'ahahahahha' ) ),
85 ),
86 );
87 }
88
89 /**
90 * @covers Message::__construct
91 * @covers Message::getParams
92 * @dataProvider provideConstructorParams
93 */
94 public function testConstructorParams( $expected, $args ) {
95 $msg = new Message( 'imasomething' );
96
97 $returned = call_user_func_array( array( $msg, 'params' ), $args );
98
99 $this->assertSame( $msg, $returned );
100 $this->assertEquals( $expected, $msg->getParams() );
101 }
102
103 public static function provideConstructorLanguage() {
104 return array(
105 array( 'foo', array( 'bar' ), 'en' ),
106 array( 'foo', array( 'bar' ), 'de' )
107 );
108 }
109
110 /**
111 * @covers Message::__construct
112 * @covers Message::getLanguage
113 * @dataProvider provideConstructorLanguage
114 */
115 public function testConstructorLanguage( $key, $params, $languageCode ) {
116 $language = Language::factory( $languageCode );
117 $message = new Message( $key, $params, $language );
118
119 $this->assertEquals( $language, $message->getLanguage() );
120 }
121
122 public static function provideKeys() {
123 return array(
124 'string' => array(
125 'key' => 'mainpage',
126 'expected' => array( 'mainpage' ),
127 ),
128 'single' => array(
129 'key' => array( 'mainpage' ),
130 'expected' => array( 'mainpage' ),
131 ),
132 'multi' => array(
133 'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
134 'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
135 ),
136 'empty' => array(
137 'key' => array(),
138 'expected' => null,
139 'exception' => 'InvalidArgumentException',
140 ),
141 'null' => array(
142 'key' => null,
143 'expected' => null,
144 'exception' => 'InvalidArgumentException',
145 ),
146 'bad type' => array(
147 'key' => 123,
148 'expected' => null,
149 'exception' => 'InvalidArgumentException',
150 ),
151 );
152 }
153
154 /**
155 * @covers Message::__construct
156 * @covers Message::getKey
157 * @covers Message::isMultiKey
158 * @covers Message::getKeysToTry
159 * @dataProvider provideKeys
160 */
161 public function testKeys( $key, $expected, $exception = null ) {
162 if ( $exception ) {
163 $this->setExpectedException( $exception );
164 }
165
166 $msg = new Message( $key );
167 $this->assertContains( $msg->getKey(), $expected );
168 $this->assertEquals( $expected, $msg->getKeysToTry() );
169 $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
170 }
171
172 /**
173 * @covers ::wfMessage
174 */
175 public function testWfMessage() {
176 $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
177 $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
178 }
179
180 /**
181 * @covers Message::newFromKey
182 */
183 public function testNewFromKey() {
184 $this->assertInstanceOf( 'Message', Message::newFromKey( 'mainpage' ) );
185 $this->assertInstanceOf( 'Message', Message::newFromKey( 'i-dont-exist-evar' ) );
186 }
187
188 /**
189 * @covers ::wfMessage
190 * @covers Message::__construct
191 */
192 public function testWfMessageParams() {
193 $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
194 $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
195 $this->assertEquals(
196 'You have foo (bar).',
197 wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
198 );
199 $this->assertEquals(
200 'You have foo (bar).',
201 wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text()
202 );
203 }
204
205 /**
206 * @covers Message::exists
207 */
208 public function testExists() {
209 $this->assertTrue( wfMessage( 'mainpage' )->exists() );
210 $this->assertTrue( wfMessage( 'mainpage' )->params( array() )->exists() );
211 $this->assertTrue( wfMessage( 'mainpage' )->rawParams( 'foo', 123 )->exists() );
212 $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->exists() );
213 $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->params( array() )->exists() );
214 $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->rawParams( 'foo', 123 )->exists() );
215 }
216
217 /**
218 * @covers Message::__construct
219 * @covers Message::text
220 * @covers Message::plain
221 * @covers Message::escaped
222 * @covers Message::toString
223 */
224 public function testToStringKey() {
225 $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->text() );
226 $this->assertEquals( '<i-dont-exist-evar>', wfMessage( 'i-dont-exist-evar' )->text() );
227 $this->assertEquals( '<i<dont>exist-evar>', wfMessage( 'i<dont>exist-evar' )->text() );
228 $this->assertEquals( '<i-dont-exist-evar>', wfMessage( 'i-dont-exist-evar' )->plain() );
229 $this->assertEquals( '<i<dont>exist-evar>', wfMessage( 'i<dont>exist-evar' )->plain() );
230 $this->assertEquals( '&lt;i-dont-exist-evar&gt;', wfMessage( 'i-dont-exist-evar' )->escaped() );
231 $this->assertEquals(
232 '&lt;i&lt;dont&gt;exist-evar&gt;',
233 wfMessage( 'i<dont>exist-evar' )->escaped()
234 );
235 }
236
237 public static function provideToString() {
238 return array(
239 array( 'mainpage', 'Main Page' ),
240 array( 'i-dont-exist-evar', '<i-dont-exist-evar>' ),
241 array( 'i-dont-exist-evar', '&lt;i-dont-exist-evar&gt;', 'escaped' ),
242 );
243 }
244
245 /**
246 * @covers Message::toString
247 * @covers Message::__toString
248 * @dataProvider provideToString
249 */
250 public function testToString( $key, $expect, $format = 'plain' ) {
251 $msg = new Message( $key );
252 $msg->$format();
253 $this->assertEquals( $expect, $msg->toString() );
254 $this->assertEquals( $expect, $msg->__toString() );
255 }
256
257 /**
258 * @covers Message::inLanguage
259 */
260 public function testInLanguage() {
261 $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inLanguage( 'en' )->text() );
262 $this->assertEquals( 'Заглавная страница',
263 wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() );
264
265 // NOTE: make sure internal caching of the message text is reset appropriately
266 $msg = wfMessage( 'mainpage' );
267 $this->assertEquals( 'Main Page', $msg->inLanguage( Language::factory( 'en' ) )->text() );
268 $this->assertEquals(
269 'Заглавная страница',
270 $msg->inLanguage( Language::factory( 'ru' ) )->text()
271 );
272 }
273
274 /**
275 * @covers Message::rawParam
276 * @covers Message::rawParams
277 */
278 public function testRawParams() {
279 $this->assertEquals(
280 '(Заглавная страница)',
281 wfMessage( 'parentheses', 'Заглавная страница' )->plain()
282 );
283 $this->assertEquals(
284 '(Заглавная страница $1)',
285 wfMessage( 'parentheses', 'Заглавная страница $1' )->plain()
286 );
287 $this->assertEquals(
288 '(Заглавная страница)',
289 wfMessage( 'parentheses' )->rawParams( 'Заглавная страница' )->plain()
290 );
291 $this->assertEquals(
292 '(Заглавная страница $1)',
293 wfMessage( 'parentheses' )->rawParams( 'Заглавная страница $1' )->plain()
294 );
295 }
296
297 /**
298 * @covers RawMessage::__construct
299 * @covers RawMessage::fetchMessage
300 */
301 public function testRawMessage() {
302 $msg = new RawMessage( 'example &' );
303 $this->assertEquals( 'example &', $msg->plain() );
304 $this->assertEquals( 'example &amp;', $msg->escaped() );
305 }
306
307 /**
308 * @covers Message::params
309 * @covers Message::toString
310 * @covers Message::replaceParameters
311 */
312 public function testReplaceManyParams() {
313 $msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' );
314 // One less than above has placeholders
315 $params = array( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' );
316 $this->assertEquals(
317 'abcdefghijka2',
318 $msg->params( $params )->plain(),
319 'Params > 9 are replaced correctly'
320 );
321
322 $msg = new RawMessage( 'Params$*' );
323 $params = array( 'ab', 'bc', 'cd' );
324 $this->assertEquals(
325 'Params: ab, bc, cd',
326 $msg->params( $params )->text()
327 );
328 }
329
330 /**
331 * @covers Message::numParam
332 * @covers Message::numParams
333 */
334 public function testNumParams() {
335 $lang = Language::factory( 'en' );
336 $msg = new RawMessage( '$1' );
337
338 $this->assertEquals(
339 $lang->formatNum( 123456.789 ),
340 $msg->inLanguage( $lang )->numParams( 123456.789 )->plain(),
341 'numParams is handled correctly'
342 );
343 }
344
345 /**
346 * @covers Message::durationParam
347 * @covers Message::durationParams
348 */
349 public function testDurationParams() {
350 $lang = Language::factory( 'en' );
351 $msg = new RawMessage( '$1' );
352
353 $this->assertEquals(
354 $lang->formatDuration( 1234 ),
355 $msg->inLanguage( $lang )->durationParams( 1234 )->plain(),
356 'durationParams is handled correctly'
357 );
358 }
359
360 /**
361 * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
362 * @group Database
363 * @covers Message::expiryParam
364 * @covers Message::expiryParams
365 */
366 public function testExpiryParams() {
367 $lang = Language::factory( 'en' );
368 $msg = new RawMessage( '$1' );
369
370 $this->assertEquals(
371 $lang->formatExpiry( wfTimestampNow() ),
372 $msg->inLanguage( $lang )->expiryParams( wfTimestampNow() )->plain(),
373 'expiryParams is handled correctly'
374 );
375 }
376
377 /**
378 * @covers Message::timeperiodParam
379 * @covers Message::timeperiodParams
380 */
381 public function testTimeperiodParams() {
382 $lang = Language::factory( 'en' );
383 $msg = new RawMessage( '$1' );
384
385 $this->assertEquals(
386 $lang->formatTimePeriod( 1234 ),
387 $msg->inLanguage( $lang )->timeperiodParams( 1234 )->plain(),
388 'timeperiodParams is handled correctly'
389 );
390 }
391
392 /**
393 * @covers Message::sizeParam
394 * @covers Message::sizeParams
395 */
396 public function testSizeParams() {
397 $lang = Language::factory( 'en' );
398 $msg = new RawMessage( '$1' );
399
400 $this->assertEquals(
401 $lang->formatSize( 123456 ),
402 $msg->inLanguage( $lang )->sizeParams( 123456 )->plain(),
403 'sizeParams is handled correctly'
404 );
405 }
406
407 /**
408 * @covers Message::bitrateParam
409 * @covers Message::bitrateParams
410 */
411 public function testBitrateParams() {
412 $lang = Language::factory( 'en' );
413 $msg = new RawMessage( '$1' );
414
415 $this->assertEquals(
416 $lang->formatBitrate( 123456 ),
417 $msg->inLanguage( $lang )->bitrateParams( 123456 )->plain(),
418 'bitrateParams is handled correctly'
419 );
420 }
421
422 public static function providePlaintextParams() {
423 return array(
424 array(
425 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
426 'plain',
427 ),
428
429 array(
430 // expect
431 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
432 // format
433 'text',
434 ),
435 array(
436 'one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;',
437 'escaped',
438 ),
439
440 array(
441 'one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;',
442 'parse',
443 ),
444
445 array(
446 "<p>one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;\n</p>",
447 'parseAsBlock',
448 ),
449 );
450 }
451
452 /**
453 * @covers Message::plaintextParam
454 * @covers Message::plaintextParams
455 * @covers Message::formatPlaintext
456 * @covers Message::toString
457 * @covers Message::parse
458 * @covers Message::parseAsBlock
459 * @dataProvider providePlaintextParams
460 */
461 public function testPlaintextParams( $expect, $format ) {
462 $lang = Language::factory( 'en' );
463
464 $msg = new RawMessage( '$1 $2' );
465 $params = array(
466 'one $2',
467 '<div>foo</div> [[Bar]] {{Baz}} &lt;',
468 );
469 $this->assertEquals(
470 $expect,
471 $msg->inLanguage( $lang )->plaintextParams( $params )->$format(),
472 "Fail formatting for $format"
473 );
474 }
475
476 public static function provideParser() {
477 return array(
478 array(
479 "''&'' <x><!-- x -->",
480 'plain',
481 ),
482
483 array(
484 "''&'' <x><!-- x -->",
485 'text',
486 ),
487 array(
488 '<i>&amp;</i> &lt;x&gt;',
489 'parse',
490 ),
491
492 array(
493 "<p><i>&amp;</i> &lt;x&gt;\n</p>",
494 'parseAsBlock',
495 ),
496 );
497 }
498
499 /**
500 * @covers Message::text
501 * @covers Message::parse
502 * @covers Message::parseAsBlock
503 * @covers Message::toString
504 * @covers Message::transformText
505 * @covers Message::parseText
506 * @dataProvider provideParser
507 */
508 public function testParser( $expect, $format ) {
509 $msg = new RawMessage( "''&'' <x><!-- x -->" );
510 $this->assertEquals(
511 $expect,
512 $msg->inLanguage( 'en' )->$format()
513 );
514 }
515
516 /**
517 * @covers Message::inContentLanguage
518 */
519 public function testInContentLanguage() {
520 $this->setMwGlobals( 'wgLang', Language::factory( 'fr' ) );
521
522 // NOTE: make sure internal caching of the message text is reset appropriately
523 $msg = wfMessage( 'mainpage' );
524 $this->assertEquals( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" );
525 $this->assertEquals( 'Main Page', $msg->inContentLanguage()->plain(), "inContentLanguage()" );
526 $this->assertEquals( 'Accueil', $msg->inLanguage( 'fr' )->plain(), "inLanguage( 'fr' )" );
527 }
528
529 /**
530 * @covers Message::inContentLanguage
531 */
532 public function testInContentLanguageOverride() {
533 $this->setMwGlobals( array(
534 'wgLang' => Language::factory( 'fr' ),
535 'wgForceUIMsgAsContentMsg' => array( 'mainpage' ),
536 ) );
537
538 // NOTE: make sure internal caching of the message text is reset appropriately.
539 // NOTE: wgForceUIMsgAsContentMsg forces the messages *current* language to be used.
540 $msg = wfMessage( 'mainpage' );
541 $this->assertEquals(
542 'Accueil',
543 $msg->inContentLanguage()->plain(),
544 'inContentLanguage() with ForceUIMsg override enabled'
545 );
546 $this->assertEquals( 'Main Page', $msg->inLanguage( 'en' )->plain(), "inLanguage( 'en' )" );
547 $this->assertEquals(
548 'Main Page',
549 $msg->inContentLanguage()->plain(),
550 'inContentLanguage() with ForceUIMsg override enabled'
551 );
552 $this->assertEquals( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" );
553 }
554
555 /**
556 * @expectedException MWException
557 * @covers Message::inLanguage
558 */
559 public function testInLanguageThrows() {
560 wfMessage( 'foo' )->inLanguage( 123 );
561 }
562
563 /**
564 * @covers Message::serialize
565 * @covers Message::unserialize
566 */
567 public function testSerialization() {
568 $msg = new Message( 'parentheses' );
569 $msg->rawParams( '<a>foo</a>' );
570 $msg->title( Title::newFromText( 'Testing' ) );
571 $this->assertEquals( '(<a>foo</a>)', $msg->parse(), 'Sanity check' );
572 $msg = unserialize( serialize( $msg ) );
573 $this->assertEquals( '(<a>foo</a>)', $msg->parse() );
574 $title = TestingAccessWrapper::newFromObject( $msg )->title;
575 $this->assertInstanceOf( 'Title', $title );
576 $this->assertEquals( 'Testing', $title->getFullText() );
577
578 $msg = new Message( 'mainpage' );
579 $msg->inLanguage( 'de' );
580 $this->assertEquals( 'Hauptseite', $msg->plain(), 'Sanity check' );
581 $msg = unserialize( serialize( $msg ) );
582 $this->assertEquals( 'Hauptseite', $msg->plain() );
583 }
584 }