From 451ae85b6d32bbacce1a8b5a48806807a4058203 Mon Sep 17 00:00:00 2001 From: Luca Tumedei Date: Thu, 17 Aug 2023 10:51:53 +0200 Subject: [PATCH] fix(src) phpstan pass --- src/Command/DevInfo.php | 1 - src/Command/GenerateWPUnit.php | 1 - src/Command/RunAll.php | 2 +- src/Command/ServiceExtensionsTrait.php | 56 ++++- src/Extension/DockerComposeController.php | 8 +- src/Extension/ServiceExtension.php | 3 + src/Lib/Generator/WPUnit.php | 49 +--- src/ManagedProcess/ChromeDriver.php | 4 +- ...erface.php => ManagedProcessInterface.php} | 4 +- src/ManagedProcess/ManagedProcessTrait.php | 42 ++-- src/ManagedProcess/PhpBuiltInServer.php | 6 +- src/Module/WPDb.php | 10 +- src/Process/Protocol/Control.php | 3 +- src/Process/Worker/Worker.php | 1 + src/Project/ContentProject.php | 2 +- src/Project/ProjectInterface.php | 2 +- src/Project/SiteProject.php | 2 +- src/Project/TestEnvironment.php | 2 +- src/Utils/Arr.php | 3 + src/Utils/Composer.php | 11 +- .../InstallationState/InstallationChecks.php | 9 +- src/version-4-aliases.php | 12 - ...ite_with_non_default_structure__0.snapshot | 4 +- ...ffold_for_multi_site_correctly__1.snapshot | 226 +++++++++--------- ...fold_for_single_site_correctly__1.snapshot | 226 +++++++++--------- .../ManagedProcess/ChromedriverTest.php | 12 +- .../lucatume/WPBrowser/Utils/ComposerTest.php | 16 ++ 27 files changed, 375 insertions(+), 342 deletions(-) rename src/ManagedProcess/{ManagedProcessinterface.php => ManagedProcessInterface.php} (87%) diff --git a/src/Command/DevInfo.php b/src/Command/DevInfo.php index e00ac31ef..f2450e40b 100644 --- a/src/Command/DevInfo.php +++ b/src/Command/DevInfo.php @@ -5,7 +5,6 @@ use Codeception\CustomCommandInterface; use Codeception\Exception\ConfigurationException; use Codeception\Exception\ExtensionException; -use lucatume\WPBrowser\Extension\ServiceExtensionInfo; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Command/GenerateWPUnit.php b/src/Command/GenerateWPUnit.php index b7a3f44d4..de3469d3e 100644 --- a/src/Command/GenerateWPUnit.php +++ b/src/Command/GenerateWPUnit.php @@ -6,7 +6,6 @@ use Codeception\Configuration; use Codeception\CustomCommandInterface; use lucatume\WPBrowser\Exceptions\InvalidArgumentException; -use lucatume\WPBrowser\Lib\Generator\WPUnit; use lucatume\WPBrowser\Lib\Generator\WPUnit as WPUnitGenerator; use lucatume\WPBrowser\Module\WPLoader; use lucatume\WPBrowser\TestCase\WPTestCase; diff --git a/src/Command/RunAll.php b/src/Command/RunAll.php index 87d76d007..36211976c 100644 --- a/src/Command/RunAll.php +++ b/src/Command/RunAll.php @@ -38,7 +38,7 @@ public function execute(InputInterface $input, OutputInterface $output): int foreach ($this->getSuites() as $suite) { try { - $cwd = getcwd(); + $cwd = getcwd() ?: null; $process = new Process([$codeceptBin, 'codeception:run', $suite, ...$runOptions], $cwd); $process->setTimeout(null); $process->start(); diff --git a/src/Command/ServiceExtensionsTrait.php b/src/Command/ServiceExtensionsTrait.php index 47283ddc8..86f7c0798 100644 --- a/src/Command/ServiceExtensionsTrait.php +++ b/src/Command/ServiceExtensionsTrait.php @@ -4,6 +4,7 @@ use Codeception\Configuration; use Codeception\Exception\ConfigurationException; +use lucatume\WPBrowser\Exceptions\InvalidArgumentException; use lucatume\WPBrowser\Extension\ServiceExtension; trait ServiceExtensionsTrait @@ -16,6 +17,10 @@ trait ServiceExtensionsTrait */ protected function buildServiceExtension(string $serviceExtension): ServiceExtension { + if (!is_a($serviceExtension, ServiceExtension::class, true)) { + $message = "The class {$serviceExtension} does not implement the " . ServiceExtension::class . " interface."; + throw new InvalidArgumentException($message); + } $config = $this->getServiceExtensionConfig($serviceExtension); return new $serviceExtension($config, []); } @@ -27,18 +32,61 @@ protected function buildServiceExtension(string $serviceExtension): ServiceExten protected function getServiceExtensions(): array { $config = Configuration::config(); - $enabledExtensions = $config['extensions']['enabled'] ?? []; + + if (!(isset($config['extensions']) && is_array($config['extensions']))) { + return []; + } + + $extensions = $config['extensions']; + + if (!(isset($extensions['enabled']) && is_array($extensions['enabled']))) { + return []; + } + + $enabledExtensions = $config['extensions']['enabled']; + + if (!is_array($enabledExtensions)) { + return []; + } + return array_filter( $enabledExtensions, - static fn(string $extension) => is_a($extension, ServiceExtension::class, true), + static fn($extension) => is_string($extension) && is_a($extension, ServiceExtension::class, true), ); } /** + * @return array * @throws ConfigurationException */ - protected function getServiceExtensionConfig(string $serviceExtension): mixed + protected function getServiceExtensionConfig(string $serviceExtension): array { - return Configuration::config()['extensions']['config'][$serviceExtension] ?? []; + $codeceptionConfig = Configuration::config(); + + if (!(isset($codeceptionConfig['extensions']) && is_array($codeceptionConfig['extensions']))) { + return []; + } + + if (!( + isset($codeceptionConfig['extensions']['config']) + && is_array($codeceptionConfig['extensions']['config'])) + ) { + return []; + } + + if (!( + isset($codeceptionConfig['extensions']['config'][$serviceExtension]) + && is_array($codeceptionConfig['extensions']['config'][$serviceExtension])) + ) { + return []; + } + + $extensionConfig = $codeceptionConfig['extensions']['config'][$serviceExtension]; + + if (!is_array($extensionConfig)) { + return []; + } + + return $extensionConfig; } } diff --git a/src/Extension/DockerComposeController.php b/src/Extension/DockerComposeController.php index baf35aa6e..ff78dff55 100644 --- a/src/Extension/DockerComposeController.php +++ b/src/Extension/DockerComposeController.php @@ -88,7 +88,7 @@ public function stop(OutputInterface $output): void } /** - * @param array $config + * @param array $config * * @throws ExtensionException */ @@ -109,7 +109,7 @@ protected function getComposeFile(array $config): string } /** - * @param array $config + * @param array $config * * @throws ExtensionException */ @@ -137,7 +137,7 @@ public function getPrettyName(): string /** * @return array{ * status: string, - * config: string|mixed[] + * config: mixed * } * @throws ExtensionException */ @@ -170,7 +170,7 @@ public static function getRunningFile(): string } /** - * @param array $config + * @param array $config * * @return string[] * @throws ExtensionException diff --git a/src/Extension/ServiceExtension.php b/src/Extension/ServiceExtension.php index 3b4c9cd8c..77249da46 100644 --- a/src/Extension/ServiceExtension.php +++ b/src/Extension/ServiceExtension.php @@ -55,5 +55,8 @@ abstract public function stop(OutputInterface $output): void; abstract public function getPrettyName(): string; + /** + * @return array + */ abstract public function getInfo(): array; } diff --git a/src/Lib/Generator/WPUnit.php b/src/Lib/Generator/WPUnit.php index 9001d73f6..8d5f2afd5 100644 --- a/src/Lib/Generator/WPUnit.php +++ b/src/Lib/Generator/WPUnit.php @@ -12,7 +12,7 @@ use Codeception\Util\Shared\Namespaces; use Codeception\Util\Template; use Exception; -use lucatume\WPBrowser\Compat\Compatibility; +use lucatume\WPBrowser\Exceptions\InvalidArgumentException; /** * Class WPUnit @@ -27,9 +27,8 @@ class WPUnit /** * @var array{namespace: string, actor: string} */ - protected array $settings; - - protected string $name; + private array $settings; + private string $name; /** * @var string @@ -76,8 +75,6 @@ public function test_factory() :void */ public function __construct(array $settings, string $name, protected string $baseClass) { - $this->ensureSettings(); - $this->ensureSettingsAreAllStrings(); $this->settings = $settings; $this->name = $this->removeSuffix($name, 'Test'); } @@ -133,44 +130,4 @@ protected function getTester(): string return ltrim($testerFrag); } - - - /** - * Checks the template settings. - * - * @return bool Whether the template settings are correct or not. - */ - protected function ensureSettings(): bool - { - if (empty(static::$requiredSettings)) { - return true; - } - - foreach (static::$requiredSettings as $requiredSetting) { - if (!isset($this->settings[$requiredSetting])) { - throw new BadMethodCallException('Required template setting [{' . $requiredSetting . '}] is missing.'); - } - } - - return true; - } - - /** - * Checks all settings are strings. - */ - protected function ensureSettingsAreAllStrings(): bool - { - if (empty(static::$requiredSettings)) { - return true; - } - - foreach (static::$requiredSettings as $requiredSetting) { - if (!is_string($this->settings[$requiredSetting])) { - $message = 'Required template setting [{' . $requiredSetting . '}] is not a string.'; - throw new BadMethodCallException($message); - } - } - - return true; - } } diff --git a/src/ManagedProcess/ChromeDriver.php b/src/ManagedProcess/ChromeDriver.php index a463d248e..ceb4a1c59 100644 --- a/src/ManagedProcess/ChromeDriver.php +++ b/src/ManagedProcess/ChromeDriver.php @@ -31,7 +31,7 @@ public function __construct( if (!(file_exists($binary) && is_executable($binary))) { throw new RuntimeException( "ChromeDriver binary $binary does not exist.", - ManagedProcessinterface::ERR_BINARY_NOT_FOUND + ManagedProcessInterface::ERR_BINARY_NOT_FOUND ); } @@ -72,7 +72,7 @@ private function confirmStart(Process $process): void throw new RuntimeException( 'Could not start ChromeDriver: ' . $process->getOutput(), - ManagedProcessinterface::ERR_START + ManagedProcessInterface::ERR_START ); } } diff --git a/src/ManagedProcess/ManagedProcessinterface.php b/src/ManagedProcess/ManagedProcessInterface.php similarity index 87% rename from src/ManagedProcess/ManagedProcessinterface.php rename to src/ManagedProcess/ManagedProcessInterface.php index f0b18016c..d4e63070b 100644 --- a/src/ManagedProcess/ManagedProcessinterface.php +++ b/src/ManagedProcess/ManagedProcessInterface.php @@ -2,7 +2,7 @@ namespace lucatume\WPBrowser\ManagedProcess; -interface ManagedProcessinterface +interface ManagedProcessInterface { public const ERR_START = 1; public const ERR_NO_STARTED = 2; @@ -19,7 +19,7 @@ public function getPort(): int; public function stop(): ?int; - public function getPid(): int; + public function getPid(): ?int; public static function getPidFile(): string; } diff --git a/src/ManagedProcess/ManagedProcessTrait.php b/src/ManagedProcess/ManagedProcessTrait.php index d4c0aed4a..bdf68131e 100644 --- a/src/ManagedProcess/ManagedProcessTrait.php +++ b/src/ManagedProcess/ManagedProcessTrait.php @@ -5,8 +5,10 @@ use lucatume\WPBrowser\Exceptions\RuntimeException; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; -use Throwable; +/** + * @property string $prettyName + */ trait ManagedProcessTrait { private ?Process $process = null; @@ -14,12 +16,13 @@ trait ManagedProcessTrait private function writePidFile(): void { - $pid = $this->process->getPid(); + $process = $this->checkIsRunning(); + $pid = $process->getPid(); if (!is_numeric($pid) || (int)$pid < 1) { $error = new RuntimeException( - "Could not start $this->prettyName: " . $this->process->getErrorOutput(), - ManagedProcessinterface::ERR_PID + "Could not start $this->prettyName: " . $process->getErrorOutput(), + ManagedProcessInterface::ERR_PID ); $this->stop(); throw $error; @@ -29,20 +32,20 @@ private function writePidFile(): void if (file_put_contents($pidFile, $pid, LOCK_EX) === false) { throw new RuntimeException( "Could not write PID file '$pidFile'.", - ManagedProcessinterface::ERR_PID_FILE + ManagedProcessInterface::ERR_PID_FILE ); } } public function stop(): ?int { - $this->checkStarted(); - $exitCode = $this->process->stop(); + $process = $this->checkStarted(); + $exitCode = $process->stop(); if (is_file(static::getPidFile()) && !unlink(static::getPidFile())) { throw new RuntimeException( "Could not remove PID file '{static::getPidFile(}'.", - ManagedProcessinterface::ERR_PID_FILE_DELETE + ManagedProcessInterface::ERR_PID_FILE_DELETE ); } @@ -54,14 +57,16 @@ public static function getPidFile(): string return codecept_output_dir(self::PID_FILE_NAME); } - private function checkStarted(): void + private function checkStarted(): Process { if ($this->process === null) { throw new RuntimeException( "{$this->prettyName} not started.", - ManagedProcessinterface::ERR_NO_STARTED + ManagedProcessInterface::ERR_NO_STARTED ); } + + return $this->process; } public function getPort(): int @@ -87,25 +92,26 @@ public function start(): void } throw new RuntimeException( "Could not start $this->prettyName: " . $t->getMessage(), - ManagedProcessinterface::ERR_START, + ManagedProcessInterface::ERR_START, $t ); } } - public function getPid(): int + public function getPid(): ?int { - $this->checkIsRunning(); - return $this->pid; + return $this->checkIsRunning()->getPid(); } - private function checkIsRunning(): void + private function checkIsRunning(): Process { - if (!($this->process instanceof Process) && $this->process->isRunning()) { + if (!($this->process instanceof Process && $this->process->isRunning())) { throw new RuntimeException( - "{$this->prettyName} is not running.", - ManagedProcessinterface::ERR_NOT_RUNNING + "$this->prettyName is not running.", + ManagedProcessInterface::ERR_NOT_RUNNING ); } + + return $this->process; } } diff --git a/src/ManagedProcess/PhpBuiltInServer.php b/src/ManagedProcess/PhpBuiltInServer.php index b59775e00..57b70d5a2 100644 --- a/src/ManagedProcess/PhpBuiltInServer.php +++ b/src/ManagedProcess/PhpBuiltInServer.php @@ -7,7 +7,7 @@ use lucatume\WPBrowser\Utils\Filesystem; use Symfony\Component\Process\Process; -class PhpBuiltInServer implements ManagedProcessinterface +class PhpBuiltInServer implements ManagedProcessInterface { use ManagedProcessTrait; @@ -15,7 +15,7 @@ class PhpBuiltInServer implements ManagedProcessinterface public const ERR_PORT_ALREADY_IN_USE = 2; public const ERR_ENV = 3; public const PID_FILE_NAME = 'php-built-in-server.pid'; - private string $prettyName = 'PHP built-in server'; + private string $prettyName = 'PHP Built-in Server'; /** * @param array $env @@ -66,7 +66,7 @@ public function doStart(): void if ($confirmPort === null || !(is_numeric($confirmPort) && (int)$confirmPort > 0)) { $error = new RuntimeException( 'Could not start PHP Built-in server: ' . $process->getErrorOutput(), - ManagedProcessinterface::ERR_START + ManagedProcessInterface::ERR_START ); $this->stop(); throw $error; diff --git a/src/Module/WPDb.php b/src/Module/WPDb.php index 71de0cab8..7da3042f0 100644 --- a/src/Module/WPDb.php +++ b/src/Module/WPDb.php @@ -19,7 +19,6 @@ use lucatume\WPBrowser\Generators\Links; use lucatume\WPBrowser\Generators\Post; use lucatume\WPBrowser\Generators\Tables; -use lucatume\WPBrowser\Generators\TablesGeneratorFactory; use lucatume\WPBrowser\Generators\User; use lucatume\WPBrowser\Module\Support\DbDump; use lucatume\WPBrowser\Utils\Db as DbUtils; @@ -286,9 +285,9 @@ public function grabSiteMetaFromDatabase(int $blogId, string $key, bool $single) * @param int $postId The post ID. * @param string $field The post field to get the value for. * - * @return string The value of the post field. + * @return mixed The value of the post field. */ - public function grabPostFieldFromDatabase(int $postId, string $field): string + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { $tableName = $this->grabPrefixedTableNameFor('posts'); return $this->grabFromDatabase($tableName, $field, ['ID' => $postId]); @@ -4496,13 +4495,14 @@ public function _beforeSuite($settings = []): void */ protected function createDatabasesIfNotExist(array $config): void { - if (str_starts_with($config['dsn'], 'sqlite:')) { + $configDsn = $config['dsn']; + if (is_string($configDsn) && str_starts_with($configDsn, 'sqlite:')) { return; } $createIfNotExist = []; if (!empty($config['createIfNotExists'])) { - $createIfNotExist[$config['dsn']] = [$config['user'], $config['password']]; + $createIfNotExist[$configDsn] = [$config['user'], $config['password']]; } if (!empty($config['databases']) && is_array($config['databases'])) { diff --git a/src/Process/Protocol/Control.php b/src/Process/Protocol/Control.php index 778630d60..d1afd76f3 100644 --- a/src/Process/Protocol/Control.php +++ b/src/Process/Protocol/Control.php @@ -85,7 +85,8 @@ public static function getDefault(): array 'codeceptionRootDir' => codecept_root_dir(), 'codeceptionConfig' => Configuration::isEmpty() ? [] : Configuration::config(), 'composerAutoloadPath' => $GLOBALS['_composer_autoload_path'] ?? null, - 'composerBinDir' => $GLOBALS['_composer_bin_dir'] ?? null + 'composerBinDir' => $GLOBALS['_composer_bin_dir'] ?? null, + 'env' => $_ENV, ]; } diff --git a/src/Process/Worker/Worker.php b/src/Process/Worker/Worker.php index e8530ce84..442c5d65f 100644 --- a/src/Process/Worker/Worker.php +++ b/src/Process/Worker/Worker.php @@ -60,6 +60,7 @@ public function __construct( 'codeceptionConfig' => $control['codeceptionConfig'] ?? $defaultControl['codeceptionConfig'], 'composerAutoloadPath' => $control['composerAutoloadPath'] ?? $defaultControl['composerAutoloadPath'], 'composerBinDir' => $control['composerBinDir'] ?? $defaultControl['composerBinDir'], + 'env' => $control['env'] ?? $defaultControl['env'], ]; } diff --git a/src/Project/ContentProject.php b/src/Project/ContentProject.php index c1bde7169..f5c80ade3 100644 --- a/src/Project/ContentProject.php +++ b/src/Project/ContentProject.php @@ -67,7 +67,7 @@ private function getAfterSuccessClosure(bool $activated): Closure /** * @throws Throwable */ - public function setup() + public function setup(): void { $this->say('You can use a portable configuration based on PHP built-in server, Chromedriver ' . 'and SQLite.'); diff --git a/src/Project/ProjectInterface.php b/src/Project/ProjectInterface.php index c64808888..ddf909e16 100644 --- a/src/Project/ProjectInterface.php +++ b/src/Project/ProjectInterface.php @@ -8,5 +8,5 @@ public function getType(): string; public function getTestEnv(): ?TestEnvironment; - public function setup(); + public function setup() : void; } diff --git a/src/Project/SiteProject.php b/src/Project/SiteProject.php index 963bbcd06..f59205be1 100644 --- a/src/Project/SiteProject.php +++ b/src/Project/SiteProject.php @@ -68,7 +68,7 @@ public function getType(): string /** * @throws Throwable */ - public function setup() + public function setup(): void { $this->say('You can use a portable configuration based on PHP built-in server, Chromedriver ' . 'and SQLite.'); diff --git a/src/Project/TestEnvironment.php b/src/Project/TestEnvironment.php index ecaf4414e..d20b57dd4 100644 --- a/src/Project/TestEnvironment.php +++ b/src/Project/TestEnvironment.php @@ -17,7 +17,7 @@ class TestEnvironment public string $chromeDriverHost = 'localhost'; public int $chromeDriverPort = 4444; /** - * @var array> + * @var array> */ public array $extensionsEnabled = []; public ?string $dumpFile = null; diff --git a/src/Utils/Arr.php b/src/Utils/Arr.php index cbbcad2bf..2a7e66a05 100644 --- a/src/Utils/Arr.php +++ b/src/Utils/Arr.php @@ -74,6 +74,9 @@ public static function containsOnly(array $array, string|callable $type): bool return true; } + /** + * @param array $array + */ public static function isAssociative(array $array): bool { return array_filter(array_keys($array), 'is_string') === array_keys($array); diff --git a/src/Utils/Composer.php b/src/Utils/Composer.php index a87e69f86..f0847c0f6 100644 --- a/src/Utils/Composer.php +++ b/src/Utils/Composer.php @@ -15,9 +15,10 @@ class Composer public const ERR_FILE_UNREADABLE = 2; public const ERR_FILE_WRITE_FAILED = 3; public const ERR_UPDATE_FAILED = 4; + const ERR_DECODING_FAILED = 5; private string $composerJsonFile; /** - * @var StdClass + * @var StdClass */ private stdClass $decoded; @@ -58,7 +59,13 @@ public function __construct(?string $composerJsonFile = null) throw new RuntimeException('Composer file not readable.', self::ERR_FILE_UNREADABLE); } - $this->decoded = json_decode($json, false, 512, JSON_THROW_ON_ERROR); + $decoded = json_decode($json, false, 512, JSON_THROW_ON_ERROR); + + if (!$decoded instanceof StdClass) { + throw new RuntimeException('Composer file decoding failed.', self::ERR_DECODING_FAILED); + } + + $this->decoded = $decoded; } /** diff --git a/src/WordPress/InstallationState/InstallationChecks.php b/src/WordPress/InstallationState/InstallationChecks.php index ee92eeb0d..026ebd216 100644 --- a/src/WordPress/InstallationState/InstallationChecks.php +++ b/src/WordPress/InstallationState/InstallationChecks.php @@ -12,6 +12,9 @@ use PDOException; use Throwable; +/** + * @property DatabaseInterface $db + */ trait InstallationChecks { /** @@ -22,9 +25,11 @@ trait InstallationChecks */ protected function isInstalled(bool $multisite, DatabaseInterface $db = null): bool { - $db = $db ?? $this->db; + if ($db === null && property_exists($this,'db') && $this->db instanceof DatabaseInterface) { + $db = $this->db; + } - if (!$db instanceof DatabaseInterface) { + if ($db === null) { return false; } diff --git a/src/version-4-aliases.php b/src/version-4-aliases.php index 3876d9800..7aa8004ba 100644 --- a/src/version-4-aliases.php +++ b/src/version-4-aliases.php @@ -2,13 +2,7 @@ namespace lucatume\WPBrowser; -use lucatume\WPBrowser\Command\GenerateWPAjax; -use lucatume\WPBrowser\Command\GenerateWPCanonical; -use lucatume\WPBrowser\Command\GenerateWPRestApi; -use lucatume\WPBrowser\Command\GenerateWPRestController; -use lucatume\WPBrowser\Command\GenerateWPRestPostTypeController; use lucatume\WPBrowser\Command\GenerateWPUnit; -use lucatume\WPBrowser\Command\GenerateWPXMLRPC; use lucatume\WPBrowser\Module\WPBrowser; use lucatume\WPBrowser\Module\WPBrowserMethods; use lucatume\WPBrowser\Module\WPCLI; @@ -45,13 +39,7 @@ 'Codeception\\Module\\WPLoader' => WPLoader::class, 'Codeception\\Module\\WPQueries' => WPQueries::class, 'Codeception\\Module\\WPWebDriver' => WPWebDriver::class, - 'Codeception\\Command\\GenerateWPAjax' => GenerateWPAjax::class, - 'Codeception\\Command\\GenerateWPCanonical' => GenerateWPCanonical::class, - 'Codeception\\Command\\GenerateWPRestApi' => GenerateWPRestApi::class, - 'Codeception\\Command\\GenerateWPRestController' => GenerateWPRestController::class, - 'Codeception\\Command\\GenerateWPRestPostTypeController' => GenerateWPRestPostTypeController::class, 'Codeception\\Command\\GenerateWPUnit' => GenerateWPUnit::class, - 'Codeception\\Command\\GenerateWPXMLRPC' => GenerateWPXMLRPC::class, 'Codeception\\Template\\Wpbrowser' => WpbrowserInitTemplate::class, 'Codeception\\TestCase\\WPTestCase' => WPTestCase::class, 'Codeception\\TestCase\\WPAjaxTestCase' => WPAjaxTestCase::class, diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot index b091c5e9c..0e464cbff 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_correctly_on_site_with_non_default_structure__0.snapshot @@ -3826,10 +3826,10 @@ trait EndToEndTesterActions * @param int $postId The post ID. * @param string $field The post field to get the value for. * - * @return string The value of the post field. + * @return mixed The value of the post field. * @see \lucatume\WPBrowser\Module\WPDb::grabPostFieldFromDatabase() */ - public function grabPostFieldFromDatabase(int $postId, string $field): string { + public function grabPostFieldFromDatabase(int $postId, string $field): mixed { return $this->getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__1.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__1.snapshot index cda1dc8d4..314e80875 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__1.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_multi_site_correctly__1.snapshot @@ -43,6 +43,75 @@ modules: <<< /EndToEnd.suite.yml <<< +>>> /EndToEnd/ActivationCest.php >>> +amOnPage('/'); + $I->seeElement('body'); + } + + public function test_can_login_as_admin(EndToEndTester $I): void + { + $I->loginAsAdmin(); + $I->amOnAdminPage('/'); + $I->seeElement('body.wp-admin'); + } +} + +<<< /EndToEnd/ActivationCest.php <<< + +>>> /EndToEnd/_bootstrap.php >>> +` command + * to run WP-CLI commands on the WordPress site and database used by the EndToEnd suite. + * E.g.: + * `vendor/bin/codecept wp:cli EndToEnd db import tests/Support/Data/dump.sql` to load dump file. + * `vendor/bin/codecept wp:cli EndToEnd plugin activate woocommerce` to activate the WooCommerce plugin. + * `vendor/bin/codecept wp:cli EndToEnd user create alice alice@example.com --role=administrator` to create a new user. + * `vendor/bin/codecept wp:cli EndToEnd db export tests/Support/Data/dump.sql` to update the dump file. + */ +<<< /EndToEnd/_bootstrap.php <<< + +>>> /Integration.suite.yml >>> +# Integration suite configuration +# +# Run integration and "WordPress unit" tests. + +actor: IntegrationTester +bootstrap: _bootstrap.php +modules: + enabled: + - lucatume\WPBrowser\Module\WPLoader + config: + lucatume\WPBrowser\Module\WPLoader: + wpRootFolder: "%WORDPRESS_ROOT_DIR%" + dbUrl: '%WORDPRESS_DB_URL%' + wpDebug: true + tablePrefix: '%TEST_TABLE_PREFIX%' + domain: '%WORDPRESS_DOMAIN%' + adminEmail: 'admin@%WORDPRESS_DOMAIN%' + title: 'Integration Tests' + plugins: [] + theme: '' +<<< /Integration.suite.yml <<< + >>> /Integration/SampleTest.php >>> >> /Integration.suite.yml >>> -# Integration suite configuration -# -# Run integration and "WordPress unit" tests. +>>> /.env >>> +# The path to the WordPress root directory, the one containing the wp-load.php file. +# This can be a relative path from the directory that contains the codeception.yml file, +# or an absolute path. +WORDPRESS_ROOT_DIR=. -actor: IntegrationTester -bootstrap: _bootstrap.php -modules: - enabled: - - lucatume\WPBrowser\Module\WPLoader - config: - lucatume\WPBrowser\Module\WPLoader: - wpRootFolder: "%WORDPRESS_ROOT_DIR%" - dbUrl: '%WORDPRESS_DB_URL%' - wpDebug: true - tablePrefix: '%TEST_TABLE_PREFIX%' - domain: '%WORDPRESS_DOMAIN%' - adminEmail: 'admin@%WORDPRESS_DOMAIN%' - title: 'Integration Tests' - plugins: [] - theme: '' -<<< /Integration.suite.yml <<< +# Tests will require a MySQL database to run. +# The database will be created if it does not exist. +# Do not use a database that contains important data! +WORDPRESS_DB_URL=sqlite://%codecept_root_dir%/tests/Support/Data/db.sqlite ->>> /Support/IntegrationTester.php >>> +# The Integration suite will use this table prefix for the WordPress tables. +TEST_TABLE_PREFIX=test_ + +# This table prefix used by the WordPress site in end-to-end tests. +WORDPRESS_TABLE_PREFIX=wp_ + +# The URL and domain of the WordPress site used in end-to-end tests. +WORDPRESS_URL=http://localhost:33083 +WORDPRESS_DOMAIN=localhost:33083 + +# The username and password of the administrator user of the WordPress site used in end-to-end tests. +WORDPRESS_ADMIN_USER=admin +WORDPRESS_ADMIN_PASSWORD=password + +# The host and port of the ChromeDriver server that will be used in end-to-end tests. +CHROMEDRIVER_HOST=localhost +CHROMEDRIVER_PORT=40515 + +# The port on which the PHP built-in server will serve the WordPress installation. +BUILTIN_SERVER_PORT=33083 + +<<< /.env <<< + +>>> /Support/EndToEndTester.php >>> >> /Support/EndToEndTester.php >>> +>>> /Support/IntegrationTester.php >>> >> /Support/Data/.gitkeep >>> - -<<< /Support/Data/.gitkeep <<< +<<< /Support/IntegrationTester.php <<< >>> /Support/_generated/EndToEndTesterActions.php >>> getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -10064,85 +10140,9 @@ trait IntegrationTesterActions <<< /Support/_generated/.gitignore <<< ->>> /EndToEnd/_bootstrap.php >>> -` command - * to run WP-CLI commands on the WordPress site and database used by the EndToEnd suite. - * E.g.: - * `vendor/bin/codecept wp:cli EndToEnd db import tests/Support/Data/dump.sql` to load dump file. - * `vendor/bin/codecept wp:cli EndToEnd plugin activate woocommerce` to activate the WooCommerce plugin. - * `vendor/bin/codecept wp:cli EndToEnd user create alice alice@example.com --role=administrator` to create a new user. - * `vendor/bin/codecept wp:cli EndToEnd db export tests/Support/Data/dump.sql` to update the dump file. - */ -<<< /EndToEnd/_bootstrap.php <<< - ->>> /EndToEnd/ActivationCest.php >>> -amOnPage('/'); - $I->seeElement('body'); - } - - public function test_can_login_as_admin(EndToEndTester $I): void - { - $I->loginAsAdmin(); - $I->amOnAdminPage('/'); - $I->seeElement('body.wp-admin'); - } -} - -<<< /EndToEnd/ActivationCest.php <<< - ->>> /.env >>> -# The path to the WordPress root directory, the one containing the wp-load.php file. -# This can be a relative path from the directory that contains the codeception.yml file, -# or an absolute path. -WORDPRESS_ROOT_DIR=. - -# Tests will require a MySQL database to run. -# The database will be created if it does not exist. -# Do not use a database that contains important data! -WORDPRESS_DB_URL=sqlite://%codecept_root_dir%/tests/Support/Data/db.sqlite - -# The Integration suite will use this table prefix for the WordPress tables. -TEST_TABLE_PREFIX=test_ - -# This table prefix used by the WordPress site in end-to-end tests. -WORDPRESS_TABLE_PREFIX=wp_ - -# The URL and domain of the WordPress site used in end-to-end tests. -WORDPRESS_URL=http://localhost:53871 -WORDPRESS_DOMAIN=localhost:53871 - -# The username and password of the administrator user of the WordPress site used in end-to-end tests. -WORDPRESS_ADMIN_USER=admin -WORDPRESS_ADMIN_PASSWORD=password - -# The host and port of the ChromeDriver server that will be used in end-to-end tests. -CHROMEDRIVER_HOST=localhost -CHROMEDRIVER_PORT=53880 - -# The port on which the PHP built-in server will serve the WordPress installation. -BUILTIN_SERVER_PORT=53871 +>>> /Support/Data/.gitkeep >>> -<<< /.env <<< +<<< /Support/Data/.gitkeep <<< >>> /_output/.gitignore >>> * diff --git a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__1.snapshot b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__1.snapshot index d4fc1eda3..b9745db4d 100644 --- a/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__1.snapshot +++ b/tests/unit/Codeception/Template/__snapshots__/WpbrowserTest__should_scaffold_for_single_site_correctly__1.snapshot @@ -43,6 +43,75 @@ modules: <<< /EndToEnd.suite.yml <<< +>>> /EndToEnd/ActivationCest.php >>> +amOnPage('/'); + $I->seeElement('body'); + } + + public function test_can_login_as_admin(EndToEndTester $I): void + { + $I->loginAsAdmin(); + $I->amOnAdminPage('/'); + $I->seeElement('body.wp-admin'); + } +} + +<<< /EndToEnd/ActivationCest.php <<< + +>>> /EndToEnd/_bootstrap.php >>> +` command + * to run WP-CLI commands on the WordPress site and database used by the EndToEnd suite. + * E.g.: + * `vendor/bin/codecept wp:cli EndToEnd db import tests/Support/Data/dump.sql` to load dump file. + * `vendor/bin/codecept wp:cli EndToEnd plugin activate woocommerce` to activate the WooCommerce plugin. + * `vendor/bin/codecept wp:cli EndToEnd user create alice alice@example.com --role=administrator` to create a new user. + * `vendor/bin/codecept wp:cli EndToEnd db export tests/Support/Data/dump.sql` to update the dump file. + */ +<<< /EndToEnd/_bootstrap.php <<< + +>>> /Integration.suite.yml >>> +# Integration suite configuration +# +# Run integration and "WordPress unit" tests. + +actor: IntegrationTester +bootstrap: _bootstrap.php +modules: + enabled: + - lucatume\WPBrowser\Module\WPLoader + config: + lucatume\WPBrowser\Module\WPLoader: + wpRootFolder: "%WORDPRESS_ROOT_DIR%" + dbUrl: '%WORDPRESS_DB_URL%' + wpDebug: true + tablePrefix: '%TEST_TABLE_PREFIX%' + domain: '%WORDPRESS_DOMAIN%' + adminEmail: 'admin@%WORDPRESS_DOMAIN%' + title: 'Integration Tests' + plugins: [] + theme: '' +<<< /Integration.suite.yml <<< + >>> /Integration/SampleTest.php >>> >> /Integration.suite.yml >>> -# Integration suite configuration -# -# Run integration and "WordPress unit" tests. +>>> /.env >>> +# The path to the WordPress root directory, the one containing the wp-load.php file. +# This can be a relative path from the directory that contains the codeception.yml file, +# or an absolute path. +WORDPRESS_ROOT_DIR=. -actor: IntegrationTester -bootstrap: _bootstrap.php -modules: - enabled: - - lucatume\WPBrowser\Module\WPLoader - config: - lucatume\WPBrowser\Module\WPLoader: - wpRootFolder: "%WORDPRESS_ROOT_DIR%" - dbUrl: '%WORDPRESS_DB_URL%' - wpDebug: true - tablePrefix: '%TEST_TABLE_PREFIX%' - domain: '%WORDPRESS_DOMAIN%' - adminEmail: 'admin@%WORDPRESS_DOMAIN%' - title: 'Integration Tests' - plugins: [] - theme: '' -<<< /Integration.suite.yml <<< +# Tests will require a MySQL database to run. +# The database will be created if it does not exist. +# Do not use a database that contains important data! +WORDPRESS_DB_URL=sqlite://%codecept_root_dir%/tests/Support/Data/db.sqlite ->>> /Support/IntegrationTester.php >>> +# The Integration suite will use this table prefix for the WordPress tables. +TEST_TABLE_PREFIX=test_ + +# This table prefix used by the WordPress site in end-to-end tests. +WORDPRESS_TABLE_PREFIX=wp_ + +# The URL and domain of the WordPress site used in end-to-end tests. +WORDPRESS_URL=http://localhost:42911 +WORDPRESS_DOMAIN=localhost:42911 + +# The username and password of the administrator user of the WordPress site used in end-to-end tests. +WORDPRESS_ADMIN_USER=admin +WORDPRESS_ADMIN_PASSWORD=password + +# The host and port of the ChromeDriver server that will be used in end-to-end tests. +CHROMEDRIVER_HOST=localhost +CHROMEDRIVER_PORT=37863 + +# The port on which the PHP built-in server will serve the WordPress installation. +BUILTIN_SERVER_PORT=42911 + +<<< /.env <<< + +>>> /Support/EndToEndTester.php >>> >> /Support/EndToEndTester.php >>> +>>> /Support/IntegrationTester.php >>> >> /Support/Data/.gitkeep >>> - -<<< /Support/Data/.gitkeep <<< +<<< /Support/IntegrationTester.php <<< >>> /Support/_generated/EndToEndTesterActions.php >>> getScenario()->runStep(new \Codeception\Step\Action('grabPostFieldFromDatabase', func_get_args())); } @@ -10064,85 +10140,9 @@ trait IntegrationTesterActions <<< /Support/_generated/.gitignore <<< ->>> /EndToEnd/_bootstrap.php >>> -` command - * to run WP-CLI commands on the WordPress site and database used by the EndToEnd suite. - * E.g.: - * `vendor/bin/codecept wp:cli EndToEnd db import tests/Support/Data/dump.sql` to load dump file. - * `vendor/bin/codecept wp:cli EndToEnd plugin activate woocommerce` to activate the WooCommerce plugin. - * `vendor/bin/codecept wp:cli EndToEnd user create alice alice@example.com --role=administrator` to create a new user. - * `vendor/bin/codecept wp:cli EndToEnd db export tests/Support/Data/dump.sql` to update the dump file. - */ -<<< /EndToEnd/_bootstrap.php <<< - ->>> /EndToEnd/ActivationCest.php >>> -amOnPage('/'); - $I->seeElement('body'); - } - - public function test_can_login_as_admin(EndToEndTester $I): void - { - $I->loginAsAdmin(); - $I->amOnAdminPage('/'); - $I->seeElement('body.wp-admin'); - } -} - -<<< /EndToEnd/ActivationCest.php <<< - ->>> /.env >>> -# The path to the WordPress root directory, the one containing the wp-load.php file. -# This can be a relative path from the directory that contains the codeception.yml file, -# or an absolute path. -WORDPRESS_ROOT_DIR=. - -# Tests will require a MySQL database to run. -# The database will be created if it does not exist. -# Do not use a database that contains important data! -WORDPRESS_DB_URL=sqlite://%codecept_root_dir%/tests/Support/Data/db.sqlite - -# The Integration suite will use this table prefix for the WordPress tables. -TEST_TABLE_PREFIX=test_ - -# This table prefix used by the WordPress site in end-to-end tests. -WORDPRESS_TABLE_PREFIX=wp_ - -# The URL and domain of the WordPress site used in end-to-end tests. -WORDPRESS_URL=http://localhost:53843 -WORDPRESS_DOMAIN=localhost:53843 - -# The username and password of the administrator user of the WordPress site used in end-to-end tests. -WORDPRESS_ADMIN_USER=admin -WORDPRESS_ADMIN_PASSWORD=password - -# The host and port of the ChromeDriver server that will be used in end-to-end tests. -CHROMEDRIVER_HOST=localhost -CHROMEDRIVER_PORT=53851 - -# The port on which the PHP built-in server will serve the WordPress installation. -BUILTIN_SERVER_PORT=53843 +>>> /Support/Data/.gitkeep >>> -<<< /.env <<< +<<< /Support/Data/.gitkeep <<< >>> /_output/.gitignore >>> * diff --git a/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php b/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php index d519ea37e..af55cc894 100644 --- a/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php +++ b/tests/unit/lucatume/WPBrowser/ManagedProcess/ChromedriverTest.php @@ -35,7 +35,7 @@ public function should_throw_if_binary_not_found(): void $this->uopzSetStaticMethodReturn(Composer::class, 'binDir', '/not-a-binary'); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_BINARY_NOT_FOUND); + $this->expectExceptionCode(ManagedProcessInterface::ERR_BINARY_NOT_FOUND); new ChromeDriver(); } @@ -50,7 +50,7 @@ public function should_throw_if_binary_is_not_executable(): void $this->uopzSetStaticMethodReturn(Composer::class, 'binDir', __FILE__); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_BINARY_NOT_FOUND); + $this->expectExceptionCode(ManagedProcessInterface::ERR_BINARY_NOT_FOUND); new ChromeDriver(); } @@ -65,7 +65,7 @@ public function should_throw_if_binary_cannot_be_started_with_arguments(): void $this->uopzSetStaticMethodReturn(Composer::class, 'binDir', $throwingBin); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_START); + $this->expectExceptionCode(ManagedProcessInterface::ERR_START); $chromedriver = new ChromeDriver(); $chromedriver->start(); @@ -94,7 +94,7 @@ public function getPid(): ?int $chromedriver = new ChromeDriver(3456, ['--url-base=wd/hub', '--headless']); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_PID); + $this->expectExceptionCode(ManagedProcessInterface::ERR_PID); $chromedriver->start(); } @@ -122,7 +122,7 @@ public function getPid(): ?int $chromedriver = new ChromeDriver(3456, ['--url-base=wd/hub', '--headless']); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_PID_FILE); + $this->expectExceptionCode(ManagedProcessInterface::ERR_PID_FILE); $this->uopzSetFunctionReturn('file_put_contents', function (string $file): false|int { return $file === ChromeDriver::getPidFile() ? false : 0; @@ -171,7 +171,7 @@ public function should_throw_if_pid_file_removal_fails(): void $this->uopzSetFunctionReturn('unlink', false); $this->expectException(RuntimeException::class); - $this->expectExceptionCode(ManagedProcessinterface::ERR_PID_FILE_DELETE); + $this->expectExceptionCode(ManagedProcessInterface::ERR_PID_FILE_DELETE); $chromedriver->stop(); } diff --git a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php index 17d2ab3c1..a9ef57b72 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php @@ -51,6 +51,22 @@ public function should_throw_if_trying_to_build_on_non_json_file(): void new Composer(__FILE__); } + /** + * It should throw if json file contents cannot be decoded + * + * @test + */ + public function should_throw_if_json_file_contents_cannot_be_decoded(): void + { + $jsonFile = sys_get_temp_dir() . '/json-file-returning-array.json'; + file_put_contents($jsonFile, '[]'); + + $this->expectException(RuntimeException::class); + $this->expectExceptionCode(Composer::ERR_DECODING_FAILED); + + new Composer($jsonFile); + } + /** * It should throw if file contents cannot be read *