Skip to content

Commit

Permalink
test(unit) cover commands
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Aug 18, 2023
1 parent d63160e commit c7e7272
Show file tree
Hide file tree
Showing 16 changed files with 1,054 additions and 56 deletions.
2 changes: 0 additions & 2 deletions codeception.dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ coverage:
- src/*
wpFolder: '%WORDPRESS_ROOT_DIR%'
extensions:
enabled:
- "lucatume\\WPBrowser\\Extension\\EventDispatcherBridge"
commands:
- "lucatume\\WPBrowser\\Command\\RunOriginal"
- "lucatume\\WPBrowser\\Command\\RunAll"
Expand Down
17 changes: 14 additions & 3 deletions src/Command/DbExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
class DbExport extends Command implements CustomCommandInterface
{

public const INVALID_PATH = 1;
public const DUMP_DIR_NOT_FOUND = 2;
public const INSTALLATION_DB_NOT_FOUND = 3;

public static function getCommandName(): string
{
return 'wp:db:export';
Expand Down Expand Up @@ -50,19 +54,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$dumpFilePath = $input->getArgument('dumpFilePath');

if (!(is_string($path) && is_dir($path) && is_file($path . '/wp-load.php'))) {
throw new InvalidArgumentException("The path provided is not a valid WordPress root directory.");
throw new InvalidArgumentException(
"The path provided is not a valid WordPress root directory.",
self::INVALID_PATH
);
}

if (!(is_string($dumpFilePath) && is_dir(dirname($dumpFilePath)))) {
throw new InvalidArgumentException(
"The dump file path provided is not valid: the directory does not exist."
"The dump file path provided is not valid: the directory does not exist.",
self::DUMP_DIR_NOT_FOUND
);
}

$db = (new Installation($path))->getDb();

if ($db === null) {
throw new RuntimeException("Could not get the database instance from the installation.");
throw new RuntimeException(
"Could not get the database instance from the installation.",
self::INSTALLATION_DB_NOT_FOUND
);
}

$db->dump($dumpFilePath);
Expand Down
13 changes: 11 additions & 2 deletions src/Command/DbImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

class DbImport extends Command implements CustomCommandInterface
{
public const INVALID_PATH = 1;
public const DUMP_FILE_NOT_FOUND = 2;

public static function getCommandName(): string
{
return 'wp:db:import';
Expand Down Expand Up @@ -49,11 +52,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$dumpFilePath = $input->getArgument('dumpFilePath');

if (!(is_string($path) && is_dir($path) && is_file($path . '/wp-load.php'))) {
throw new InvalidArgumentException("The path provided is not a valid WordPress root directory.");
throw new InvalidArgumentException(
"The path provided is not a valid WordPress root directory.",
self::INVALID_PATH
);
}

if (!(is_string($dumpFilePath) && is_file($dumpFilePath) && is_readable($dumpFilePath))) {
throw new InvalidArgumentException("The dump file path provided is not a readable file.");
throw new InvalidArgumentException(
"The dump file path provided is not a readable file.",
self::DUMP_FILE_NOT_FOUND
);
}

$db = (new Installation($path))->getDb();
Expand Down
2 changes: 1 addition & 1 deletion src/Command/DevInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$serviceExtensions = $this->getServiceExtensions();

if (count($serviceExtensions) === 0) {
$output->writeln('No services to start.');
$output->writeln('No services extensions found.');
return 0;
}

Expand Down
84 changes: 64 additions & 20 deletions src/Command/ServiceExtensionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,35 @@ protected function getServiceExtensions(): array
return [];
}

return array_filter(
$enabledExtensions,
static fn($extension) => is_string($extension) && is_a($extension, ServiceExtension::class, true),
);
$serviceExtensions = [];
foreach ($enabledExtensions as $key => $value) {
if (is_string($key) && is_a($key, ServiceExtension::class, true)) {
$serviceExtensions[] = $key;
continue;
}

if (is_array($value)) {
// Configured inline.
$extensionClass = array_key_first($value);

if (!is_string($extensionClass)) {
continue;
}

if (!is_a($extensionClass, ServiceExtension::class, true)) {
continue;
}

$serviceExtensions[] = $extensionClass;
continue;
}

if (is_string($value) && is_a($value, ServiceExtension::class, true)) {
$serviceExtensions[] = $value;
}
}

return $serviceExtensions;
}

/**
Expand All @@ -68,26 +93,45 @@ protected function getServiceExtensionConfig(string $serviceExtension): array
return [];
}

if (!(
isset($codeceptionConfig['extensions']['config'])
&& is_array($codeceptionConfig['extensions']['config']))
) {
return [];
$extensions = $codeceptionConfig['extensions'];

// Look up the `enabled` section.
if (isset($extensions['enabled']) && is_array($extensions['enabled'])) {
foreach ($extensions['enabled'] as $key => $value) {
if (
$key === $serviceExtension
&& is_a($key, ServiceExtension::class, true)
&& isset($value[0]) && is_array($value[0])
) {
// Configured inline.
return $value[0];
}

if (is_array($value)) {
$extensionClass = array_key_first($value);

if ($extensionClass !== $serviceExtension) {
continue;
}

if ($value[$extensionClass] === null) {
continue;
}

return $value[$extensionClass];
}
}
}

if (!(
isset($codeceptionConfig['extensions']['config'][$serviceExtension])
&& is_array($codeceptionConfig['extensions']['config'][$serviceExtension]))
// Lookup the `config` section.
if (isset($extensions['config'])
&& is_array($extensions['config'])
&& isset($extensions['config'][$serviceExtension])
&& is_array($extensions['config'][$serviceExtension])
) {
return [];
}

$extensionConfig = $codeceptionConfig['extensions']['config'][$serviceExtension];

if (!is_array($extensionConfig)) {
return [];
return $extensions['config'][$serviceExtension];
}

return $extensionConfig;
return [];
}
}
33 changes: 13 additions & 20 deletions src/Events/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,21 @@ public static function setEventDispatcher(EventDispatcherInterface $eventDispatc
return;
}

try {
if ($previousEventDispatcher instanceof EventDispatcherInterface) {
$listeners = Property::readPrivate($previousEventDispatcher, 'listeners');
} else {
$listeners = [];
}

if ($listeners && is_array($listeners)) {
foreach ($listeners as $event => $priorities) {
foreach ($priorities as $priority => $callback) {
$eventDispatcher->addListener($event, $callback, $priority);
}
if ($previousEventDispatcher !== null) {
/** @var array<callable[]> $previousListeners */
$previousListeners = $previousEventDispatcher->getListeners();
foreach ($previousListeners as $eventName => $listeners) {
foreach ($listeners as $listener) {
$priority = $previousEventDispatcher->getListenerPriority($eventName, $listener);
$eventDispatcher->addListener($eventName, $listener, $priority ?? 0);
}
}
} catch (ReflectionException) {
// Do nothing.
}

self::$eventDispatcher = $eventDispatcher;
}

public static function getEventDispatcher(): EventDispatcherInterface
public static function getEventDispatcher(): ?EventDispatcherInterface
{
if (self::$eventDispatcher === null) {
// Create a one local to the Dispatcher.
Expand All @@ -73,10 +66,10 @@ public static function getEventDispatcher(): EventDispatcherInterface
*/
public static function addListener(string $eventName, callable $listener, int $priority = 0): Closure
{
self::getEventDispatcher()->addListener($eventName, $listener, $priority);
self::getEventDispatcher()?->addListener($eventName, $listener, $priority);

return static function () use ($eventName, $listener): void {
self::getEventDispatcher()->removeListener($eventName, $listener);
self::getEventDispatcher()?->removeListener($eventName, $listener);
};
}

Expand All @@ -90,12 +83,12 @@ public static function addListener(string $eventName, callable $listener, int $p
* @param array<string,mixed> $context A map of the event context that will set as context of the dispatched
* event.
*
* @return object The dispatched event.
* @return object|null The dispatched event, or `null` if no event was dispatched.
*/
public static function dispatch(string $name, mixed $origin = null, array $context = []): object
public static function dispatch(string $name, mixed $origin = null, array $context = []): ?object
{
$event = new Event($name, $context, $origin);

return self::getEventDispatcher()->dispatch($event, $name);
return self::getEventDispatcher()?->dispatch($event, $name);
}
}
16 changes: 10 additions & 6 deletions src/Extension/EventDispatcherBridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Codeception\Exception\ExtensionException;
use Codeception\Extension;
use lucatume\WPBrowser\Events\Dispatcher;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface as SymfonyEventDispatcher;

class EventDispatcherBridge extends Extension
Expand Down Expand Up @@ -57,13 +58,16 @@ private function captureEventDispatcher(SuiteEvent $event, string $eventName): v
}

$previousDispatcher = Dispatcher::getEventDispatcher();
/** @var callable[] $listeners */
$listeners = $previousDispatcher->getListeners($eventName);

// Call the listeners for this event now,remove them from the previous dispatcher.
foreach ($listeners as $listener) {
$listener($event, $eventName, $eventDispatcher);
$previousDispatcher->removeListener($eventName, $listener);
if ($previousDispatcher !== null) {
/** @var callable[] $listeners */
$listeners = $previousDispatcher->getListeners($eventName);

// Call the listeners for this event now,remove them from the previous dispatcher.
foreach ($listeners as $listener) {
$listener($event, $eventName, $eventDispatcher);
$previousDispatcher->removeListener($eventName, $listener);
}
}

Dispatcher::setEventDispatcher($eventDispatcher);
Expand Down
16 changes: 16 additions & 0 deletions tests/_support/Traits/UopzFunctions.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,20 @@ protected function uopzUnsetMock(string $class): void
unset(self::$uopzSetMocks[$index]);
uopz_unset_mock($class);
}

protected function uopzUnsetFunctionReturn(string $string)
{
if (!function_exists('uopz_unset_return')) {
$this->markTestSkipped('This test requires the uopz extension');
}

$index = array_search($string, self::$uopzSetFunctionReturns, true);

if ($index === false) {
return;
}

uopz_unset_return($string);
unset(self::$uopzSetFunctionReturns[$index]);
}
}
Loading

0 comments on commit c7e7272

Please sign in to comment.