Skip to content

Commit

Permalink
tests/e2e - Isolate each call to civix. More representative of real u…
Browse files Browse the repository at this point in the history
…sage.
  • Loading branch information
totten committed Jun 27, 2024
1 parent 6f235e6 commit 56d043e
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 7 deletions.
34 changes: 34 additions & 0 deletions src/CRM/CivixBundle/Test/CommandTester.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace CRM\CivixBundle\Test;

interface CommandTester {

/**
* Executes the command.
*
* Available execution options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
* * capture_stderr_separately: Make output of stdOut and stdErr separately available
*
* @param array $input An array of command arguments and options
* @param array $options An array of execution options
*
* @return int The command exit code
*/
public function execute(array $input, array $options = []);

/**
* @return string
*/
public function getDisplay(bool $normalize = FALSE);

/**
* @return int
*/
public function getStatusCode();

}
83 changes: 83 additions & 0 deletions src/CRM/CivixBundle/Test/SubProcessCommandTester.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace CRM\CivixBundle\Test;

use Symfony\Component\Process\Process;

class SubProcessCommandTester implements CommandTester {

/**
* @var array
*/
protected $baseCommand;

/**
* @var string|null
*/
protected $display;

/**
* @var int|null
*/
protected $statusCode;

/**
* @param array $baseCommand
*/
public function __construct(array $baseCommand) {
$this->baseCommand = $baseCommand;
}

/**
* Executes the command.
*
* @param array $input An array of command arguments and options
* @param array $options An array of execution options
* Ignored
* @return int The command exit code
*/
public function execute(array $input, array $options = []) {
if (!empty($options)) {
throw new \LogicException(__CLASS__ . " does not implement support for execute() options");
}

$command = $this->baseCommand;
foreach ($input as $key => $value) {
if (substr($key, 0, 2) === '--') {
$command[] = "$key=$value";
}
else {
$command[] = $value;
}
}

$buffer = fopen('php://memory', 'w+');

$p = new Process($command);
$p->run(function ($type, $data) use ($buffer) {
// Default policy - combine STDOUT and STDIN into one continuous stream.
fwrite($buffer, $data);
});
$this->statusCode = $p->getExitCode();

rewind($buffer);
$this->display = stream_get_contents($buffer);
fclose($buffer);

return $this->statusCode;
}

public function getDisplay(bool $normalize = FALSE) {
if ($normalize) {
return str_replace(\PHP_EOL, "\n", $this->display);
}
else {
return $this->display;
}
}

public function getStatusCode(): int {
return $this->statusCode;
}

}
35 changes: 28 additions & 7 deletions tests/e2e/CivixProjectTestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

namespace E2E;

use CRM\CivixBundle\Application;
use CRM\CivixBundle\Generator;
use CRM\CivixBundle\Test\CommandTester;
use CRM\CivixBundle\Test\SubProcessCommandTester;
use CRM\CivixBundle\Utils\Files;
use CRM\CivixBundle\Utils\Path;
use ProcessHelper\ProcessHelper as PH;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Tester\CommandTester;

/**
* Add this to a test-class to define an E2E test with a new civix-style extension/project.
Expand Down Expand Up @@ -71,11 +71,32 @@ public static function getExtPath(...$subpath): Path {
return static::getWorkspacePath(...$subpath);
}

public static function civix(string $command): CommandTester {
public static function civix(string $subCommand): CommandTester {
\Civix::reset();
$application = new Application();
$command = $application->find($command);
return new CommandTester($command);

$isolation = getenv('CIVIX_TEST_ISOLATION') ?: 'on';

switch ($isolation) {
case 'on':
if (getenv('CIVIX_TEST_BINARY')) {
$baseCommand = [getenv('CIVIX_TEST_BINARY')];
}
else {
$baseCommand = ['php', (dirname(__DIR__, 2) . '/bin/civix')];
}
$baseCommand[] = $subCommand;
return new SubProcessCommandTester($baseCommand);

case 'off':
$application = new \CRM\CivixBundle\Application();
$command = $application->find($subCommand);
return new class ($command) extends \Symfony\Component\Console\Tester\CommandTester implements CommandTester {

};

default:
throw new \RuntimeException("Unrecognized value of CIVIX_TEST_BINARY. Specify on|off.");
}
}

public function civixGenerateModule(string $key, array $options = []): CommandTester {
Expand All @@ -85,7 +106,7 @@ public function civixGenerateModule(string $key, array $options = []): CommandTe
'--enable' => 'false',
]);
if ($tester->getStatusCode() !== 0) {
throw new \RuntimeException(sprintf("Failed to generate module (%s)", $key));
throw new \RuntimeException(sprintf("Failed to generate module (%s):\n%s", $key, $tester->getDisplay(TRUE)));
}
return $tester;
}
Expand Down

0 comments on commit 56d043e

Please sign in to comment.