diff --git a/bin/pest b/bin/pest index c83b6446..439a6dec 100755 --- a/bin/pest +++ b/bin/pest @@ -2,6 +2,7 @@ getParameterOption('--test-directory', 'tests')); + $phpunitConfig = new ConfigLoader($rootPath); + + $testSuite = TestSuite::getInstance($rootPath, $argv->getParameterOption('--test-directory', $phpunitConfig->getTestsDirectory())); $isDecorated = $argv->getParameterOption('--colors', 'always') !== 'never'; $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated); diff --git a/src/ConfigLoader.php b/src/ConfigLoader.php new file mode 100644 index 00000000..49a005a1 --- /dev/null +++ b/src/ConfigLoader.php @@ -0,0 +1,110 @@ +loadConfiguration(); + } + + /** + * Get the tests directory or fallback to default path. + */ + public function getTestsDirectory(): string + { + if (is_null($this->config)) { + return self::DEFAULT_TESTS_PATH; + } + + $suiteDirectory = $this->config->xpath('/phpunit/testsuites/testsuite/directory'); + + // @phpstan-ignore-next-line + if (!$suiteDirectory || count($suiteDirectory) === 0) { + return self::DEFAULT_TESTS_PATH; + } + + $directory = (string) ($suiteDirectory[0] ?? ''); + + if ($directory === '') { + return self::DEFAULT_TESTS_PATH; + } + + // Return the whole directory if only a separator found (e.g. `./tests`) + if (substr_count($directory, DIRECTORY_SEPARATOR) === 1) { + return is_dir($directory) ? $directory : self::DEFAULT_TESTS_PATH; + } + + $basePath = Str::beforeLast($directory, DIRECTORY_SEPARATOR); + + return is_dir($basePath) ? $basePath : self::DEFAULT_TESTS_PATH; + } + + /** + * Load the configuration file. + */ + private function loadConfiguration(): void + { + $configPath = $this->getConfigurationFilePath(); + + if ($configPath === false) { + return; + } + + $oldReportingLevel = error_reporting(0); + $content = file_get_contents($configPath); + + if ($content !== false) { + try { + $this->config = new SimpleXMLElement($content); + } catch (Throwable) { // @phpstan-ignore-line + // @ignoreException + } + } + + // Restore the correct error reporting + error_reporting($oldReportingLevel); + } + + /** + * Get the configuration file path. + */ + private function getConfigurationFilePath(): string|false + { + $candidates = [ + $this->rootPath . '/phpunit.xml', + $this->rootPath . '/phpunit.dist.xml', + $this->rootPath . '/phpunit.xml.dist', + ]; + + foreach ($candidates as $candidate) { + if (is_file($candidate)) { + return realpath($candidate); + } + } + + return false; + } +} diff --git a/src/Support/Str.php b/src/Support/Str.php index a7217704..0314e11f 100644 --- a/src/Support/Str.php +++ b/src/Support/Str.php @@ -58,4 +58,22 @@ final class Str return (string) preg_replace('/[^A-Z_a-z0-9\\\\]/', '', $code); } + + /** + * Get the portion of a string before the last occurrence of a given value. + */ + public static function beforeLast(string $subject, string $search): string + { + if ($search === '') { + return $subject; + } + + $pos = mb_strrpos($subject, $search); + + if ($pos === false) { + return $subject; + } + + return substr($subject, 0, $pos); + } }