From: Brad Jorsch Date: Thu, 17 Dec 2015 19:57:12 +0000 (-0500) Subject: API: Add a unit test to check all modules' i18n X-Git-Tag: 1.31.0-rc.0~8589^2~1 X-Git-Url: http://git.cyclocoop.org/%24action?a=commitdiff_plain;h=0d3712dd6091b49ff79056388710ac502bed73a1;p=lhc%2Fweb%2Fwiklou.git API: Add a unit test to check all modules' i18n It's not perfect since module i18n can vary on configuration, but it should catch many cases of forgotten i18n. Change-Id: Ida7e5720fe304c5168fe752b1b5485fe4cb2cb45 Depends-On: I4a0a6c47afdd62e1c9d0b29f066d2a6d1791b52d Depends-On: I378d112a36c0981ac8d5366e3e1805ead71a85c8 Depends-On: If9e1ae5f1e360385e70bd68ec9847230bd274d9d Depends-On: If2694de72a62e46cfdc29401c4d2d3756897c998 --- diff --git a/tests/phpunit/structure/ApiDocumentationTest.php b/tests/phpunit/structure/ApiDocumentationTest.php new file mode 100644 index 0000000000..d2f96dc9cb --- /dev/null +++ b/tests/phpunit/structure/ApiDocumentationTest.php @@ -0,0 +1,177 @@ + false, + 'AllowCategorizedRecentChanges' => false, + ), + array( + 'MiserMode' => true, + 'AllowCategorizedRecentChanges' => true, + ), + ); + + /** + * Initialize/fetch the ApiMain instance for testing + * @return ApiMain + */ + private static function getMain() { + if ( !self::$main ) { + self::$main = new ApiMain( RequestContext::getMain() ); + self::$main->getContext()->setLanguage( 'en' ); + } + return self::$main; + } + + /** + * Test a message + * @param Message $msg + * @param string $what Which message is being checked + */ + private function checkMessage( $msg, $what ) { + $msg = ApiBase::makeMessage( $msg, self::getMain()->getContext() ); + $this->assertInstanceOf( 'Message', $msg, "$what message" ); + $this->assertTrue( $msg->exists(), "$what message {$msg->getKey()} exists" ); + } + + /** + * @dataProvider provideDocumentationExists + * @param string $path Module path + * @param array $globals Globals to set + */ + public function testDocumentationExists( $path, array $globals ) { + $main = self::getMain(); + + // Set configuration variables + $main->getContext()->setConfig( new MultiConfig( array( + new HashConfig( $globals ), + RequestContext::getMain()->getConfig(), + ) ) ); + foreach ( $globals as $k => $v ) { + $this->setMWGlobals( "wg$k", $v ); + } + + // Fetch module. + $module = TestingAccessWrapper::newFromObject( $main->getModuleFromPath( $path ) ); + + // Test messages for flags. + foreach ( $module->getHelpFlags() as $flag ) { + $this->checkMessage( "api-help-flag-$flag", "Flag $flag" ); + } + + // Module description messages. + $this->checkMessage( $module->getDescriptionMessage(), 'Module description' ); + + // Parameters. Lots of messages in here. + $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP ); + $tags = array(); + foreach ( $params as $name => $settings ) { + if ( !is_array( $settings ) ) { + $settings = array(); + } + + // Basic description message + if ( isset( $settings[ApiBase::PARAM_HELP_MSG] ) ) { + $msg = $settings[ApiBase::PARAM_HELP_MSG]; + } else { + $msg = "apihelp-{$path}-param-{$name}"; + } + $this->checkMessage( $msg, "Parameter $name description" ); + + // If param-per-value is in use, each value's message + if ( isset( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) { + $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE], + "Parameter $name PARAM_HELP_MSG_PER_VALUE is array" ); + $this->assertInternalType( 'array', $settings[ApiBase::PARAM_TYPE], + "Parameter $name PARAM_TYPE is array for msg-per-value mode" ); + $valueMsgs = $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE]; + foreach ( $settings[ApiBase::PARAM_TYPE] as $value ) { + if ( isset( $valueMsgs[$value] ) ) { + $msg = $valueMsgs[$value]; + } else { + $msg = "apihelp-{$path}-paramvalue-{$name}-{$value}"; + } + $this->checkMessage( $msg, "Parameter $name value $value" ); + } + } + + // Appended messages (e.g. "disabled in miser mode") + if ( isset( $settings[ApiBase::PARAM_HELP_MSG_APPEND] ) ) { + $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_APPEND], + "Parameter $name PARAM_HELP_MSG_APPEND is array" ); + foreach ( $settings[ApiBase::PARAM_HELP_MSG_APPEND] as $i => $msg ) { + $this->checkMessage( $msg, "Parameter $name HELP_MSG_APPEND #$i" ); + } + } + + // Info tags (e.g. "only usable in mode 1") are typically shared by + // several parameters, so accumulate them and test them later. + if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) { + foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) { + $tags[array_shift( $i )] = 1; + } + } + } + + // Info tags (e.g. "only usable in mode 1") accumulated above + foreach ( $tags as $tag => $dummy ) { + $this->checkMessage( "apihelp-{$path}-paraminfo-{$tag}", "HELP_MSG_INFO tag $tag" ); + } + + // Messages for examples. + foreach ( $module->getExamplesMessages() as $qs => $msg ) { + $this->checkMessage( $msg, "Example $qs" ); + } + } + + public static function provideDocumentationExists() { + $main = self::getMain(); + $paths = self::getSubModulePaths( $main->getModuleManager() ); + array_unshift( $paths, $main->getModulePath() ); + + $ret = array(); + foreach ( $paths as $path ) { + foreach ( self::$testGlobals as $globals ) { + $g = array(); + foreach ( $globals as $k => $v ) { + $g[] = "$k=" . var_export( $v, 1 ); + } + $k = "Module $path with " . join( ', ', $g ); + $ret[$k] = array( $path, $globals ); + } + } + return $ret; + } + + /** + * Return paths of all submodules in an ApiModuleManager, recursively + * @param ApiModuleManager $manager + * @return string[] + */ + protected static function getSubModulePaths( ApiModuleManager $manager ) { + $paths = array(); + foreach ( $manager->getNames() as $name ) { + $module = $manager->getModule( $name ); + $paths[] = $module->getModulePath(); + $subManager = $module->getModuleManager(); + if ( $subManager ) { + $paths = array_merge( $paths, self::getSubModulePaths( $subManager ) ); + } + } + return $paths; + } +}