Completed
Pull Request — master (#15)
by Marco
03:10
created

InstallerTest   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 504
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 9
Bugs 0 Features 0
Metric Value
wmc 12
lcom 1
cbo 6
dl 0
loc 504
rs 10
c 9
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 11 1
A testActivate() 0 6 1
A testGetSubscribedEvents() 0 16 2
B testDumpVersionsClass() 0 111 1
B testDumpVersionsClassNoDev() 0 101 1
B testDumpVersionsWithoutPackageSourceDetails() 0 98 1
A testDumpsVersionsClassToSpecificLocation() 0 49 2
B rootPackageProvider() 0 40 1
A rmDir() 0 20 2
1
<?php
2
3
namespace PackageVersionsTest;
4
5
use Composer\Autoload\AutoloadGenerator;
6
use Composer\Composer;
7
use Composer\Config;
8
use Composer\EventDispatcher\EventDispatcher;
9
use Composer\Installer\InstallationManager;
10
use Composer\IO\IOInterface;
11
use Composer\Package\Locker;
12
use Composer\Package\RootAliasPackage;
13
use Composer\Package\RootPackage;
14
use Composer\Package\RootPackageInterface;
15
use Composer\Repository\InstalledRepositoryInterface;
16
use Composer\Repository\RepositoryManager;
17
use Composer\Script\Event;
18
use PackageVersions\Installer;
19
use PHPUnit_Framework_TestCase;
20
21
/**
22
 * @covers \PackageVersions\Installer
23
 */
24
final class InstallerTest extends PHPUnit_Framework_TestCase
25
{
26
    /**
27
     * @var Composer|\PHPUnit_Framework_MockObject_MockObject
28
     */
29
    private $composer;
30
31
    /**
32
     * @var EventDispatcher|\PHPUnit_Framework_MockObject_MockObject
33
     */
34
    private $eventDispatcher;
35
36
    /**
37
     * @var IOInterface|\PHPUnit_Framework_MockObject_MockObject
38
     */
39
    private $io;
40
41
    /**
42
     * @var Installer
43
     */
44
    private $installer;
45
46
    /**
47
     * {@inheritDoc}
48
     */
49
    protected function setUp()
50
    {
51
        parent::setUp();
52
53
        $this->installer       = new Installer();
54
        $this->io              = $this->getMock(IOInterface::class);
55
        $this->composer        = $this->getMock(Composer::class);
56
        $this->eventDispatcher = $this->getMockBuilder(EventDispatcher::class)->disableOriginalConstructor()->getMock();
57
58
        $this->composer->expects(self::any())->method('getEventDispatcher')->willReturn($this->eventDispatcher);
59
    }
60
61
    public function testActivate()
62
    {
63
        $this->eventDispatcher->expects(self::once())->method('addSubscriber')->with($this->installer);
64
65
        $this->installer->activate($this->composer, $this->io);
66
    }
67
68
    public function testGetSubscribedEvents()
69
    {
70
        $events = Installer::getSubscribedEvents();
71
72
        self::assertSame(
73
            [
74
                'post-install-cmd' => 'dumpVersionsClass',
75
                'post-update-cmd'  => 'dumpVersionsClass',
76
            ],
77
            $events
78
        );
79
80
        foreach ($events as $callback) {
81
            self::assertInternalType('callable', [$this->installer, $callback]);
82
        }
83
    }
84
85
    public function testDumpVersionsClass()
86
    {
87
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
88
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
89
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
90
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
91
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
92
        $package           = $this->getMock(RootPackageInterface::class);
93
94
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
95
96
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
97
98
        mkdir($expectedPath, 0777, true);
99
100
        $locker
101
            ->expects(self::any())
102
            ->method('getLockData')
103
            ->willReturn([
104
                'packages' => [
105
                    [
106
                        'name'    => 'foo/bar',
107
                        'version' => '1.2.3',
108
                        'source'  => [
109
                            'reference' => 'abc123',
110
                        ],
111
                    ],
112
                    [
113
                        'name'    => 'baz/tab',
114
                        'version' => '4.5.6',
115
                        'source'  => [
116
                            'reference' => 'def456',
117
                        ],
118
                    ],
119
                ],
120
                'packages-dev' => [
121
                    [
122
                        'name'    => 'tar/taz',
123
                        'version' => '7.8.9',
124
                        'source'  => [
125
                            'reference' => 'ghi789',
126
                        ],
127
                    ]
128
                ],
129
            ]);
130
131
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
132
133
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
134
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
135
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
136
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
137
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
138
139
        $package->expects(self::any())->method('getName')->willReturn('root/package');
140
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
141
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
142
143
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
144
145
        Installer::dumpVersionsClass(new Event(
146
            'post-install-cmd',
147
            $this->composer,
148
            $this->io
149
        ));
150
151
        $expectedSource = <<<'PHP'
152
<?php
153
154
namespace PackageVersions;
155
156
/**
157
 * This class is generated by ocramius/package-versions, specifically by
158
 * @see \PackageVersions\Installer
159
 *
160
 * This file is overwritten at every run of `composer install` or `composer update`.
161
 */
162
final class Versions
163
{
164
    const VERSIONS = array (
165
  'foo/bar' => '1.2.3@abc123',
166
  'baz/tab' => '4.5.6@def456',
167
  'tar/taz' => '7.8.9@ghi789',
168
  'root/package' => '1.3.5@aaabbbcccddd',
169
);
170
171
    private function __construct()
172
    {
173
    }
174
175
    /**
176
     * @throws \OutOfBoundsException if a version cannot be located
177
     */
178
    public static function getVersion(string $packageName) : string
179
    {
180
        if (! isset(self::VERSIONS[$packageName])) {
181
            throw new \OutOfBoundsException(
182
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
183
            );
184
        }
185
186
        return self::VERSIONS[$packageName];
187
    }
188
}
189
190
PHP;
191
192
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
193
194
        $this->rmDir($vendorDir);
195
    }
196
197
    public function testDumpVersionsClassNoDev()
198
    {
199
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
200
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
201
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
202
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
203
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
204
        $package           = $this->getMock(RootPackageInterface::class);
205
206
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
207
208
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
209
210
        mkdir($expectedPath, 0777, true);
211
212
        $locker
213
            ->expects(self::any())
214
            ->method('getLockData')
215
            ->willReturn([
216
                'packages' => [
217
                    [
218
                        'name'    => 'foo/bar',
219
                        'version' => '1.2.3',
220
                        'source'  => [
221
                            'reference' => 'abc123',
222
                        ],
223
                    ],
224
                    [
225
                        'name'    => 'baz/tab',
226
                        'version' => '4.5.6',
227
                        'source'  => [
228
                            'reference' => 'def456',
229
                        ],
230
                    ],
231
                ],
232
            ]);
233
234
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
235
236
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
237
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
238
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
239
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
240
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
241
242
        $package->expects(self::any())->method('getName')->willReturn('root/package');
243
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
244
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
245
246
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
247
248
        Installer::dumpVersionsClass(new Event(
249
            'post-install-cmd',
250
            $this->composer,
251
            $this->io
252
        ));
253
254
        $expectedSource = <<<'PHP'
255
<?php
256
257
namespace PackageVersions;
258
259
/**
260
 * This class is generated by ocramius/package-versions, specifically by
261
 * @see \PackageVersions\Installer
262
 *
263
 * This file is overwritten at every run of `composer install` or `composer update`.
264
 */
265
final class Versions
266
{
267
    const VERSIONS = array (
268
  'foo/bar' => '1.2.3@abc123',
269
  'baz/tab' => '4.5.6@def456',
270
  'root/package' => '1.3.5@aaabbbcccddd',
271
);
272
273
    private function __construct()
274
    {
275
    }
276
277
    /**
278
     * @throws \OutOfBoundsException if a version cannot be located
279
     */
280
    public static function getVersion(string $packageName) : string
281
    {
282
        if (! isset(self::VERSIONS[$packageName])) {
283
            throw new \OutOfBoundsException(
284
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
285
            );
286
        }
287
288
        return self::VERSIONS[$packageName];
289
    }
290
}
291
292
PHP;
293
294
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
295
296
        $this->rmDir($vendorDir);
297
    }
298
299
    /**
300
     * @group #12
301
     */
302
    public function testDumpVersionsWithoutPackageSourceDetails()
303
    {
304
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
305
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
306
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
307
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
308
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
309
        $package           = $this->getMock(RootPackageInterface::class);
310
311
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true);
312
313
        $expectedPath = $vendorDir . '/ocramius/package-versions/src/PackageVersions';
314
315
        mkdir($expectedPath, 0777, true);
316
317
        $locker
318
            ->expects(self::any())
319
            ->method('getLockData')
320
            ->willReturn([
321
                'packages' => [
322
                    [
323
                        'name'    => 'foo/bar',
324
                        'version' => '1.2.3',
325
                        'dist'  => [
326
                            'reference' => 'abc123', // version defined in the dist, this time
327
                        ],
328
                    ],
329
                    [
330
                        'name'    => 'baz/tab',
331
                        'version' => '4.5.6', // source missing
332
                    ],
333
                ],
334
            ]);
335
336
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
337
338
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
339
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
340
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
341
        $this->composer->expects(self::any())->method('getPackage')->willReturn($package);
342
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
343
344
        $package->expects(self::any())->method('getName')->willReturn('root/package');
345
        $package->expects(self::any())->method('getVersion')->willReturn('1.3.5');
346
        $package->expects(self::any())->method('getSourceReference')->willReturn('aaabbbcccddd');
347
348
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
349
350
        Installer::dumpVersionsClass(new Event(
351
            'post-install-cmd',
352
            $this->composer,
353
            $this->io
354
        ));
355
356
        $expectedSource = <<<'PHP'
357
<?php
358
359
namespace PackageVersions;
360
361
/**
362
 * This class is generated by ocramius/package-versions, specifically by
363
 * @see \PackageVersions\Installer
364
 *
365
 * This file is overwritten at every run of `composer install` or `composer update`.
366
 */
367
final class Versions
368
{
369
    const VERSIONS = array (
370
  'foo/bar' => '1.2.3@abc123',
371
  'baz/tab' => '4.5.6@',
372
  'root/package' => '1.3.5@aaabbbcccddd',
373
);
374
375
    private function __construct()
376
    {
377
    }
378
379
    /**
380
     * @throws \OutOfBoundsException if a version cannot be located
381
     */
382
    public static function getVersion(string $packageName) : string
383
    {
384
        if (! isset(self::VERSIONS[$packageName])) {
385
            throw new \OutOfBoundsException(
386
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
387
            );
388
        }
389
390
        return self::VERSIONS[$packageName];
391
    }
392
}
393
394
PHP;
395
396
        self::assertSame($expectedSource, file_get_contents($expectedPath . '/Versions.php'));
397
398
        $this->rmDir($vendorDir);
399
    }
400
401
    /**
402
     * @dataProvider rootPackageProvider
403
     *
404
     * @param RootPackageInterface $rootPackage
405
     * @param bool                 $inVendor
406
     */
407
    public function testDumpsVersionsClassToSpecificLocation(RootPackageInterface $rootPackage, bool $inVendor)
408
    {
409
        $config            = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock();
410
        $locker            = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
411
        $repositoryManager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
412
        $installManager    = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock();
413
        $repository        = $this->getMock(InstalledRepositoryInterface::class);
414
415
        $vendorDir = sys_get_temp_dir() . '/' . uniqid('InstallerTest', true) . '/vendor';
416
417
        mkdir($vendorDir, 0777, true);
418
419
        $expectedPath = $inVendor
420
            ? $vendorDir . '/ocramius/package-versions/src/PackageVersions'
421
            : realpath($vendorDir . '/..') . '/src/PackageVersions';
422
423
        mkdir($expectedPath, 0777, true);
424
425
        $locker
426
            ->expects(self::any())
427
            ->method('getLockData')
428
            ->willReturn([
429
                'packages' => [],
430
                'packages-dev' => [],
431
            ]);
432
433
        $repositoryManager->expects(self::any())->method('getLocalRepository')->willReturn($repository);
434
435
        $this->composer->expects(self::any())->method('getConfig')->willReturn($config);
436
        $this->composer->expects(self::any())->method('getLocker')->willReturn($locker);
437
        $this->composer->expects(self::any())->method('getRepositoryManager')->willReturn($repositoryManager);
438
        $this->composer->expects(self::any())->method('getPackage')->willReturn($rootPackage);
439
        $this->composer->expects(self::any())->method('getInstallationManager')->willReturn($installManager);
440
441
        $config->expects(self::any())->method('get')->with('vendor-dir')->willReturn($vendorDir);
442
443
        Installer::dumpVersionsClass(new Event(
444
            'post-install-cmd',
445
            $this->composer,
446
            $this->io
447
        ));
448
449
        self::assertStringMatchesFormat(
450
            '%Aclass Versions%A1.2.3@%A',
451
            file_get_contents($expectedPath . '/Versions.php')
452
        );
453
454
        $this->rmDir($vendorDir);
455
    }
456
457
    /**
458
     * @return bool[][]|RootPackageInterface[][] the root package and whether the versions class is to be generated in
459
     *                                           the vendor dir or not
460
     */
461
    public function rootPackageProvider() : array
462
    {
463
        $baseRootPackage                         = new RootPackage('root/package', '1.2.3', '1.2.3');
464
        $aliasRootPackage                        = new RootAliasPackage($baseRootPackage, '1.2.3', '1.2.3');
465
        $indirectAliasRootPackage                = new RootAliasPackage($aliasRootPackage, '1.2.3', '1.2.3');
466
        $packageVersionsRootPackage              = new RootPackage('ocramius/package-versions', '1.2.3', '1.2.3');
467
        $aliasPackageVersionsRootPackage         = new RootAliasPackage($packageVersionsRootPackage, '1.2.3', '1.2.3');
468
        $indirectAliasPackageVersionsRootPackage = new RootAliasPackage(
469
            $aliasPackageVersionsRootPackage,
470
            '1.2.3',
471
            '1.2.3'
472
        );
473
474
        return [
475
            'root package is not ocramius/package-versions' => [
476
                $baseRootPackage,
477
                true
478
            ],
479
            'alias root package is not ocramius/package-versions' => [
480
                $aliasRootPackage,
481
                true
482
            ],
483
            'indirect alias root package is not ocramius/package-versions' => [
484
                $indirectAliasRootPackage,
485
                true
486
            ],
487
            'root package is ocramius/package-versions' => [
488
                $packageVersionsRootPackage,
489
                false
490
            ],
491
            'alias root package is ocramius/package-versions' => [
492
                $aliasPackageVersionsRootPackage,
493
                false
494
            ],
495
            'indirect alias root package is ocramius/package-versions' => [
496
                $indirectAliasPackageVersionsRootPackage,
497
                false
498
            ],
499
        ];
500
    }
501
502
    /**
503
     * @param string $directory
504
     *
505
     * @return void
506
     */
507
    private function rmDir(string $directory)
508
    {
509
        if (! is_dir($directory)) {
510
            unlink($directory);
511
512
            return;
513
        }
514
515
        array_map(
516
            function ($item) use ($directory) {
517
                $this->rmDir($directory . '/' . $item);
518
            },
519
            array_filter(
520
                scandir($directory),
521
                function (string $dirItem) {
522
                    return ! in_array($dirItem, ['.', '..'], true);
523
                }
524
            )
525
        );
526
    }
527
}
528