From 071ca83280fc9d865294be587257ca4b319d2fc5 Mon Sep 17 00:00:00 2001 From: Vishal Khode Date: Tue, 26 Mar 2024 12:38:12 +0530 Subject: [PATCH] ACMS-3658: More PHPUnit tests added. --- src/Robo/Tasks/DrushTask.php | 45 ++-- src/Robo/Tasks/LoadTasks.php | 7 +- tests/src/CommandsTestBase.php | 77 +++++++ tests/src/Helpers/NullLogOutputStylers.php | 19 ++ tests/src/Helpers/TestDrushTask.php | 24 +++ .../unit/Robo/Config/ConfigAwareTraitTest.php | 35 +++ tests/src/unit/Robo/Tasks/DrushTaskTest.php | 204 ++++++++++++++++++ tests/src/unit/Robo/Tasks/LoadTasksTest.php | 20 ++ 8 files changed, 406 insertions(+), 25 deletions(-) create mode 100644 tests/src/CommandsTestBase.php create mode 100644 tests/src/Helpers/NullLogOutputStylers.php create mode 100644 tests/src/Helpers/TestDrushTask.php create mode 100644 tests/src/unit/Robo/Config/ConfigAwareTraitTest.php create mode 100644 tests/src/unit/Robo/Tasks/DrushTaskTest.php create mode 100644 tests/src/unit/Robo/Tasks/LoadTasksTest.php diff --git a/src/Robo/Tasks/DrushTask.php b/src/Robo/Tasks/DrushTask.php index dba2dc1..8165bc3 100644 --- a/src/Robo/Tasks/DrushTask.php +++ b/src/Robo/Tasks/DrushTask.php @@ -46,7 +46,7 @@ class DrushTask extends CommandStack { /** * Indicates if the command output should be verbose. */ - protected bool $verbose = FALSE; + protected bool|int $verbose = FALSE; /** * Indicates if the command output should be very verbose. @@ -71,7 +71,7 @@ class DrushTask extends CommandStack { /** * Add or not the --ansi option. */ - protected bool $ansi = FALSE; + protected bool|NULL $ansi = NULL; /** * Drush commands to execute when task is run. @@ -90,12 +90,12 @@ class DrushTask extends CommandStack { /** * Adds the given drush command to a stack. * - * @param string $command + * @param string|array $commands * The drush command to execute. Do NOT include "drush" prefix. * * @return $this */ - public function drush(string $command) { + public function drush(string|array $commands) { // Clear out options associated with previous drush command. $this->setOptionsForLastCommand(); @@ -103,11 +103,11 @@ public function drush(string $command) { $this->init(); } - if (is_array($command)) { - $command = implode(' ', array_filter($command)); + if (is_array($commands)) { + $commands = implode(' ', array_filter($commands)); } - $this->commands[] = trim($command); + $this->commands[] = trim($commands); return $this; } @@ -156,7 +156,7 @@ public function dir($dir) { * * @return $this */ - public function verbose(bool $verbose) { + public function verbose(string|bool|int $verbose) { $this->verbose = $this->mixedToBool($verbose); return $this; } @@ -169,7 +169,7 @@ public function verbose(bool $verbose) { * * @return $this */ - public function veryVerbose(bool $verbose) { + public function veryVerbose(string|bool $verbose) { $this->veryVerbose = $this->mixedToBool($verbose); return $this; } @@ -182,7 +182,7 @@ public function veryVerbose(bool $verbose) { * * @return $this */ - public function debug(bool $verbose) { + public function debug(string|bool $verbose) { $this->debug = $this->mixedToBool($verbose); return $this; } @@ -203,12 +203,12 @@ public function includePath(string $path) { /** * Include or not the --ansi option for drush commands. * - * @param bool $ansi + * @param string|bool $ansi * The flag for including --ansi option. * * @return $this */ - public function ansi(bool $ansi) { + public function ansi(string|bool $ansi) { $this->ansi = $ansi; return $this; } @@ -237,7 +237,7 @@ protected function init(): void { $this->interactive(FALSE); } if (!isset($this->ansi)) { - $this->ansi($this->getConfig()->get('drush.ansi')); + $this->ansi($this->getConfig()->get('drush.ansi', FALSE)); } $this->defaultsInitialized = TRUE; @@ -249,14 +249,17 @@ protected function init(): void { * @param mixed $mixedVar * Mixed. * - * @return bool + * @return int|bool * TRUE/FALSE as per PHP's cast to boolean ruleset, with the exception that * a string value not equal to 'yes' or 'true' will evaluate to FALSE. */ - protected function mixedToBool(mixed $mixedVar): bool { + protected function mixedToBool(mixed $mixedVar): int|bool { if (is_string($mixedVar)) { $boolVar = ($mixedVar === 'yes' || $mixedVar === 'true'); } + elseif (is_int($mixedVar)) { + $boolVar = $mixedVar; + } else { $boolVar = (bool) $mixedVar; } @@ -290,8 +293,8 @@ protected function setGlobalOptions(): void { $this->option('no-interaction'); } - if ($this->verbose !== FALSE) { - $verbosity_threshold = $this->verbosityThreshold(); + if ($this->verbose !== FALSE || ($this->verbosityThreshold() >= OutputInterface::VERBOSITY_VERBOSE)) { + $verbosity_threshold = ($this->verbose !== FALSE) ? $this->verbose : $this->verbosityThreshold(); switch ($verbosity_threshold) { case OutputInterface::VERBOSITY_VERBOSE: $this->verbose(TRUE); @@ -304,12 +307,9 @@ protected function setGlobalOptions(): void { case OutputInterface::VERBOSITY_DEBUG: $this->debug(TRUE); break; + } } - if ($this->verbosityThreshold() >= OutputInterface::VERBOSITY_VERBOSE - && $this->verbose !== FALSE) { - $this->verbose(TRUE); - } if (($this->debug || $this->getConfig()->get('drush.debug')) && $this->getConfig()->get('drush.debug') !== FALSE) { @@ -359,9 +359,6 @@ public function option(string $option, string $value = NULL, string $separator = */ public function run() { $this->setupExecution(); - if (empty($this->exec)) { - throw new TaskException($this, 'You must add at least one command'); - } // If 'stopOnFail' is not set, or if there is only one command to run, // then execute the single command to run. diff --git a/src/Robo/Tasks/LoadTasks.php b/src/Robo/Tasks/LoadTasks.php index c8d6971..61d91b9 100644 --- a/src/Robo/Tasks/LoadTasks.php +++ b/src/Robo/Tasks/LoadTasks.php @@ -9,6 +9,11 @@ */ trait LoadTasks { + /** + * An instance of drush task class. + */ + protected string $drushTaskClass = DrushTask::class; + /** * Task drush. * @@ -17,7 +22,7 @@ trait LoadTasks { */ protected function taskDrush(): CollectionBuilder { /** @var \Acquia\Drupal\RecommendedSettings\Robo\Tasks\DrushTask $task */ - $task = $this->task(DrushTask::class); + $task = $this->task($this->drushTaskClass); /** @var \Symfony\Component\Console\Output\OutputInterface $output */ $output = $this->output(); $task->setVerbosityThreshold($output->getVerbosity()); diff --git a/tests/src/CommandsTestBase.php b/tests/src/CommandsTestBase.php new file mode 100644 index 0000000..ac86e24 --- /dev/null +++ b/tests/src/CommandsTestBase.php @@ -0,0 +1,77 @@ +createContainer(); + } + + /** + * Initialize the Container. + * + * @param ContainerInterface|null $container + * An instance of container object or NULL. + */ + protected function createContainer(?ContainerInterface $container = NULL): void { + if (!$container) { + $container = new Container(); + $output = new NullOutput(); + $this->setOutput($output); + + $config = new Config(); + $this->setConfig($config); + $logger = new Logger($this->output()); + $null_log_output = new NullLogOutputStylers; + $logger->setLogOutputStyler($null_log_output); + $container->add("logger", $logger); + + $app = Robo::createDefaultApplication("acquia/drupal-recommended-settings", "1.0.0"); + Robo::configureContainer($container, $app, $this->getConfig()); + + $tasks = new Tasks(); + $builder = CollectionBuilder::create($container, $tasks); + $this->setBuilder($builder); + $container->add("builder", $builder); + } + $this->container = $container; + } + + /** + * Returns an instance of container object. + */ + protected function getContainer(): ContainerInterface { + return $this->container; + } + +} diff --git a/tests/src/Helpers/NullLogOutputStylers.php b/tests/src/Helpers/NullLogOutputStylers.php new file mode 100644 index 0000000..ae3e2e3 --- /dev/null +++ b/tests/src/Helpers/NullLogOutputStylers.php @@ -0,0 +1,19 @@ +getCommandLine(); + $command_arr = explode(" ", $command); + $process->disableOutput(); + if (in_array("--error", $command_arr)) { + return new ResultData(ResultData::EXITCODE_ERROR, $command, []); + } + return new ResultData(ResultData::EXITCODE_OK, $command, []); + } + +} diff --git a/tests/src/unit/Robo/Config/ConfigAwareTraitTest.php b/tests/src/unit/Robo/Config/ConfigAwareTraitTest.php new file mode 100644 index 0000000..0a6c5ad --- /dev/null +++ b/tests/src/unit/Robo/Config/ConfigAwareTraitTest.php @@ -0,0 +1,35 @@ +assertEquals( + "/var/www/html/acms.prod/vendor", + $this->getConfigValue("composer.bin", "/var/www/html/acms.prod/vendor"), + ); + $config = new DrushConfig(); + $config->set("runtime.project", "/var/www/html/acms.prod"); + $config->set("options.root", "/var/www/html/acms.prod/docroot"); + $drush_config = new DefaultDrushConfig($config); + $this->setConfig($drush_config); + $this->assertEquals("/var/www/html/acms.prod", $this->getConfigValue("repo.root")); + } + +} diff --git a/tests/src/unit/Robo/Tasks/DrushTaskTest.php b/tests/src/unit/Robo/Tasks/DrushTaskTest.php new file mode 100644 index 0000000..cd66185 --- /dev/null +++ b/tests/src/unit/Robo/Tasks/DrushTaskTest.php @@ -0,0 +1,204 @@ +getConfig()->set("drush.alias", "self"); + $this->getConfig()->set("drush.bin", "./vendor/bin/drush"); + $this->drushTaskClass = TestDrushTask::class; + } + + /** + * Tests the basic Robo Drush task commands. + */ + public function testBasicDrushTaskCommands(): void { + $result = $this->taskDrush() + ->drush(["--version"]) + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self --version --no-interaction", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->drush(["site:install", "minimal"]) + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self site:install minimal --no-interaction", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->includePath('/var/www/html/project/drush') + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction --include=/var/www/html/project/drush", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->ansi(TRUE) + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction --ansi", + $result->getMessage(), + ); + + $this->getConfig()->set("drush.bin", ""); + $result = $this->taskDrush() + ->ansi("true") + ->drush("status") + ->run(); + $this->assertEquals( + "drush @self status --no-interaction --ansi", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->stopOnFail() + ->drush("updb") + ->drush("cr") + ->run(); + $this->assertEquals( + "drush @self cr --no-interaction\ndrush @self updb --no-interaction\n", + $result->getMessage(), + ); + } + + /** + * Tests the Robo Drush commands with uri parameter. + */ + public function testDrushTaskCommandsWithUri(): void { + $result = $this->taskDrush() + ->uri("site1") + ->drush(["site:install", "minimal"]) + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self site:install minimal --uri=site1 --no-interaction", + $result->getMessage(), + ); + + $this->expectException(TaskException::class); + $this->taskDrush() + ->option("uri", "site1") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self site:install minimal --uri=site1 --no-interaction", + $result->getMessage(), + ); + } + + /** + * Tests the Robo Drush commands with verbose. + */ + public function testDrushTaskCommandsWithVerbose(): void { + $result = $this->taskDrush() + ->verbose(TRUE) + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction -v", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->verbose("yes") + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction -v", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->veryVerbose("yes") + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction -vv", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->debug('true') + ->drush("status") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self status --no-interaction -vvv", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->verbose(OutputInterface::VERBOSITY_VERBOSE) + ->drush("cr") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self cr --no-interaction -v", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->verbose(OutputInterface::VERBOSITY_VERY_VERBOSE) + ->drush("cr") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self cr --no-interaction -vv", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->verbose(OutputInterface::VERBOSITY_DEBUG) + ->drush("cr") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self cr --no-interaction -vvv", + $result->getMessage(), + ); + + $result = $this->taskDrush() + ->setVerbosityThreshold(OutputInterface::VERBOSITY_DEBUG) + ->drush("cr") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self cr --no-interaction -vvv", + $result->getMessage(), + ); + } + + /** + * Tests the Robo Drush command exception. + */ + public function testDrushTaskCommandException(): void { + $result = $this->taskDrush() + ->stopOnFail() + ->drush("cr") + ->drush("--error") + ->run(); + $this->assertEquals( + "./vendor/bin/drush @self --error --no-interaction\n./vendor/bin/drush @self cr --no-interaction\n", + $result->getMessage(), + ); + $this->assertEquals(ResultData::EXITCODE_ERROR, $result->getExitCode()); + } + +} diff --git a/tests/src/unit/Robo/Tasks/LoadTasksTest.php b/tests/src/unit/Robo/Tasks/LoadTasksTest.php new file mode 100644 index 0000000..ed89c9e --- /dev/null +++ b/tests/src/unit/Robo/Tasks/LoadTasksTest.php @@ -0,0 +1,20 @@ +assertInstanceOf(CollectionBuilder::class, $this->taskDrush()); + $this->assertEquals(DrushTask::class, $this->drushTaskClass); + } + +}