diff --git a/src/Frontend.php b/src/Frontend.php index c5b1e7c..0a1981b 100644 --- a/src/Frontend.php +++ b/src/Frontend.php @@ -1,223 +1,223 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Legoktm\CoverMe; use Legoktm\CloverDiff\CloverXml; class Frontend { private const COVER_GOOD = 90; private const COVER_BAD = 50; /** * @var CoverLogIndex */ private $coverLogIndex; /** * @var PerformanceLogIndex */ private $perfLogIndex; public function __construct() { $this->coverLogIndex = new CoverLogIndex(); $this->perfLogIndex = new PerformanceLogIndex(); } private function select() { $selected = isset( $_GET['repo'] ) ? $_GET['repo'] : null; $list = $this->coverLogIndex->getExtensionList(); $html = << HTML; foreach ( $list as $ext ) { $isSelected = $selected === "Extension:$ext" ? ' selected' : ''; $html .= " Extension:$ext\n"; } return $html . "\n"; } private function typeSelect( $selected ) { $list = $this->perfLogIndex->getTypes(); $html = << HTML; foreach ( $list as $type ) { $isSelected = $selected === $type ? ' selected' : ''; $html .= " $type\n"; } return $html . "\n"; } private function progressBar( $percent ) { if ( $percent >= self::COVER_GOOD ) { $color = 'success'; } elseif ( $percent < self::COVER_BAD ) { $color = 'danger'; } else { $color = 'warning'; } $minWidth = $percent >= 10 ? '3em' : '2em'; return <<
$percent%
HTML; } private function body( $cover, $repo, $type, $hideCovered ) { $xenon = $this->perfLogIndex->getLatestLocalLog( $type ); $parser = new XenonLogs(); $parser->parse( $xenon ); $data = $parser->getData(); $clover = new CloverXml( $cover ); $methods = []; foreach ( $clover->getFiles( $clover::METHODS ) as $file => $methodInfo ) { $methods += $methodInfo; foreach ( $methodInfo as $method => $coverage ) { $methods[$method] = [ 'coverage' => round( $coverage ), 'file' => $file, ]; } } $html = ''; $iterCount = 0; if ( $repo === 'MediaWiki core' ) { $linkBase = 'https://doc.wikimedia.org/cover/mediawiki-core/'; } else { list( , $prefixless ) = explode( ':', $repo ); $linkBase = "https://doc.wikimedia.org/cover-extensions/$prefixless/"; } foreach ( $data as $name => $count ) { if ( isset( $methods[$name] ) ) { $coverage = $methods[$name]['coverage']; } else { continue; } if ( $hideCovered && $coverage >= self::COVER_GOOD ) { continue; } $file = $methods[$name]['file']; $progress = $this->progressBar( $coverage ); $html .= <<
$progress
$name ($count calls)
HTML; $iterCount++; if ( $iterCount > 100 ) { break; } } return $html; } private function profileTime() { return round( microtime( true ) - $GLOBALS['startTime'], 2 ); } public function execute() { $repo = isset( $_GET['repo'] ) ? $_GET['repo'] : 'MediaWiki core'; if ( strpos( $repo, 'Extension:' ) === 0 ) { $ploded = explode( ':', $repo ); if ( !in_array( $ploded[1], $this->coverLogIndex->getExtensionList() ) ) { $repo = 'MediaWiki core'; } else { $cover = $this->coverLogIndex->getExtension( $ploded[1] ); } } else { $repo = 'MediaWiki core'; } if ( $repo === 'MediaWiki core' ) { $cover = $this->coverLogIndex->getCore(); } $type = isset( $_GET['type'] ) ? $_GET['type'] : 'all'; if ( !in_array( $type, $this->perfLogIndex->getTypes() ) ) { $type = 'all'; } $typeSelect = $this->typeSelect( $type ); $eRepo = htmlspecialchars( $repo ); $eType = htmlspecialchars( $type ); $hideCovered = isset( $_GET['hide-covered' ] ) ? 'checked' : ''; $body = $this->body( $cover, $repo, $type, $hideCovered ); $phpVersion = PHP_VERSION; // phpcs:disable Generic.Files.LineLength.TooLong return << CoverMe

CoverMe helps you find the most impactful areas to increase test coverage. It sorts functions by how often they are called in Wikimedia production, and annotates them with how much test coverage each has. You can sort by repository and entry point (index.php, api.php, etc.).

{$eRepo}: {$eType}

{$body}

- Source code + Source code available under the terms of the AGPL v3, or any later version. Loaded in {$this->profileTime()} seconds using PHP {$phpVersion}.

HTML; } }