Skip to content

Commit 4c3df39

Browse files
author
Klaas Sangers
committed
Implement unit test and update object to be testable
1 parent a92986a commit 4c3df39

File tree

2 files changed

+207
-10
lines changed

2 files changed

+207
-10
lines changed

src/DependencyInstaller.php

+40-10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Composer\Factory;
1313
use Composer\Json\JsonFile;
1414
use Symfony\Component\Console\Input\ArrayInput;
15+
use Symfony\Component\Console\Output\OutputInterface;
1516

1617
class DependencyInstaller
1718
{
@@ -20,14 +21,30 @@ class DependencyInstaller
2021
*/
2122
private $definition;
2223

24+
/**
25+
* @var string
26+
*/
27+
private $workingDir;
28+
/**
29+
* @var null|OutputInterface
30+
*/
31+
private $output;
32+
2333
/**
2434
* Constructor.
35+
*
36+
* @param string|null $composerFile
37+
* @param OutputInterface|null $output
2538
*/
26-
public function __construct()
27-
{
28-
$composerFile = Factory::getComposerFile();
39+
public function __construct(
40+
string $composerFile = null,
41+
OutputInterface $output = null
42+
) {
43+
$composerFile = $composerFile ?: Factory::getComposerFile();
2944
$composerJson = new JsonFile($composerFile);
3045
$this->definition = $composerJson->read();
46+
$this->workingDir = dirname($composerFile);
47+
$this->output = $output;
3148
}
3249

3350
/**
@@ -41,7 +58,9 @@ public function __construct()
4158
*/
4259
public function installRepository(string $name, string $type, string $url)
4360
{
44-
if (array_key_exists($name, $this->definition['repositories'])) {
61+
if (array_key_exists('repositories', $this->definition)
62+
&& array_key_exists($name, $this->definition['repositories'])
63+
) {
4564
return;
4665
}
4766

@@ -59,25 +78,34 @@ public function installRepository(string $name, string $type, string $url)
5978
'setting-value' => [
6079
$type,
6180
$url
62-
]
81+
],
82+
'--working-dir' => $this->workingDir
6383
],
6484
$definition
6585
);
6686

67-
$application->run($input);
87+
$application->setAutoExit(false);
88+
$application->run($input, $this->output);
6889
}
6990

7091
/**
7192
* Install a composer package.
7293
*
7394
* @param string $name
7495
* @param string $version
96+
* @param bool $dev
7597
*
7698
* @return void
99+
*
100+
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
77101
*/
78-
public function installPackage(string $name, string $version)
102+
public function installPackage(string $name, string $version, bool $dev = true)
79103
{
80-
if (array_key_exists($name, $this->definition['require-dev'])) {
104+
$node = $dev ? 'require-dev' : 'require';
105+
106+
if (array_key_exists($node, $this->definition)
107+
&& array_key_exists($name, $this->definition[$node])
108+
) {
81109
return;
82110
}
83111

@@ -92,14 +120,16 @@ public function installPackage(string $name, string $version)
92120
[
93121
'command' => 'require',
94122
'packages' => [$name . ':' . $version],
95-
'--dev' => true,
123+
'--dev' => $dev,
96124
'--no-scripts' => true,
97125
'--no-interaction' => true,
98126
'--no-plugins' => true,
127+
'--working-dir' => $this->workingDir
99128
],
100129
$definition
101130
);
102131

103-
$application->run($input);
132+
$application->setAutoExit(false);
133+
$application->run($input, $this->output);
104134
}
105135
}

tests/DependencyInstallerTest.php

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
/**
3+
* Copyright MediaCT. All rights reserved.
4+
* https://www.mediact.nl
5+
*/
6+
7+
namespace Mediact\Composer\DependencyInstaller\Tests;
8+
9+
use Composer\Json\JsonFile;
10+
use Mediact\Composer\DependencyInstaller\DependencyInstaller;
11+
use PHPUnit\Framework\TestCase;
12+
use Symfony\Component\Console\Output\OutputInterface;
13+
14+
/**
15+
* @coversDefaultClass \Mediact\Composer\DependencyInstaller\DependencyInstaller
16+
*/
17+
class DependencyInstallerTest extends TestCase
18+
{
19+
/** @var string */
20+
private static $directory = __DIR__ . DIRECTORY_SEPARATOR . 'tmp';
21+
22+
/**
23+
* @return void
24+
*/
25+
public static function setUpBeforeClass()
26+
{
27+
static::tearDownAfterClass();
28+
29+
mkdir(static::$directory);
30+
chdir(static::$directory);
31+
file_put_contents('composer.json', '{}');
32+
}
33+
34+
/**
35+
* @return void
36+
*/
37+
public static function tearDownAfterClass()
38+
{
39+
if (is_dir(static::$directory)) {
40+
static::rrmdir(static::$directory);
41+
}
42+
}
43+
44+
/**
45+
* @param string $src
46+
*
47+
* @return void
48+
*/
49+
private static function rrmdir(string $src)
50+
{
51+
$dir = opendir($src);
52+
while (false !== ($file = readdir($dir))) {
53+
if (($file != '.') && ($file != '..')) {
54+
$full = $src . '/' . $file;
55+
if (is_dir($full)) {
56+
static::rrmdir($full);
57+
} else {
58+
unlink($full);
59+
}
60+
}
61+
}
62+
closedir($dir);
63+
rmdir($src);
64+
}
65+
66+
67+
/**
68+
* @return DependencyInstaller
69+
* @covers ::__construct
70+
*/
71+
public function testConstructor(): DependencyInstaller
72+
{
73+
$installer = new DependencyInstaller(
74+
'composer.json',
75+
$this->createMock(OutputInterface::class)
76+
);
77+
78+
$this->assertInstanceOf(
79+
DependencyInstaller::class,
80+
$installer
81+
);
82+
83+
return $installer;
84+
}
85+
86+
/**
87+
* @depends testConstructor
88+
* @dataProvider repositoryProvider
89+
*
90+
* @param string $name
91+
* @param string $type
92+
* @param string $url
93+
* @param DependencyInstaller $dependencyInstaller
94+
*
95+
* @return void
96+
* @covers ::installRepository
97+
*/
98+
public function testInstallRepository(
99+
string $name,
100+
string $type,
101+
string $url,
102+
DependencyInstaller $dependencyInstaller
103+
) {
104+
$dependencyInstaller->installRepository($name, $type, $url);
105+
106+
$jsonFile = new JsonFile('composer.json');
107+
$definition = $jsonFile->read();
108+
109+
$this->assertArrayHasKey('repositories', $definition);
110+
$this->assertArrayHasKey($name, $definition['repositories']);
111+
$this->assertArrayHasKey('type', $definition['repositories'][$name]);
112+
$this->assertArrayHasKey('url', $definition['repositories'][$name]);
113+
$this->assertEquals($type, $definition['repositories'][$name]['type']);
114+
$this->assertEquals($url, $definition['repositories'][$name]['url']);
115+
}
116+
117+
/**
118+
* @return array
119+
*/
120+
public function repositoryProvider(): array
121+
{
122+
return [
123+
['mediact', 'composer', 'https://composer.mediact.nl']
124+
];
125+
}
126+
127+
/**
128+
* @depends testConstructor
129+
* @dataProvider packageProvider
130+
*
131+
* @param string $name
132+
* @param string $version
133+
* @param bool $dev
134+
* @param DependencyInstaller $dependencyInstaller
135+
*
136+
* @return void
137+
* @covers ::installPackage
138+
*/
139+
public function testInstallPackage(
140+
string $name,
141+
string $version,
142+
bool $dev,
143+
DependencyInstaller $dependencyInstaller
144+
) {
145+
$dependencyInstaller->installPackage($name, $version, $dev);
146+
147+
$jsonFile = new JsonFile('composer.json');
148+
$definition = $jsonFile->read();
149+
150+
$node = $dev ? 'require-dev' : 'require';
151+
152+
$this->assertArrayHasKey($node, $definition);
153+
$this->assertArrayHasKey($name, $definition[$node]);
154+
$this->assertEquals($version, $definition[$node][$name]);
155+
}
156+
157+
/**
158+
* @return array
159+
*/
160+
public function packageProvider(): array
161+
{
162+
return [
163+
['psr/log', '@stable', true],
164+
['psr/log', '@stable', false]
165+
];
166+
}
167+
}

0 commit comments

Comments
 (0)