X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/tests/phpunit/includes/MessageTest.php diff --git a/tests/phpunit/includes/MessageTest.php b/tests/phpunit/includes/MessageTest.php new file mode 100644 index 00000000..912bffe6 --- /dev/null +++ b/tests/phpunit/includes/MessageTest.php @@ -0,0 +1,852 @@ +setMwGlobals( [ + 'wgForceUIMsgAsContentMsg' => [], + ] ); + $this->setUserLang( 'en' ); + } + + /** + * @covers Message::__construct + * @dataProvider provideConstructor + */ + public function testConstructor( $expectedLang, $key, $params, $language ) { + $message = new Message( $key, $params, $language ); + + $this->assertSame( $key, $message->getKey() ); + $this->assertSame( $params, $message->getParams() ); + $this->assertEquals( $expectedLang, $message->getLanguage() ); + + $messageSpecifier = $this->getMockForAbstractClass( 'MessageSpecifier' ); + $messageSpecifier->expects( $this->any() ) + ->method( 'getKey' )->will( $this->returnValue( $key ) ); + $messageSpecifier->expects( $this->any() ) + ->method( 'getParams' )->will( $this->returnValue( $params ) ); + $message = new Message( $messageSpecifier, [], $language ); + + $this->assertSame( $key, $message->getKey() ); + $this->assertSame( $params, $message->getParams() ); + $this->assertEquals( $expectedLang, $message->getLanguage() ); + } + + public static function provideConstructor() { + $langDe = Language::factory( 'de' ); + $langEn = Language::factory( 'en' ); + + return [ + [ $langDe, 'foo', [], $langDe ], + [ $langDe, 'foo', [ 'bar' ], $langDe ], + [ $langEn, 'foo', [ 'bar' ], null ] + ]; + } + + public static function provideConstructorParams() { + return [ + [ + [], + [], + ], + [ + [], + [ [] ], + ], + [ + [ 'foo' ], + [ 'foo' ], + ], + [ + [ 'foo', 'bar' ], + [ 'foo', 'bar' ], + ], + [ + [ 'baz' ], + [ [ 'baz' ] ], + ], + [ + [ 'baz', 'foo' ], + [ [ 'baz', 'foo' ] ], + ], + [ + [ Message::rawParam( 'baz' ) ], + [ Message::rawParam( 'baz' ) ], + ], + [ + [ Message::rawParam( 'baz' ), 'foo' ], + [ Message::rawParam( 'baz' ), 'foo' ], + ], + [ + [ Message::rawParam( 'baz' ) ], + [ [ Message::rawParam( 'baz' ) ] ], + ], + [ + [ Message::rawParam( 'baz' ), 'foo' ], + [ [ Message::rawParam( 'baz' ), 'foo' ] ], + ], + + // Test handling of erroneous input, to detect if it changes + [ + [ [ 'baz', 'foo' ], 'hhh' ], + [ [ 'baz', 'foo' ], 'hhh' ], + ], + [ + [ [ 'baz', 'foo' ], 'hhh', [ 'ahahahahha' ] ], + [ [ 'baz', 'foo' ], 'hhh', [ 'ahahahahha' ] ], + ], + [ + [ [ 'baz', 'foo' ], [ 'ahahahahha' ] ], + [ [ 'baz', 'foo' ], [ 'ahahahahha' ] ], + ], + [ + [ [ 'baz' ], [ 'ahahahahha' ] ], + [ [ 'baz' ], [ 'ahahahahha' ] ], + ], + ]; + } + + /** + * @covers Message::__construct + * @covers Message::getParams + * @dataProvider provideConstructorParams + */ + public function testConstructorParams( $expected, $args ) { + $msg = new Message( 'imasomething' ); + + $returned = call_user_func_array( [ $msg, 'params' ], $args ); + + $this->assertSame( $msg, $returned ); + $this->assertSame( $expected, $msg->getParams() ); + } + + public static function provideConstructorLanguage() { + return [ + [ 'foo', [ 'bar' ], 'en' ], + [ 'foo', [ 'bar' ], 'de' ] + ]; + } + + /** + * @covers Message::__construct + * @covers Message::getLanguage + * @dataProvider provideConstructorLanguage + */ + public function testConstructorLanguage( $key, $params, $languageCode ) { + $language = Language::factory( $languageCode ); + $message = new Message( $key, $params, $language ); + + $this->assertEquals( $language, $message->getLanguage() ); + } + + public static function provideKeys() { + return [ + 'string' => [ + 'key' => 'mainpage', + 'expected' => [ 'mainpage' ], + ], + 'single' => [ + 'key' => [ 'mainpage' ], + 'expected' => [ 'mainpage' ], + ], + 'multi' => [ + 'key' => [ 'mainpage-foo', 'mainpage-bar', 'mainpage' ], + 'expected' => [ 'mainpage-foo', 'mainpage-bar', 'mainpage' ], + ], + 'empty' => [ + 'key' => [], + 'expected' => null, + 'exception' => 'InvalidArgumentException', + ], + 'null' => [ + 'key' => null, + 'expected' => null, + 'exception' => 'InvalidArgumentException', + ], + 'bad type' => [ + 'key' => 123, + 'expected' => null, + 'exception' => 'InvalidArgumentException', + ], + ]; + } + + /** + * @covers Message::__construct + * @covers Message::getKey + * @covers Message::isMultiKey + * @covers Message::getKeysToTry + * @dataProvider provideKeys + */ + public function testKeys( $key, $expected, $exception = null ) { + if ( $exception ) { + $this->setExpectedException( $exception ); + } + + $msg = new Message( $key ); + $this->assertContains( $msg->getKey(), $expected ); + $this->assertSame( $expected, $msg->getKeysToTry() ); + $this->assertSame( count( $expected ) > 1, $msg->isMultiKey() ); + } + + /** + * @covers ::wfMessage + */ + public function testWfMessage() { + $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) ); + $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) ); + } + + /** + * @covers Message::newFromKey + */ + public function testNewFromKey() { + $this->assertInstanceOf( 'Message', Message::newFromKey( 'mainpage' ) ); + $this->assertInstanceOf( 'Message', Message::newFromKey( 'i-dont-exist-evar' ) ); + } + + /** + * @covers ::wfMessage + * @covers Message::__construct + */ + public function testWfMessageParams() { + $this->assertSame( 'Return to $1.', wfMessage( 'returnto' )->text() ); + $this->assertSame( 'Return to $1.', wfMessage( 'returnto', [] )->text() ); + $this->assertSame( + 'Return to 1,024.', + wfMessage( 'returnto', Message::numParam( 1024 ) )->text() + ); + $this->assertSame( + 'Return to 1,024.', + wfMessage( 'returnto', [ Message::numParam( 1024 ) ] )->text() + ); + $this->assertSame( + 'You have foo (bar).', + wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text() + ); + $this->assertSame( + 'You have foo (bar).', + wfMessage( 'youhavenewmessages', [ 'foo', 'bar' ] )->text() + ); + $this->assertSame( + 'You have 1,024 (bar).', + wfMessage( + 'youhavenewmessages', + Message::numParam( 1024 ), 'bar' + )->text() + ); + $this->assertSame( + 'You have foo (2,048).', + wfMessage( + 'youhavenewmessages', + 'foo', Message::numParam( 2048 ) + )->text() + ); + $this->assertSame( + 'You have 1,024 (2,048).', + wfMessage( + 'youhavenewmessages', + [ Message::numParam( 1024 ), Message::numParam( 2048 ) ] + )->text() + ); + } + + /** + * @covers Message::exists + */ + public function testExists() { + $this->assertTrue( wfMessage( 'mainpage' )->exists() ); + $this->assertTrue( wfMessage( 'mainpage' )->params( [] )->exists() ); + $this->assertTrue( wfMessage( 'mainpage' )->rawParams( 'foo', 123 )->exists() ); + $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->exists() ); + $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->params( [] )->exists() ); + $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->rawParams( 'foo', 123 )->exists() ); + } + + /** + * @covers Message::__construct + * @covers Message::text + * @covers Message::plain + * @covers Message::escaped + * @covers Message::toString + */ + public function testToStringKey() { + $this->assertSame( 'Main Page', wfMessage( 'mainpage' )->text() ); + $this->assertSame( '⧼i-dont-exist-evar⧽', wfMessage( 'i-dont-exist-evar' )->text() ); + $this->assertSame( '⧼i<dont>exist-evar⧽', wfMessage( 'iexist-evar' )->text() ); + $this->assertSame( '⧼i-dont-exist-evar⧽', wfMessage( 'i-dont-exist-evar' )->plain() ); + $this->assertSame( '⧼i<dont>exist-evar⧽', wfMessage( 'iexist-evar' )->plain() ); + $this->assertSame( '⧼i-dont-exist-evar⧽', wfMessage( 'i-dont-exist-evar' )->escaped() ); + $this->assertSame( + '⧼i<dont>exist-evar⧽', + wfMessage( 'iexist-evar' )->escaped() + ); + } + + public static function provideToString() { + return [ + // key, transformation, transformed, transformed implicitly + [ 'mainpage', 'plain', 'Main Page', 'Main Page' ], + [ 'i-dont-exist-evar', 'plain', '⧼i-dont-exist-evar⧽', '⧼i-dont-exist-evar⧽' ], + [ 'i-dont-exist-evar', 'escaped', '⧼i-dont-exist-evar⧽', '⧼i-dont-exist-evar⧽' ], + [ 'script>alert(1)alert(1)assertSame( $expect, $msg->$format() ); + $this->assertSame( $expect, $msg->toString(), 'toString is unaffected by previous call' ); + $this->assertSame( $expectImplicit, $msg->__toString() ); + $this->assertSame( $expect, $msg->toString(), 'toString is unaffected by __toString' ); + } + + public static function provideToString_raw() { + return [ + [ 'foo', 'parse', 'foo', 'foo' ], + [ 'foo', 'escaped', '<span>foo</span>', + 'foo' ], + [ 'foo', 'plain', 'foo', 'foo' ], + [ '', 'parse', '<script>alert(1)</script>', + '<script>alert(1)</script>' ], + [ '', 'escaped', '<script>alert(1)</script>', + '<script>alert(1)</script>' ], + [ '', 'plain', '', + '<script>alert(1)</script>' ], + ]; + } + + /** + * @covers Message::toString + * @covers Message::__toString + * @dataProvider provideToString_raw + */ + public function testToString_raw( $message, $format, $expect, $expectImplicit ) { + // make the message behave like RawMessage and use the key as-is + $msg = $this->getMockBuilder( Message::class )->setMethods( [ 'fetchMessage' ] ) + ->disableOriginalConstructor() + ->getMock(); + $msg->expects( $this->any() )->method( 'fetchMessage' )->willReturn( $message ); + /** @var Message $msg */ + $this->assertSame( $expect, $msg->$format() ); + $this->assertSame( $expect, $msg->toString(), 'toString is unaffected by previous call' ); + $this->assertSame( $expectImplicit, $msg->__toString() ); + $this->assertSame( $expect, $msg->toString(), 'toString is unaffected by __toString' ); + } + + /** + * @covers Message::inLanguage + */ + public function testInLanguage() { + $this->assertSame( 'Main Page', wfMessage( 'mainpage' )->inLanguage( 'en' )->text() ); + $this->assertSame( 'Заглавная страница', + wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() ); + + // NOTE: make sure internal caching of the message text is reset appropriately + $msg = wfMessage( 'mainpage' ); + $this->assertSame( 'Main Page', $msg->inLanguage( Language::factory( 'en' ) )->text() ); + $this->assertSame( + 'Заглавная страница', + $msg->inLanguage( Language::factory( 'ru' ) )->text() + ); + } + + /** + * @covers Message::rawParam + * @covers Message::rawParams + */ + public function testRawParams() { + $this->assertSame( + '(Заглавная страница)', + wfMessage( 'parentheses', 'Заглавная страница' )->plain() + ); + $this->assertSame( + '(Заглавная страница $1)', + wfMessage( 'parentheses', 'Заглавная страница $1' )->plain() + ); + $this->assertSame( + '(Заглавная страница)', + wfMessage( 'parentheses' )->rawParams( 'Заглавная страница' )->plain() + ); + $this->assertSame( + '(Заглавная страница $1)', + wfMessage( 'parentheses' )->rawParams( 'Заглавная страница $1' )->plain() + ); + } + + /** + * @covers RawMessage::__construct + * @covers RawMessage::fetchMessage + */ + public function testRawMessage() { + $msg = new RawMessage( 'example &' ); + $this->assertSame( 'example &', $msg->plain() ); + $this->assertSame( 'example &', $msg->escaped() ); + } + + public function testRawHtmlInMsg() { + global $wgParserConf; + $this->setMwGlobals( 'wgRawHtml', true ); + // We have to reset the core hook registration. + // to register the html hook + MessageCache::destroyInstance(); + $this->setMwGlobals( 'wgParser', + ObjectFactory::constructClassInstance( $wgParserConf['class'], [ $wgParserConf ] ) + ); + + $msg = new RawMessage( '' ); + $txt = '<html> tags cannot be' . + ' used outside of normal pages.'; + $this->assertSame( $txt, $msg->parse() ); + } + + /** + * @covers Message::params + * @covers Message::toString + * @covers Message::replaceParameters + */ + public function testReplaceManyParams() { + $msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' ); + // One less than above has placeholders + $params = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' ]; + $this->assertSame( + 'abcdefghijka2', + $msg->params( $params )->plain(), + 'Params > 9 are replaced correctly' + ); + + $msg = new RawMessage( 'Params$*' ); + $params = [ 'ab', 'bc', 'cd' ]; + $this->assertSame( + 'Params: ab, bc, cd', + $msg->params( $params )->text() + ); + } + + /** + * @covers Message::numParam + * @covers Message::numParams + */ + public function testNumParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatNum( 123456.789 ), + $msg->inLanguage( $lang )->numParams( 123456.789 )->plain(), + 'numParams is handled correctly' + ); + } + + /** + * @covers Message::durationParam + * @covers Message::durationParams + */ + public function testDurationParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatDuration( 1234 ), + $msg->inLanguage( $lang )->durationParams( 1234 )->plain(), + 'durationParams is handled correctly' + ); + } + + /** + * FIXME: This should not need database, but Language#formatExpiry does (T57912) + * @group Database + * @covers Message::expiryParam + * @covers Message::expiryParams + */ + public function testExpiryParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatExpiry( wfTimestampNow() ), + $msg->inLanguage( $lang )->expiryParams( wfTimestampNow() )->plain(), + 'expiryParams is handled correctly' + ); + } + + /** + * @covers Message::timeperiodParam + * @covers Message::timeperiodParams + */ + public function testTimeperiodParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatTimePeriod( 1234 ), + $msg->inLanguage( $lang )->timeperiodParams( 1234 )->plain(), + 'timeperiodParams is handled correctly' + ); + } + + /** + * @covers Message::sizeParam + * @covers Message::sizeParams + */ + public function testSizeParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatSize( 123456 ), + $msg->inLanguage( $lang )->sizeParams( 123456 )->plain(), + 'sizeParams is handled correctly' + ); + } + + /** + * @covers Message::bitrateParam + * @covers Message::bitrateParams + */ + public function testBitrateParams() { + $lang = Language::factory( 'en' ); + $msg = new RawMessage( '$1' ); + + $this->assertSame( + $lang->formatBitrate( 123456 ), + $msg->inLanguage( $lang )->bitrateParams( 123456 )->plain(), + 'bitrateParams is handled correctly' + ); + } + + public static function providePlaintextParams() { + return [ + [ + 'one $2
foo
[[Bar]] {{Baz}} <', + 'plain', + ], + + [ + // expect + 'one $2
foo
[[Bar]] {{Baz}} <', + // format + 'text', + ], + [ + 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;', + 'escaped', + ], + + [ + 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;', + 'parse', + ], + + [ + "

one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;\n

", + 'parseAsBlock', + ], + ]; + } + + /** + * @covers Message::plaintextParam + * @covers Message::plaintextParams + * @covers Message::formatPlaintext + * @covers Message::toString + * @covers Message::parse + * @covers Message::parseAsBlock + * @dataProvider providePlaintextParams + */ + public function testPlaintextParams( $expect, $format ) { + $lang = Language::factory( 'en' ); + + $msg = new RawMessage( '$1 $2' ); + $params = [ + 'one $2', + '
foo
[[Bar]] {{Baz}} <', + ]; + $this->assertSame( + $expect, + $msg->inLanguage( $lang )->plaintextParams( $params )->$format(), + "Fail formatting for $format" + ); + } + + public static function provideListParam() { + $lang = Language::factory( 'de' ); + $msg1 = new Message( 'mainpage', [], $lang ); + $msg2 = new RawMessage( "''link''", [], $lang ); + + return [ + 'Simple comma list' => [ + [ 'a', 'b', 'c' ], + 'comma', + 'text', + 'a, b, c' + ], + + 'Simple semicolon list' => [ + [ 'a', 'b', 'c' ], + 'semicolon', + 'text', + 'a; b; c' + ], + + 'Simple pipe list' => [ + [ 'a', 'b', 'c' ], + 'pipe', + 'text', + 'a | b | c' + ], + + 'Simple text list' => [ + [ 'a', 'b', 'c' ], + 'text', + 'text', + 'a, b and c' + ], + + 'Empty list' => [ + [], + 'comma', + 'text', + '' + ], + + 'List with all "before" params, ->text()' => [ + [ "''link''", Message::numParam( 12345678 ) ], + 'semicolon', + 'text', + '\'\'link\'\'; 12,345,678' + ], + + 'List with all "before" params, ->parse()' => [ + [ "''link''", Message::numParam( 12345678 ) ], + 'semicolon', + 'parse', + 'link; 12,345,678' + ], + + 'List with all "after" params, ->text()' => [ + [ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ], + 'semicolon', + 'text', + 'Main Page; \'\'link\'\'; [[foo]]' + ], + + 'List with all "after" params, ->parse()' => [ + [ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ], + 'semicolon', + 'parse', + 'Main Page; link; [[foo]]' + ], + + 'List with both "before" and "after" params, ->text()' => [ + [ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ], + 'semicolon', + 'text', + 'Main Page; \'\'link\'\'; [[foo]]; \'\'link\'\'; 12,345,678' + ], + + 'List with both "before" and "after" params, ->parse()' => [ + [ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ], + 'semicolon', + 'parse', + 'Main Page; link; [[foo]]; link; 12,345,678' + ], + ]; + } + + /** + * @covers Message::listParam + * @covers Message::extractParam + * @covers Message::formatListParam + * @dataProvider provideListParam + */ + public function testListParam( $list, $type, $format, $expect ) { + $lang = Language::factory( 'en' ); + + $msg = new RawMessage( '$1' ); + $msg->params( [ Message::listParam( $list, $type ) ] ); + $this->assertEquals( + $expect, + $msg->inLanguage( $lang )->$format() + ); + } + + /** + * @covers Message::extractParam + */ + public function testMessageAsParam() { + $this->setMwGlobals( [ + 'wgScript' => '/wiki/index.php', + 'wgArticlePath' => '/wiki/$1', + ] ); + + $msg = new Message( 'returnto', [ + new Message( 'apihelp-link', [ + 'foo', new Message( 'mainpage', [], Language::factory( 'en' ) ) + ], Language::factory( 'de' ) ) + ], Language::factory( 'es' ) ); + + $this->assertEquals( + 'Volver a [[Special:ApiHelp/foo|Página principal]].', + $msg->text(), + 'Process with ->text()' + ); + $this->assertEquals( + '

Volver a Página ' + . "principal.\n

", + $msg->parseAsBlock(), + 'Process with ->parseAsBlock()' + ); + } + + public static function provideParser() { + return [ + [ + "''&'' ", + 'plain', + ], + + [ + "''&'' ", + 'text', + ], + [ + '& <x>', + 'parse', + ], + + [ + "

& <x>\n

", + 'parseAsBlock', + ], + ]; + } + + /** + * @covers Message::text + * @covers Message::parse + * @covers Message::parseAsBlock + * @covers Message::toString + * @covers Message::transformText + * @covers Message::parseText + * @dataProvider provideParser + */ + public function testParser( $expect, $format ) { + $msg = new RawMessage( "''&'' " ); + $this->assertSame( + $expect, + $msg->inLanguage( 'en' )->$format() + ); + } + + /** + * @covers Message::inContentLanguage + */ + public function testInContentLanguage() { + $this->setUserLang( 'fr' ); + + // NOTE: make sure internal caching of the message text is reset appropriately + $msg = wfMessage( 'mainpage' ); + $this->assertSame( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" ); + $this->assertSame( 'Main Page', $msg->inContentLanguage()->plain(), "inContentLanguage()" ); + $this->assertSame( 'Accueil', $msg->inLanguage( 'fr' )->plain(), "inLanguage( 'fr' )" ); + } + + /** + * @covers Message::inContentLanguage + */ + public function testInContentLanguageOverride() { + $this->setMwGlobals( [ + 'wgForceUIMsgAsContentMsg' => [ 'mainpage' ], + ] ); + $this->setUserLang( 'fr' ); + + // NOTE: make sure internal caching of the message text is reset appropriately. + // NOTE: wgForceUIMsgAsContentMsg forces the messages *current* language to be used. + $msg = wfMessage( 'mainpage' ); + $this->assertSame( + 'Accueil', + $msg->inContentLanguage()->plain(), + 'inContentLanguage() with ForceUIMsg override enabled' + ); + $this->assertSame( 'Main Page', $msg->inLanguage( 'en' )->plain(), "inLanguage( 'en' )" ); + $this->assertSame( + 'Main Page', + $msg->inContentLanguage()->plain(), + 'inContentLanguage() with ForceUIMsg override enabled' + ); + $this->assertSame( 'Hauptseite', $msg->inLanguage( 'de' )->plain(), "inLanguage( 'de' )" ); + } + + /** + * @expectedException MWException + * @covers Message::inLanguage + */ + public function testInLanguageThrows() { + wfMessage( 'foo' )->inLanguage( 123 ); + } + + /** + * @covers Message::serialize + * @covers Message::unserialize + */ + public function testSerialization() { + $msg = new Message( 'parentheses' ); + $msg->rawParams( 'foo' ); + $msg->title( Title::newFromText( 'Testing' ) ); + $this->assertSame( '(foo)', $msg->parse(), 'Sanity check' ); + $msg = unserialize( serialize( $msg ) ); + $this->assertSame( '(foo)', $msg->parse() ); + $title = TestingAccessWrapper::newFromObject( $msg )->title; + $this->assertInstanceOf( 'Title', $title ); + $this->assertSame( 'Testing', $title->getFullText() ); + + $msg = new Message( 'mainpage' ); + $msg->inLanguage( 'de' ); + $this->assertSame( 'Hauptseite', $msg->plain(), 'Sanity check' ); + $msg = unserialize( serialize( $msg ) ); + $this->assertSame( 'Hauptseite', $msg->plain() ); + } + + /** + * @covers Message::newFromSpecifier + * @dataProvider provideNewFromSpecifier + */ + public function testNewFromSpecifier( $value, $expectedText ) { + $message = Message::newFromSpecifier( $value ); + $this->assertInstanceOf( Message::class, $message ); + if ( $value instanceof Message ) { + $this->assertInstanceOf( get_class( $value ), $message ); + $this->assertEquals( $value, $message ); + } + $this->assertSame( $expectedText, $message->text() ); + } + + public function provideNewFromSpecifier() { + $messageSpecifier = $this->getMockForAbstractClass( MessageSpecifier::class ); + $messageSpecifier->expects( $this->any() )->method( 'getKey' )->willReturn( 'mainpage' ); + $messageSpecifier->expects( $this->any() )->method( 'getParams' )->willReturn( [] ); + + return [ + 'string' => [ 'mainpage', 'Main Page' ], + 'array' => [ [ 'youhavenewmessages', 'foo', 'bar' ], 'You have foo (bar).' ], + 'Message' => [ new Message( 'youhavenewmessages', [ 'foo', 'bar' ] ), 'You have foo (bar).' ], + 'RawMessage' => [ new RawMessage( 'foo ($1)', [ 'bar' ] ), 'foo (bar)' ], + 'ApiMessage' => [ new ApiMessage( [ 'mainpage' ], 'code', [ 'data' ] ), 'Main Page' ], + 'MessageSpecifier' => [ $messageSpecifier, 'Main Page' ], + 'nested RawMessage' => [ [ new RawMessage( 'foo ($1)', [ 'bar' ] ) ], 'foo (bar)' ], + ]; + } +}