Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default packages – 6-beta-2 bugfix #49

Merged
merged 4 commits into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="replacers">
<directory>./tests/replacers/</directory>
<testsuite name="all">
<directory>./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
29 changes: 26 additions & 3 deletions src/Console/Commands/Compose.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,26 @@ protected function execute(InputInterface $input, OutputInterface $output)
$workingDir = getcwd();
$this->workingDir = $workingDir;

$config = json_decode(file_get_contents($workingDir . '/composer.json'));
$config = $config->extra->mozart;
$composerFile = $workingDir . '/composer.json';
if (!file_exists($composerFile)) {
$output->write('No composer.json found at current directory: ' . $workingDir);
return 1;
}

$composer = json_decode(file_get_contents($composerFile));
// If the json was malformed.
if (!is_object($composer)) {
$output->write('Unable to parse composer.json read at: ' . $workingDir);
return 1;
}

// if `extra` is missing or not an object or if it does not have a `mozart` key which is an object.
if (!isset($composer->extra) || !is_object($composer->extra)
|| !isset($composer->extra->mozart) || !is_object($composer->extra->mozart)) {
$output->write('Mozart config not readable in composer.json at extra->mozart');
return 1;
}
$config = $composer->extra->mozart;

$config->dep_namespace = preg_replace("/\\\{2,}$/", "\\", "$config->dep_namespace\\");

Expand All @@ -47,7 +65,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->mover = new Mover($workingDir, $config);
$this->replacer = new Replacer($workingDir, $config);

$require = empty($config->packages) ? array_keys(get_object_vars($this->config->require)) : $config->packages;
$require = array();
if (isset($config->packages) && is_array($config->packages)) {
$require = $config->packages;
} elseif (isset($composer->require) && is_object($composer->require)) {
$require = array_keys(get_object_vars($composer->require));
}

$packages = $this->findPackages($require);

Expand Down
225 changes: 225 additions & 0 deletions tests/Console/Commands/ComposeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
<?php
declare(strict_types=1);

use CoenJacobs\Mozart\Console\Commands\Compose;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class ComposeTest extends TestCase
{
static $cwd;

public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
self::$cwd = getcwd();
}

/**
* Before each test ensure the current working directory is this one.
*
* Record the previous PHPUnit cwd to restore after.
*/
public function setUp(): void
{
parent::setUp();

chdir(dirname(__FILE__));
}

/**
* When composer.json is absent, instead of failing with:
* "failed to open stream: No such file or directory"
* a better message should be written to the OutputInterface.
*
* @test
*/
public function it_fails_gracefully_when_composer_json_absent(): void
{

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}

/**
* When json_decode fails, instead of
* "Trying to get property 'extra' of non-object"
* a better message should be written to the OutputInterface.
*
* @test
*/
public function it_handles_malformed_json_with_grace(): void
{

$badComposerJson = '{ "name": "coenjacobs/mozart", }';

file_put_contents(__DIR__ . '/composer.json', $badComposerJson);

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}

/**
* When composer.json->extra is absent, instead of
* "Undefined property: stdClass::$extra"
* a better message should be written to the OutputInterface.
*
* @test
*/
public function it_handles_absent_extra_config_with_grace(): void
{

$badComposerJson = '{ "name": "coenjacobs/mozart" }';

file_put_contents(__DIR__ . '/composer.json', $badComposerJson);

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}


/**
* When composer.json->extra is not an object, instead of
* "Trying to get property 'mozart' of non-object"
* a better message should be written to the OutputInterface.
*
* @test
*/
public function it_handles_malformed_extra_config_with_grace(): void
{

$badComposerJson = '{ "name": "coenjacobs/mozart", "extra": [] }';

file_put_contents(__DIR__ . '/composer.json', $badComposerJson);

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}

/**
* When composer.json->extra->mozart is absent, instead of
* "Undefined property: stdClass::$mozart"
* a better message should be written to the OutputInterface.
*
* @test
*/
public function it_handles_absent_mozart_config_with_grace(): void
{

$badComposerJson = '{ "name": "coenjacobs/mozart", "extra": { "moozart": {} } }';

file_put_contents(__DIR__ . '/composer.json', $badComposerJson);

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}

/**
* When composer.json->extra->mozart is malformed, instead of
* "Undefined property: stdClass::$mozart"
* a better message should be written to the OutputInterface.
*
* is_object() added.
*
* @test
*/
public function it_handles_malformed_mozart_config__with_grace(): void
{

$badComposerJson = '{ "name": "coenjacobs/mozart", "extra": { "mozart": [] } }';

file_put_contents(__DIR__ . '/composer.json', $badComposerJson);

$inputInterfaceMock = $this->createMock(InputInterface::class);
$outputInterfaceMock = $this->createMock(OutputInterface::class);

$outputInterfaceMock->expects($this->exactly(1))
->method('write');

$compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose {
public function __construct($inputInterfaceMock, $outputInterfaceMock)
{
parent::__construct();

$this->execute($inputInterfaceMock, $outputInterfaceMock);
}
};
}

public function tearDown(): void
{
parent::tearDown();

$composer_json = __DIR__ . '/composer.json';
if (file_exists($composer_json)) {
unlink($composer_json);
}
}

public static function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
chdir(self::$cwd);
}
}