diff options
author | Yaco <franco@reevo.org> | 2020-06-04 11:01:00 -0300 |
---|---|---|
committer | Yaco <franco@reevo.org> | 2020-06-04 11:01:00 -0300 |
commit | fc7369835258467bf97eb64f184b93691f9a9fd5 (patch) | |
tree | daabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php |
first commit
Diffstat (limited to 'www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php')
-rw-r--r-- | www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php b/www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php new file mode 100644 index 00000000..aa579ab0 --- /dev/null +++ b/www/wiki/tests/phpunit/includes/api/ApiErrorFormatterTest.php @@ -0,0 +1,642 @@ +<?php + +use Wikimedia\TestingAccessWrapper; + +/** + * @group API + */ +class ApiErrorFormatterTest extends MediaWikiLangTestCase { + + /** + * @covers ApiErrorFormatter + */ + public function testErrorFormatterBasics() { + $result = new ApiResult( 8388608 ); + $formatter = new ApiErrorFormatter( $result, Language::factory( 'de' ), 'wikitext', false ); + $this->assertSame( 'de', $formatter->getLanguage()->getCode() ); + + $formatter->addMessagesFromStatus( null, Status::newGood() ); + $this->assertSame( + [ ApiResult::META_TYPE => 'assoc' ], + $result->getResultData() + ); + + $this->assertSame( [], $formatter->arrayFromStatus( Status::newGood() ) ); + + $wrappedFormatter = TestingAccessWrapper::newFromObject( $formatter ); + $this->assertSame( + 'Blah "kbd" <X> 😊', + $wrappedFormatter->stripMarkup( 'Blah <kbd>kbd</kbd> <b><X></b> 😊' ), + 'stripMarkup' + ); + } + + /** + * @covers ApiErrorFormatter + * @dataProvider provideErrorFormatter + */ + public function testErrorFormatter( $format, $lang, $useDB, + $expect1, $expect2, $expect3 + ) { + $result = new ApiResult( 8388608 ); + $formatter = new ApiErrorFormatter( $result, Language::factory( $lang ), $format, $useDB ); + + // Add default type + $expect1[ApiResult::META_TYPE] = 'assoc'; + $expect2[ApiResult::META_TYPE] = 'assoc'; + $expect3[ApiResult::META_TYPE] = 'assoc'; + + $formatter->addWarning( 'string', 'mainpage' ); + $formatter->addError( 'err', 'mainpage' ); + $this->assertEquals( $expect1, $result->getResultData(), 'Simple test' ); + + $result->reset(); + $formatter->addWarning( 'foo', 'mainpage' ); + $formatter->addWarning( 'foo', 'mainpage' ); + $formatter->addWarning( 'foo', [ 'parentheses', 'foobar' ] ); + $msg1 = wfMessage( 'mainpage' ); + $formatter->addWarning( 'message', $msg1 ); + $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', [ 'overriddenData' => true ] ); + $formatter->addWarning( 'messageWithData', $msg2 ); + $formatter->addError( 'errWithData', $msg2 ); + $this->assertSame( $expect2, $result->getResultData(), 'Complex test' ); + + $this->assertEquals( + $this->removeModuleTag( $expect2['warnings'][2] ), + $formatter->formatMessage( $msg1 ), + 'formatMessage test 1' + ); + $this->assertEquals( + $this->removeModuleTag( $expect2['warnings'][3] ), + $formatter->formatMessage( $msg2 ), + 'formatMessage test 2' + ); + + $result->reset(); + $status = Status::newGood(); + $status->warning( 'mainpage' ); + $status->warning( 'parentheses', 'foobar' ); + $status->warning( $msg1 ); + $status->warning( $msg2 ); + $status->error( 'mainpage' ); + $status->error( 'parentheses', 'foobar' ); + $formatter->addMessagesFromStatus( 'status', $status ); + $this->assertSame( $expect3, $result->getResultData(), 'Status test' ); + + $this->assertSame( + array_map( [ $this, 'removeModuleTag' ], $expect3['errors'] ), + $formatter->arrayFromStatus( $status, 'error' ), + 'arrayFromStatus test for error' + ); + $this->assertSame( + array_map( [ $this, 'removeModuleTag' ], $expect3['warnings'] ), + $formatter->arrayFromStatus( $status, 'warning' ), + 'arrayFromStatus test for warning' + ); + } + + private function removeModuleTag( $s ) { + if ( is_array( $s ) ) { + unset( $s['module'] ); + } + return $s; + } + + public static function provideErrorFormatter() { + $mainpageText = wfMessage( 'mainpage' )->inLanguage( 'de' )->useDatabase( false )->text(); + $parensText = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'de' ) + ->useDatabase( false )->text(); + $mainpageHTML = wfMessage( 'mainpage' )->inLanguage( 'en' )->parse(); + $parensHTML = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'en' )->parse(); + $C = ApiResult::META_CONTENT; + $I = ApiResult::META_INDEXED_TAG_NAME; + $overriddenData = [ 'overriddenData' => true, ApiResult::META_TYPE => 'assoc' ]; + + return [ + $tmp = [ 'wikitext', 'de', false, + [ + 'errors' => [ + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'err', $C => 'text' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'string', $C => 'text' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'overriddenCode', 'text' => $mainpageText, + 'data' => $overriddenData, 'module' => 'errWithData', $C => 'text' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'foo', $C => 'text' ], + [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'foo', $C => 'text' ], + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'message', $C => 'text' ], + [ 'code' => 'overriddenCode', 'text' => $mainpageText, + 'data' => $overriddenData, 'module' => 'messageWithData', $C => 'text' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'status', $C => 'text' ], + [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'status', $C => 'text' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'text' => $mainpageText, 'module' => 'status', $C => 'text' ], + [ 'code' => 'parentheses', 'text' => $parensText, 'module' => 'status', $C => 'text' ], + [ 'code' => 'overriddenCode', 'text' => $mainpageText, + 'data' => $overriddenData, 'module' => 'status', $C => 'text' ], + $I => 'warning', + ], + ], + ], + [ 'plaintext' ] + $tmp, // For these messages, plaintext and wikitext are the same + [ 'html', 'en', true, + [ + 'errors' => [ + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'err', $C => 'html' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'string', $C => 'html' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'overriddenCode', 'html' => $mainpageHTML, + 'data' => $overriddenData, 'module' => 'errWithData', $C => 'html' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'foo', $C => 'html' ], + [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'foo', $C => 'html' ], + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'message', $C => 'html' ], + [ 'code' => 'overriddenCode', 'html' => $mainpageHTML, + 'data' => $overriddenData, 'module' => 'messageWithData', $C => 'html' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'status', $C => 'html' ], + [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'status', $C => 'html' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'html' => $mainpageHTML, 'module' => 'status', $C => 'html' ], + [ 'code' => 'parentheses', 'html' => $parensHTML, 'module' => 'status', $C => 'html' ], + [ 'code' => 'overriddenCode', 'html' => $mainpageHTML, + 'data' => $overriddenData, 'module' => 'status', $C => 'html' ], + $I => 'warning', + ], + ], + ], + [ 'raw', 'fr', true, + [ + 'errors' => [ + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'err', + ], + $I => 'error', + ], + 'warnings' => [ + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'string', + ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ + 'code' => 'overriddenCode', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'data' => $overriddenData, + 'module' => 'errWithData', + ], + $I => 'error', + ], + 'warnings' => [ + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'foo', + ], + [ + 'code' => 'parentheses', + 'key' => 'parentheses', + 'params' => [ 'foobar', $I => 'param' ], + 'module' => 'foo', + ], + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'message', + ], + [ + 'code' => 'overriddenCode', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'data' => $overriddenData, + 'module' => 'messageWithData', + ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'status', + ], + [ + 'code' => 'parentheses', + 'key' => 'parentheses', + 'params' => [ 'foobar', $I => 'param' ], + 'module' => 'status', + ], + $I => 'error', + ], + 'warnings' => [ + [ + 'code' => 'mainpage', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'module' => 'status', + ], + [ + 'code' => 'parentheses', + 'key' => 'parentheses', + 'params' => [ 'foobar', $I => 'param' ], + 'module' => 'status', + ], + [ + 'code' => 'overriddenCode', + 'key' => 'mainpage', + 'params' => [ $I => 'param' ], + 'data' => $overriddenData, + 'module' => 'status', + ], + $I => 'warning', + ], + ], + ], + [ 'none', 'fr', true, + [ + 'errors' => [ + [ 'code' => 'mainpage', 'module' => 'err' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'module' => 'string' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'overriddenCode', 'data' => $overriddenData, + 'module' => 'errWithData' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'module' => 'foo' ], + [ 'code' => 'parentheses', 'module' => 'foo' ], + [ 'code' => 'mainpage', 'module' => 'message' ], + [ 'code' => 'overriddenCode', 'data' => $overriddenData, + 'module' => 'messageWithData' ], + $I => 'warning', + ], + ], + [ + 'errors' => [ + [ 'code' => 'mainpage', 'module' => 'status' ], + [ 'code' => 'parentheses', 'module' => 'status' ], + $I => 'error', + ], + 'warnings' => [ + [ 'code' => 'mainpage', 'module' => 'status' ], + [ 'code' => 'parentheses', 'module' => 'status' ], + [ 'code' => 'overriddenCode', 'data' => $overriddenData, 'module' => 'status' ], + $I => 'warning', + ], + ], + ], + ]; + } + + /** + * @covers ApiErrorFormatter_BackCompat + */ + public function testErrorFormatterBC() { + $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain(); + $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain(); + + $result = new ApiResult( 8388608 ); + $formatter = new ApiErrorFormatter_BackCompat( $result ); + + $this->assertSame( 'en', $formatter->getLanguage()->getCode() ); + + $this->assertSame( [], $formatter->arrayFromStatus( Status::newGood() ) ); + + $formatter->addWarning( 'string', 'mainpage' ); + $formatter->addWarning( 'raw', + new RawMessage( 'Blah <kbd>kbd</kbd> <b><X></b> 😞' ) + ); + $formatter->addError( 'err', 'mainpage' ); + $this->assertSame( [ + 'error' => [ + 'code' => 'mainpage', + 'info' => $mainpagePlain, + ], + 'warnings' => [ + 'raw' => [ + 'warnings' => 'Blah "kbd" <X> 😞', + ApiResult::META_CONTENT => 'warnings', + ], + 'string' => [ + 'warnings' => $mainpagePlain, + ApiResult::META_CONTENT => 'warnings', + ], + ], + ApiResult::META_TYPE => 'assoc', + ], $result->getResultData(), 'Simple test' ); + + $result->reset(); + $formatter->addWarning( 'foo', 'mainpage' ); + $formatter->addWarning( 'foo', 'mainpage' ); + $formatter->addWarning( 'xxx+foo', [ 'parentheses', 'foobar' ] ); + $msg1 = wfMessage( 'mainpage' ); + $formatter->addWarning( 'message', $msg1 ); + $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', [ 'overriddenData' => true ] ); + $formatter->addWarning( 'messageWithData', $msg2 ); + $formatter->addError( 'errWithData', $msg2 ); + $formatter->addWarning( null, 'mainpage' ); + $this->assertSame( [ + 'error' => [ + 'code' => 'overriddenCode', + 'info' => $mainpagePlain, + 'overriddenData' => true, + ], + 'warnings' => [ + 'unknown' => [ + 'warnings' => $mainpagePlain, + ApiResult::META_CONTENT => 'warnings', + ], + 'messageWithData' => [ + 'warnings' => $mainpagePlain, + ApiResult::META_CONTENT => 'warnings', + ], + 'message' => [ + 'warnings' => $mainpagePlain, + ApiResult::META_CONTENT => 'warnings', + ], + 'foo' => [ + 'warnings' => "$mainpagePlain\n$parensPlain", + ApiResult::META_CONTENT => 'warnings', + ], + ], + ApiResult::META_TYPE => 'assoc', + ], $result->getResultData(), 'Complex test' ); + + $this->assertSame( + [ + 'code' => 'mainpage', + 'info' => 'Main Page', + ], + $formatter->formatMessage( $msg1 ) + ); + $this->assertSame( + [ + 'code' => 'overriddenCode', + 'info' => 'Main Page', + 'overriddenData' => true, + ], + $formatter->formatMessage( $msg2 ) + ); + + $result->reset(); + $status = Status::newGood(); + $status->warning( 'mainpage' ); + $status->warning( 'parentheses', 'foobar' ); + $status->warning( $msg1 ); + $status->warning( $msg2 ); + $status->error( 'mainpage' ); + $status->error( 'parentheses', 'foobar' ); + $formatter->addMessagesFromStatus( 'status', $status ); + $this->assertSame( [ + 'error' => [ + 'code' => 'mainpage', + 'info' => $mainpagePlain, + ], + 'warnings' => [ + 'status' => [ + 'warnings' => "$mainpagePlain\n$parensPlain", + ApiResult::META_CONTENT => 'warnings', + ], + ], + ApiResult::META_TYPE => 'assoc', + ], $result->getResultData(), 'Status test' ); + + $I = ApiResult::META_INDEXED_TAG_NAME; + $this->assertSame( + [ + [ + 'message' => 'mainpage', + 'params' => [ $I => 'param' ], + 'code' => 'mainpage', + 'type' => 'error', + ], + [ + 'message' => 'parentheses', + 'params' => [ 'foobar', $I => 'param' ], + 'code' => 'parentheses', + 'type' => 'error', + ], + $I => 'error', + ], + $formatter->arrayFromStatus( $status, 'error' ), + 'arrayFromStatus test for error' + ); + $this->assertSame( + [ + [ + 'message' => 'mainpage', + 'params' => [ $I => 'param' ], + 'code' => 'mainpage', + 'type' => 'warning', + ], + [ + 'message' => 'parentheses', + 'params' => [ 'foobar', $I => 'param' ], + 'code' => 'parentheses', + 'type' => 'warning', + ], + [ + 'message' => 'mainpage', + 'params' => [ $I => 'param' ], + 'code' => 'mainpage', + 'type' => 'warning', + ], + [ + 'message' => 'mainpage', + 'params' => [ $I => 'param' ], + 'code' => 'overriddenCode', + 'type' => 'warning', + ], + $I => 'warning', + ], + $formatter->arrayFromStatus( $status, 'warning' ), + 'arrayFromStatus test for warning' + ); + + $result->reset(); + $result->addValue( null, 'error', [ 'bogus' ] ); + $formatter->addError( 'err', 'mainpage' ); + $this->assertSame( [ + 'error' => [ + 'code' => 'mainpage', + 'info' => $mainpagePlain, + ], + ApiResult::META_TYPE => 'assoc', + ], $result->getResultData(), 'Overwrites bogus "error" value with real error' ); + } + + /** + * @dataProvider provideGetMessageFromException + * @covers ApiErrorFormatter::getMessageFromException + * @covers ApiErrorFormatter::formatException + * @param Exception $exception + * @param array $options + * @param array $expect + */ + public function testGetMessageFromException( $exception, $options, $expect ) { + if ( $exception instanceof UsageException ) { + $this->hideDeprecated( 'UsageException::getMessageArray' ); + } + + $result = new ApiResult( 8388608 ); + $formatter = new ApiErrorFormatter( $result, Language::factory( 'en' ), 'html', false ); + + $msg = $formatter->getMessageFromException( $exception, $options ); + $this->assertInstanceOf( Message::class, $msg ); + $this->assertInstanceOf( IApiMessage::class, $msg ); + $this->assertSame( $expect, [ + 'text' => $msg->parse(), + 'code' => $msg->getApiCode(), + 'data' => $msg->getApiData(), + ] ); + + $expectFormatted = $formatter->formatMessage( $msg ); + $formatted = $formatter->formatException( $exception, $options ); + $this->assertSame( $expectFormatted, $formatted ); + } + + /** + * @dataProvider provideGetMessageFromException + * @covers ApiErrorFormatter_BackCompat::formatException + * @param Exception $exception + * @param array $options + * @param array $expect + */ + public function testGetMessageFromException_BC( $exception, $options, $expect ) { + $result = new ApiResult( 8388608 ); + $formatter = new ApiErrorFormatter_BackCompat( $result ); + + $msg = $formatter->getMessageFromException( $exception, $options ); + $this->assertInstanceOf( Message::class, $msg ); + $this->assertInstanceOf( IApiMessage::class, $msg ); + $this->assertSame( $expect, [ + 'text' => $msg->parse(), + 'code' => $msg->getApiCode(), + 'data' => $msg->getApiData(), + ] ); + + $expectFormatted = $formatter->formatMessage( $msg ); + $formatted = $formatter->formatException( $exception, $options ); + $this->assertSame( $expectFormatted, $formatted ); + $formatted = $formatter->formatException( $exception, $options + [ 'bc' => true ] ); + $this->assertSame( $expectFormatted['info'], $formatted ); + } + + public static function provideGetMessageFromException() { + Wikimedia\suppressWarnings(); + $usageException = new UsageException( + '<b>Something broke!</b>', 'ue-code', 0, [ 'xxx' => 'yyy', 'baz' => 23 ] + ); + Wikimedia\restoreWarnings(); + + return [ + 'Normal exception' => [ + new RuntimeException( '<b>Something broke!</b>' ), + [], + [ + 'text' => '<b>Something broke!</b>', + 'code' => 'internal_api_error_RuntimeException', + 'data' => [], + ] + ], + 'Normal exception, wrapped' => [ + new RuntimeException( '<b>Something broke!</b>' ), + [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ], + [ + 'text' => '(<b>Something broke!</b>)', + 'code' => 'some-code', + 'data' => [ 'foo' => 'bar', 'baz' => 42 ], + ] + ], + 'UsageException' => [ + $usageException, + [], + [ + 'text' => '<b>Something broke!</b>', + 'code' => 'ue-code', + 'data' => [ 'xxx' => 'yyy', 'baz' => 23 ], + ] + ], + 'UsageException, wrapped' => [ + $usageException, + [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ], + [ + 'text' => '(<b>Something broke!</b>)', + 'code' => 'some-code', + 'data' => [ 'xxx' => 'yyy', 'baz' => 42, 'foo' => 'bar' ], + ] + ], + 'LocalizedException' => [ + new LocalizedException( [ 'returnto', '<b>FooBar</b>' ] ), + [], + [ + 'text' => 'Return to <b>FooBar</b>.', + 'code' => 'returnto', + 'data' => [], + ] + ], + 'LocalizedException, wrapped' => [ + new LocalizedException( [ 'returnto', '<b>FooBar</b>' ] ), + [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ], + [ + 'text' => 'Return to <b>FooBar</b>.', + 'code' => 'some-code', + 'data' => [ 'foo' => 'bar', 'baz' => 42 ], + ] + ], + ]; + } + +} |