Completed
Push — master ( d3051d...23bb84 )
by Marco
23s
created

E2EInstallerTest::createArtifact()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PackageVersionsTest;
6
7
use PHPUnit\Framework\TestCase;
8
use RecursiveCallbackFilterIterator;
9
use RecursiveDirectoryIterator;
10
use RecursiveIteratorIterator;
11
use SplFileInfo;
12
use ZipArchive;
13
use const JSON_PRETTY_PRINT;
14
use const JSON_UNESCAPED_SLASHES;
15
use function array_filter;
16
use function array_map;
17
use function array_walk;
18
use function chdir;
19
use function exec;
20
use function file_get_contents;
21
use function file_put_contents;
22
use function getcwd;
23
use function in_array;
24
use function is_dir;
25
use function iterator_to_array;
26
use function json_decode;
27
use function json_encode;
28
use function mkdir;
29
use function putenv;
30
use function realpath;
31
use function rmdir;
32
use function scandir;
33
use function strlen;
34
use function substr;
35
use function sys_get_temp_dir;
36
use function uniqid;
37
use function unlink;
38
39
/**
40
 * @coversNothing
41
 */
42
class E2EInstallerTest extends TestCase
43
{
44
    /** @var string */
45
    private $tempGlobalComposerHome;
46
47
    /** @var string */
48
    private $tempLocalComposerHome;
49
50
    /** @var string */
51
    private $tempArtifact;
52
53
    public function setUp() : void
54
    {
55
        $this->tempGlobalComposerHome = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/global';
56
        $this->tempLocalComposerHome  = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/local';
57
        $this->tempArtifact           = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/artifacts';
58
        mkdir($this->tempGlobalComposerHome, 0700, true);
59
        mkdir($this->tempLocalComposerHome, 0700, true);
60
        mkdir($this->tempArtifact, 0700, true);
61
62
        putenv('COMPOSER_HOME=' . $this->tempGlobalComposerHome);
63
    }
64
65
    public function tearDown() : void
66
    {
67
        $this->rmDir($this->tempGlobalComposerHome);
68
        $this->rmDir($this->tempLocalComposerHome);
69
        $this->rmDir($this->tempArtifact);
70
71
        putenv('COMPOSER_HOME');
72
    }
73
74
    public function testGloballyInstalledPluginDoesNotGenerateVersionsForLocalProject() : void
75
    {
76
        $this->createPackageVersionsArtifact();
77
78
        $this->writeComposerJsonFile(
79
            [
80
                'name'         => 'package-versions/e2e-global',
81
                'require'      => ['ocramius/package-versions' => '1.0.0'],
82
                'repositories' => [
83
                    ['packagist' => false],
84
                    [
85
                        'type' => 'artifact',
86
                        'url' => $this->tempArtifact,
87
                    ],
88
                ],
89
            ],
90
            $this->tempGlobalComposerHome
91
        );
92
93
        $this->execComposerInDir('global update', $this->tempGlobalComposerHome);
94
95
        $this->createArtifact();
96
        $this->writeComposerJsonFile(
97
            [
98
                'name'         => 'package-versions/e2e-local',
99
                'require'      => ['test/package' => '2.0.0'],
100
                'repositories' => [
101
                    ['packagist' => false],
102
                    [
103
                        'type' => 'artifact',
104
                        'url' => $this->tempArtifact,
105
                    ],
106
                ],
107
            ],
108
            $this->tempLocalComposerHome
109
        );
110
111
        $this->execComposerInDir('update', $this->tempLocalComposerHome);
112
        $this->assertFileNotExists(
113
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
114
        );
115
    }
116
117
    public function testRemovingPluginDoesNotAttemptToGenerateVersions() : void
118
    {
119
        $this->createPackageVersionsArtifact();
120
        $this->createArtifact();
121
122
        $this->writeComposerJsonFile(
123
            [
124
                'name'         => 'package-versions/e2e-local',
125
                'require'      => [
126
                    'test/package' => '2.0.0',
127
                    'ocramius/package-versions' => '1.0.0',
128
                ],
129
                'repositories' => [
130
                    ['packagist' => false],
131
                    [
132
                        'type' => 'artifact',
133
                        'url' => $this->tempArtifact,
134
                    ],
135
                ],
136
            ],
137
            $this->tempLocalComposerHome
138
        );
139
140
        $this->execComposerInDir('update', $this->tempLocalComposerHome);
141
        $this->assertFileExists(
142
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
143
        );
144
145
        $this->execComposerInDir('remove ocramius/package-versions', $this->tempLocalComposerHome);
146
147
        $this->assertFileNotExists(
148
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
149
        );
150
    }
151
152
    /**
153
     * @group #41
154
     * @group #46
155
     */
156
    public function testRemovingPluginWithNoDevDoesNotAttemptToGenerateVersions() : void
157
    {
158
        $this->createPackageVersionsArtifact();
159
        $this->createArtifact();
160
161
        $this->writeComposerJsonFile(
162
            [
163
                'name'         => 'package-versions/e2e-local',
164
                'require-dev'      => ['ocramius/package-versions' => '1.0.0'],
165
                'repositories' => [
166
                    ['packagist' => false],
167
                    [
168
                        'type' => 'artifact',
169
                        'url' => $this->tempArtifact,
170
                    ],
171
                ],
172
            ],
173
            $this->tempLocalComposerHome
174
        );
175
176
        $this->execComposerInDir('update', $this->tempLocalComposerHome);
177
        $this->assertFileExists(
178
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
179
        );
180
181
        $this->execComposerInDir('install --no-dev', $this->tempLocalComposerHome);
182
183
        $this->assertFileNotExists(
184
            $this->tempLocalComposerHome . '/vendor/ocramius/package-versions/src/PackageVersions/Versions.php'
185
        );
186
    }
187
188
    private function createPackageVersionsArtifact() : void
189
    {
190
        $zip = new ZipArchive();
191
192
        $zip->open($this->tempArtifact . '/ocramius-package-versions-1.0.0.zip', ZipArchive::CREATE);
193
194
        $files = array_filter(
195
            iterator_to_array(new RecursiveIteratorIterator(
196
                new RecursiveCallbackFilterIterator(
197
                    new RecursiveDirectoryIterator(realpath(__DIR__ . '/../../'), RecursiveDirectoryIterator::SKIP_DOTS),
198
                    static function (SplFileInfo $file, $key, RecursiveDirectoryIterator $iterator) {
199
                        return $iterator->getSubPathname()[0]  !== '.' && $iterator->getSubPathname() !== 'vendor';
200
                    }
201
                ),
202
                RecursiveIteratorIterator::LEAVES_ONLY
203
            )),
204
            static function (SplFileInfo $file) {
205
                return ! $file->isDir();
206
            }
207
        );
208
209
        array_walk(
210
            $files,
211
            static function (SplFileInfo $file) use ($zip) {
212
                if ($file->getFilename() === 'composer.json') {
213
                    $contents            = json_decode(file_get_contents($file->getRealPath()), true);
214
                    $contents['version'] = '1.0.0';
215
216
                    return $zip->addFromString('composer.json', json_encode($contents));
217
                }
218
219
                $zip->addFile(
220
                    $file->getRealPath(),
221
                    substr($file->getRealPath(), strlen(realpath(__DIR__ . '/../../')) + 1)
222
                );
223
            }
224
        );
225
226
        $zip->close();
227
    }
228
229
    private function createArtifact() : void
230
    {
231
        $zip = new ZipArchive();
232
233
        $zip->open($this->tempArtifact . '/test-package-2.0.0.zip', ZipArchive::CREATE);
234
        $zip->addFromString(
235
            'composer.json',
236
            json_encode(
237
                [
238
                    'name'    => 'test/package',
239
                    'version' => '2.0.0',
240
                ],
241
                JSON_PRETTY_PRINT
242
            )
243
        );
244
        $zip->close();
245
    }
246
247
    /**
248
     * @param mixed[] $config
249
     */
250
    private function writeComposerJsonFile(array $config, string $directory) : void
251
    {
252
        file_put_contents(
253
            $directory . '/composer.json',
254
            json_encode($config, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
255
        );
256
    }
257
258
    /**
259
     * @return mixed[]
260
     */
261
    private function execComposerInDir(string $command, string $dir) : array
262
    {
263
        $currentDir = getcwd();
264
        chdir($dir);
265
        exec(__DIR__ . '/../../vendor/bin/composer ' . $command . ' 2> /dev/null', $output, $exitCode);
266
        $this->assertEquals(0, $exitCode);
267
        chdir($currentDir);
268
        return $output;
269
    }
270
271
    private function rmDir(string $directory) : void
272
    {
273
        if (! is_dir($directory)) {
274
            unlink($directory);
275
276
            return;
277
        }
278
279
        array_map(
280
            function ($item) use ($directory) : void {
281
                $this->rmDir($directory . '/' . $item);
282
            },
283
            array_filter(
284
                scandir($directory),
285
                static function (string $dirItem) {
286
                    return ! in_array($dirItem, ['.', '..'], true);
287
                }
288
            )
289
        );
290
291
        rmdir($directory);
292
    }
293
}
294