3 class MessageTest
extends MediaWikiLangTestCase
{
5 protected function setUp() {
9 'wgForceUIMsgAsContentMsg' => [],
11 $this->setUserLang( 'en' );
15 * @covers Message::__construct
16 * @dataProvider provideConstructor
18 public function testConstructor( $expectedLang, $key, $params, $language ) {
19 $message = new Message( $key, $params, $language );
21 $this->assertEquals( $key, $message->getKey() );
22 $this->assertEquals( $params, $message->getParams() );
23 $this->assertEquals( $expectedLang, $message->getLanguage() );
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, [], $language );
32 $this->assertEquals( $key, $message->getKey() );
33 $this->assertEquals( $params, $message->getParams() );
34 $this->assertEquals( $expectedLang, $message->getLanguage() );
37 public static function provideConstructor() {
38 $langDe = Language
::factory( 'de' );
39 $langEn = Language
::factory( 'en' );
42 [ $langDe, 'foo', [], $langDe ],
43 [ $langDe, 'foo', [ 'bar' ], $langDe ],
44 [ $langEn, 'foo', [ 'bar' ], null ]
48 public static function provideConstructorParams() {
72 [ [ 'baz', 'foo' ], 'hhh' ],
76 [ [ 'baz', 'foo' ], 'hhh', [ 'ahahahahha' ] ],
80 [ [ 'baz', 'foo' ], [ 'ahahahahha' ] ],
84 [ [ 'baz' ], [ 'ahahahahha' ] ],
90 * @covers Message::__construct
91 * @covers Message::getParams
92 * @dataProvider provideConstructorParams
94 public function testConstructorParams( $expected, $args ) {
95 $msg = new Message( 'imasomething' );
97 $returned = call_user_func_array( [ $msg, 'params' ], $args );
99 $this->assertSame( $msg, $returned );
100 $this->assertEquals( $expected, $msg->getParams() );
103 public static function provideConstructorLanguage() {
105 [ 'foo', [ 'bar' ], 'en' ],
106 [ 'foo', [ 'bar' ], 'de' ]
111 * @covers Message::__construct
112 * @covers Message::getLanguage
113 * @dataProvider provideConstructorLanguage
115 public function testConstructorLanguage( $key, $params, $languageCode ) {
116 $language = Language
::factory( $languageCode );
117 $message = new Message( $key, $params, $language );
119 $this->assertEquals( $language, $message->getLanguage() );
122 public static function provideKeys() {
126 'expected' => [ 'mainpage' ],
129 'key' => [ 'mainpage' ],
130 'expected' => [ 'mainpage' ],
133 'key' => [ 'mainpage-foo', 'mainpage-bar', 'mainpage' ],
134 'expected' => [ 'mainpage-foo', 'mainpage-bar', 'mainpage' ],
139 'exception' => 'InvalidArgumentException',
144 'exception' => 'InvalidArgumentException',
149 'exception' => 'InvalidArgumentException',
155 * @covers Message::__construct
156 * @covers Message::getKey
157 * @covers Message::isMultiKey
158 * @covers Message::getKeysToTry
159 * @dataProvider provideKeys
161 public function testKeys( $key, $expected, $exception = null ) {
163 $this->setExpectedException( $exception );
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() );
173 * @covers ::wfMessage
175 public function testWfMessage() {
176 $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
177 $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
181 * @covers Message::newFromKey
183 public function testNewFromKey() {
184 $this->assertInstanceOf( 'Message', Message
::newFromKey( 'mainpage' ) );
185 $this->assertInstanceOf( 'Message', Message
::newFromKey( 'i-dont-exist-evar' ) );
189 * @covers ::wfMessage
190 * @covers Message::__construct
192 public function testWfMessageParams() {
193 $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
194 $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', [] )->text() );
196 'You have foo (bar).',
197 wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
200 'You have foo (bar).',
201 wfMessage( 'youhavenewmessages', [ 'foo', 'bar' ] )->text()
206 * @covers Message::exists
208 public function testExists() {
209 $this->assertTrue( wfMessage( 'mainpage' )->exists() );
210 $this->assertTrue( wfMessage( 'mainpage' )->params( [] )->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( [] )->exists() );
214 $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->rawParams( 'foo', 123 )->exists() );
218 * @covers Message::__construct
219 * @covers Message::text
220 * @covers Message::plain
221 * @covers Message::escaped
222 * @covers Message::toString
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( '⧼i-dont-exist-evar⧽', wfMessage( 'i-dont-exist-evar' )->escaped() );
232 '⧼i<dont>exist-evar⧽',
233 wfMessage( 'i<dont>exist-evar' )->escaped()
237 public static function provideToString() {
239 [ 'mainpage', 'Main Page' ],
240 [ 'i-dont-exist-evar', '⧼i-dont-exist-evar⧽' ],
241 [ 'i-dont-exist-evar', '⧼i-dont-exist-evar⧽', 'escaped' ],
242 [ 'script>alert(1)</script', '⧼script>alert(1)</script⧽', 'escaped' ],
243 [ 'script>alert(1)</script', '⧼script>alert(1)</script⧽' ],
248 * @covers Message::toString
249 * @covers Message::__toString
250 * @dataProvider provideToString
252 public function testToString( $key, $expect, $format = 'plain' ) {
253 $msg = new Message( $key );
255 $this->assertEquals( $expect, $msg->toString() );
256 $this->assertEquals( $expect, $msg->__toString() );
260 * @covers Message::inLanguage
262 public function testInLanguage() {
263 $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inLanguage( 'en' )->text() );
264 $this->assertEquals( 'Заглавная страница',
265 wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() );
267 // NOTE: make sure internal caching of the message text is reset appropriately
268 $msg = wfMessage( 'mainpage' );
269 $this->assertEquals( 'Main Page', $msg->inLanguage( Language
::factory( 'en' ) )->text() );
271 'Заглавная страница',
272 $msg->inLanguage( Language
::factory( 'ru' ) )->text()
277 * @covers Message::rawParam
278 * @covers Message::rawParams
280 public function testRawParams() {
282 '(Заглавная страница)',
283 wfMessage( 'parentheses', 'Заглавная страница' )->plain()
286 '(Заглавная страница $1)',
287 wfMessage( 'parentheses', 'Заглавная страница $1' )->plain()
290 '(Заглавная страница)',
291 wfMessage( 'parentheses' )->rawParams( 'Заглавная страница' )->plain()
294 '(Заглавная страница $1)',
295 wfMessage( 'parentheses' )->rawParams( 'Заглавная страница $1' )->plain()
300 * @covers RawMessage::__construct
301 * @covers RawMessage::fetchMessage
303 public function testRawMessage() {
304 $msg = new RawMessage( 'example &' );
305 $this->assertEquals( 'example &', $msg->plain() );
306 $this->assertEquals( 'example &', $msg->escaped() );
310 * @covers Message::params
311 * @covers Message::toString
312 * @covers Message::replaceParameters
314 public function testReplaceManyParams() {
315 $msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' );
316 // One less than above has placeholders
317 $params = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' ];
320 $msg->params( $params )->plain(),
321 'Params > 9 are replaced correctly'
324 $msg = new RawMessage( 'Params$*' );
325 $params = [ 'ab', 'bc', 'cd' ];
327 'Params: ab, bc, cd',
328 $msg->params( $params )->text()
333 * @covers Message::numParam
334 * @covers Message::numParams
336 public function testNumParams() {
337 $lang = Language
::factory( 'en' );
338 $msg = new RawMessage( '$1' );
341 $lang->formatNum( 123456.789 ),
342 $msg->inLanguage( $lang )->numParams( 123456.789 )->plain(),
343 'numParams is handled correctly'
348 * @covers Message::durationParam
349 * @covers Message::durationParams
351 public function testDurationParams() {
352 $lang = Language
::factory( 'en' );
353 $msg = new RawMessage( '$1' );
356 $lang->formatDuration( 1234 ),
357 $msg->inLanguage( $lang )->durationParams( 1234 )->plain(),
358 'durationParams is handled correctly'
363 * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
365 * @covers Message::expiryParam
366 * @covers Message::expiryParams
368 public function testExpiryParams() {
369 $lang = Language
::factory( 'en' );
370 $msg = new RawMessage( '$1' );
373 $lang->formatExpiry( wfTimestampNow() ),
374 $msg->inLanguage( $lang )->expiryParams( wfTimestampNow() )->plain(),
375 'expiryParams is handled correctly'
380 * @covers Message::timeperiodParam
381 * @covers Message::timeperiodParams
383 public function testTimeperiodParams() {
384 $lang = Language
::factory( 'en' );
385 $msg = new RawMessage( '$1' );
388 $lang->formatTimePeriod( 1234 ),
389 $msg->inLanguage( $lang )->timeperiodParams( 1234 )->plain(),
390 'timeperiodParams is handled correctly'
395 * @covers Message::sizeParam
396 * @covers Message::sizeParams
398 public function testSizeParams() {
399 $lang = Language
::factory( 'en' );
400 $msg = new RawMessage( '$1' );
403 $lang->formatSize( 123456 ),
404 $msg->inLanguage( $lang )->sizeParams( 123456 )->plain(),
405 'sizeParams is handled correctly'
410 * @covers Message::bitrateParam
411 * @covers Message::bitrateParams
413 public function testBitrateParams() {
414 $lang = Language
::factory( 'en' );
415 $msg = new RawMessage( '$1' );
418 $lang->formatBitrate( 123456 ),
419 $msg->inLanguage( $lang )->bitrateParams( 123456 )->plain(),
420 'bitrateParams is handled correctly'
424 public static function providePlaintextParams() {
427 'one $2 <div>foo</div> [[Bar]] {{Baz}} <',
433 'one $2 <div>foo</div> [[Bar]] {{Baz}} <',
438 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
443 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
448 "<p>one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;\n</p>",
455 * @covers Message::plaintextParam
456 * @covers Message::plaintextParams
457 * @covers Message::formatPlaintext
458 * @covers Message::toString
459 * @covers Message::parse
460 * @covers Message::parseAsBlock
461 * @dataProvider providePlaintextParams
463 public function testPlaintextParams( $expect, $format ) {
464 $lang = Language
::factory( 'en' );
466 $msg = new RawMessage( '$1 $2' );
469 '<div>foo</div> [[Bar]] {{Baz}} <',
473 $msg->inLanguage( $lang )->plaintextParams( $params )->$format(),
474 "Fail formatting for $format"
478 public static function provideParser() {
481 "''&'' <x><!-- x -->",
486 "''&'' <x><!-- x -->",
490 '<i>&</i> <x>',
495 "<p><i>&</i> <x>\n</p>",
502 * @covers Message::text
503 * @covers Message::parse
504 * @covers Message::parseAsBlock
505 * @covers Message::toString
506 * @covers Message::transformText
507 * @covers Message::parseText
508 * @dataProvider provideParser
510 public function testParser( $expect, $format ) {
511 $msg = new RawMessage( "''&'' <x><!-- x -->" );
514 $msg->inLanguage( 'en' )->$format()
519 * @covers Message::inContentLanguage
521 public function testInContentLanguage() {
522 $this->setUserLang( 'fr' );
524 // NOTE: make sure internal caching of the message text is reset appropriately
525 $msg = wfMessage( 'mainpage' );
526 $this->assertEquals( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" );
527 $this->assertEquals( 'Main Page', $msg->inContentLanguage()->plain(), "inContentLanguage()" );
528 $this->assertEquals( 'Accueil', $msg->inLanguage( 'fr' )->plain(), "inLanguage( 'fr' )" );
532 * @covers Message::inContentLanguage
534 public function testInContentLanguageOverride() {
535 $this->setMwGlobals( [
536 'wgForceUIMsgAsContentMsg' => [ 'mainpage' ],
538 $this->setUserLang( 'fr' );
540 // NOTE: make sure internal caching of the message text is reset appropriately.
541 // NOTE: wgForceUIMsgAsContentMsg forces the messages *current* language to be used.
542 $msg = wfMessage( 'mainpage' );
545 $msg->inContentLanguage()->plain(),
546 'inContentLanguage() with ForceUIMsg override enabled'
548 $this->assertEquals( 'Main Page', $msg->inLanguage( 'en' )->plain(), "inLanguage( 'en' )" );
551 $msg->inContentLanguage()->plain(),
552 'inContentLanguage() with ForceUIMsg override enabled'
554 $this->assertEquals( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" );
558 * @expectedException MWException
559 * @covers Message::inLanguage
561 public function testInLanguageThrows() {
562 wfMessage( 'foo' )->inLanguage( 123 );
566 * @covers Message::serialize
567 * @covers Message::unserialize
569 public function testSerialization() {
570 $msg = new Message( 'parentheses' );
571 $msg->rawParams( '<a>foo</a>' );
572 $msg->title( Title
::newFromText( 'Testing' ) );
573 $this->assertEquals( '(<a>foo</a>)', $msg->parse(), 'Sanity check' );
574 $msg = unserialize( serialize( $msg ) );
575 $this->assertEquals( '(<a>foo</a>)', $msg->parse() );
576 $title = TestingAccessWrapper
::newFromObject( $msg )->title
;
577 $this->assertInstanceOf( 'Title', $title );
578 $this->assertEquals( 'Testing', $title->getFullText() );
580 $msg = new Message( 'mainpage' );
581 $msg->inLanguage( 'de' );
582 $this->assertEquals( 'Hauptseite', $msg->plain(), 'Sanity check' );
583 $msg = unserialize( serialize( $msg ) );
584 $this->assertEquals( 'Hauptseite', $msg->plain() );
588 * @covers Message::newFromSpecifier
589 * @dataProvider provideNewFromSpecifier
591 public function testNewFromSpecifier( $value, $expectedText ) {
592 $message = Message
::newFromSpecifier( $value );
593 $this->assertInstanceOf( Message
::class, $message );
594 if ( $value instanceof Message
) {
595 $this->assertInstanceOf( get_class( $value ), $message );
596 $this->assertEquals( $value, $message );
598 $this->assertSame( $expectedText, $message->text() );
601 public function provideNewFromSpecifier() {
602 $messageSpecifier = $this->getMockForAbstractClass( MessageSpecifier
::class );
603 $messageSpecifier->expects( $this->any() )->method( 'getKey' )->willReturn( 'mainpage' );
604 $messageSpecifier->expects( $this->any() )->method( 'getParams' )->willReturn( [] );
607 'string' => [ 'mainpage', 'Main Page' ],
608 'array' => [ [ 'youhavenewmessages', 'foo', 'bar' ], 'You have foo (bar).' ],
609 'Message' => [ new Message( 'youhavenewmessages', [ 'foo', 'bar' ] ), 'You have foo (bar).' ],
610 'RawMessage' => [ new RawMessage( 'foo ($1)', [ 'bar' ] ), 'foo (bar)' ],
611 'ApiMessage' => [ new ApiMessage( [ 'mainpage' ], 'code', [ 'data' ] ), 'Main Page' ],
612 'MessageSpecifier' => [ $messageSpecifier, 'Main Page' ],
613 'nested RawMessage' => [ [ new RawMessage( 'foo ($1)', [ 'bar' ] ) ], 'foo (bar)' ],