Skip to content

Commit

Permalink
Merge 6a581a3 into ab3c15f
Browse files Browse the repository at this point in the history
  • Loading branch information
josefbenjac committed Jul 27, 2018
2 parents ab3c15f + 6a581a3 commit 5c4d974
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/TaskSet.php
Expand Up @@ -77,7 +77,28 @@ public function set(array $args): void
}

$content = $this->fileLoader->loadFile($file);
$this->fileLoader->saveFile(array_merge($content, $updated), $file);

$this->fileLoader->saveFile(self::mergeTree($updated, $content), $file);
}

/**
* Nette\Arrays::mergeTree
*
* Recursively appends elements of remaining keys from the second array to the first.
*
* @param mixed[] $arr1
* @param mixed[] $arr2
* @return mixed[]
*/
public static function mergeTree(array $arr1, array $arr2): array
{
$res = $arr1 + $arr2;
foreach (array_intersect_key($arr1, $arr2) as $k => $v) {
if (is_array($v) && is_array($arr2[$k])) {
$res[$k] = self::mergeTree($v, $arr2[$k]);
}
}
return $res;
}

}
219 changes: 219 additions & 0 deletions tests/cases/TaskSet.phpt
@@ -0,0 +1,219 @@
<?php declare(strict_types = 1);

namespace Contributte\Neonizer\Tests;

/**
* Test: TaskSet
*
* @testCase
*/

use Composer\IO\IOInterface;
use Contributte\Neonizer\Exception\Logical\InvalidArgumentException;
use Contributte\Neonizer\TaskSet;
use Mockery;
use Mockery\MockInterface;
use Nette\Neon\Neon;
use Tester\Assert;
use Tester\TestCase;

require_once __DIR__ . '/../bootstrap.php';

class TaskSetTest extends TestCase
{

protected function tearDown(): void
{
Mockery::close();
}

public function testSetNoArgs(): void
{
/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('write')
->withArgs(['<error>Configuration file is required, e.q. -- $(pwd)/app/config/config.local.neon</error>'])
->once()
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([]);

// Tester hack
Assert::true(true);
}

public function testSetNoParams(): void
{
/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('write')
->withArgs(['<error>Add some parameters, e.q. -- $(pwd)/app/config/config.local.neon --database.host=localhost --database.user=neonizer</error>'])
->once()
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([__DIR__ . '/../fixtures/files/set.neon']);

// Tester hack
Assert::true(true);
}

public function testSetInvalidArgument(): void
{
/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$taskSet = new TaskSet($io);

Assert::throws(function () use ($taskSet): void {
$taskSet->set([
__DIR__ . '/../fixtures/files/set.neon',
'invalid',
]);
}, InvalidArgumentException::class, 'Invalid argument "invalid" given.');
}

public function testSetNoChange(): void
{
$file = $this->createTestedFile('noChange');
$expected = '# This file is auto-generated by composer' . PHP_EOL . Neon::encode([
'parameters' => [
'database' => [
'user' => 'bar',
'pass' => 'bar',
'dbname' => 'bar',
],
'mode' => 'bar',
],
], Neon::BLOCK);

/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('isInteractive')
->andReturn(true)
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([
$file,
'--database.user=bar',
]);

$actual = file_get_contents($file);
Assert::same($expected, $actual);
}

public function testSetChangeValue(): void
{
$file = $this->createTestedFile('changeValue');
$expected = '# This file is auto-generated by composer' . PHP_EOL . Neon::encode([
'parameters' => [
'database' => [
'user' => 'foo',
'pass' => 'bar',
'dbname' => 'bar',
],
'mode' => 'bar',
],
], Neon::BLOCK);

/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('isInteractive')
->andReturn(true)
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([
$file,
'--database.user=foo',
]);

$actual = file_get_contents($file);
Assert::same($expected, $actual);
}

public function testSetAddKey(): void
{
$file = $this->createTestedFile('addKey');
$expected = '# This file is auto-generated by composer' . PHP_EOL . Neon::encode([
'parameters' => [
'database' => [
'host' => 'bar',
'user' => 'bar',
'pass' => 'bar',
'dbname' => 'bar',
],
'mode' => 'bar',
],
], Neon::BLOCK);

/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('isInteractive')
->andReturn(true)
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([
$file,
'--database.host=bar',
]);

$actual = file_get_contents($file);
Assert::same($expected, $actual);
}

public function testSetMultiple(): void
{
$file = $this->createTestedFile('multiple');
$expected = '# This file is auto-generated by composer' . PHP_EOL . Neon::encode([
'parameters' => [
'database' => [
'host' => 'bar',
'user' => 'foo',
'pass' => 'bar',
'dbname' => 'bar',
],
'mode' => 'bar',
],
], Neon::BLOCK);

/** @var IOInterface|MockInterface $io */
$io = Mockery::mock(IOInterface::class);
$io->shouldReceive('isInteractive')
->andReturn(true)
->getMock();

$taskSet = new TaskSet($io);
$taskSet->set([
$file,
'--database.host=bar',
'--database.user=foo',
]);

$actual = file_get_contents($file);
Assert::same($expected, $actual);
}

private function createTestedFile(string $name): string
{
$neon = Neon::encode([
'parameters' => [
'database' => [
'user' => 'bar',
'pass' => 'bar',
'dbname' => 'bar',
],
'mode' => 'bar',
],
], Neon::BLOCK);
$content = '# This file is auto-generated by composer' . PHP_EOL . $neon;
$fileName = __DIR__ . '/../tmp/set_' . $name . '.neon';
file_put_contents($fileName, $content);
return $fileName;
}

}

(new TaskSetTest())->run();
9 changes: 9 additions & 0 deletions tests/fixtures/files/set.neon
@@ -0,0 +1,9 @@
# This file is auto-generated by composer
parameters:
database:
user: bar
pass: bar
dbname: bar

mode: bar

0 comments on commit 5c4d974

Please sign in to comment.