ComposerJsonTest::parseComposerFile()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2020 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Tests;
15
16
use DirectoryIterator;
17
use PHPUnit\Framework\TestCase;
18
use Traversable;
19
20
/**
21
 * @internal
22
 */
23
class ComposerJsonTest extends TestCase
24
{
25
    private const SRC_DIR = __DIR__.'/../src';
26
27
    /**
28
     * @test
29
     */
30
    public function packageDependenciesEqualRootDependencies(): void
31
    {
32
        $usedDependencies = ['symfony/symfony']; // Some builds add this to composer.json
33
        $rootDependencies = $this->getComposerDependencies(__DIR__.'/../composer.json');
34
35
        foreach ($this->listSubPackages() as $package) {
36
            $packageDependencies = $this->getComposerDependencies($package.'/composer.json');
37
            foreach ($packageDependencies as $dependency => $version) {
38
                // Skip oauth2-framework/* dependencies
39
                if (0 === mb_strpos($dependency, 'oauth2-framework/')) {
40
                    continue;
41
                }
42
43
                $message = sprintf('Dependency "%s" from package "%s" is not defined in root composer.json', $dependency, $package);
44
                static::assertArrayHasKey($dependency, $rootDependencies, $message);
45
46
                $message = sprintf('Dependency "%s:%s" from package "%s" requires a different version in the root composer.json', $dependency, $version, $package);
47
                static::assertEquals($version, $rootDependencies[$dependency], $message);
48
49
                $usedDependencies[] = $dependency;
50
            }
51
        }
52
53
        $unusedDependencies = array_diff(array_keys($rootDependencies), array_unique($usedDependencies));
54
        $message = sprintf('Dependencies declared in root composer.json, which are not declared in any sub-package: %s', implode(', ', $unusedDependencies));
55
        static::assertCount(0, $unusedDependencies, $message);
56
    }
57
58
    /**
59
     * @test
60
     */
61
    public function rootReplacesSubPackages(): void
62
    {
63
        $rootReplaces = $this->getComposerReplaces(__DIR__.'/../composer.json');
64
        foreach ($this->listSubPackages() as $package) {
65
            $packageName = $this->getComposerPackageName($package.'/composer.json');
66
            $message = sprintf('Root composer.json must replace the sub-packages "%s"', $packageName);
67
            static::assertArrayHasKey($packageName, $rootReplaces, $message);
68
        }
69
    }
70
71
    private function listSubPackages(?string $path = self::SRC_DIR): Traversable
72
    {
73
        foreach (new DirectoryIterator($path) as $dirInfo) {
74
            if ($dirInfo->getFilename() === 'OpenIdConnect') {
75
                continue;
76
            }
77
            if ($dirInfo->isDir() && !$dirInfo->isDot()) {
78
                if ($dirInfo->getFilename() === 'Component') {
79
                    yield from $this->listSubPackages($dirInfo->getRealPath());
80
                    continue;
81
                }
82
                yield $dirInfo->getRealPath();
83
            }
84
        }
85
    }
86
87
    private function getComposerDependencies(string $composerFilePath): array
88
    {
89
        return $this->parseComposerFile($composerFilePath)['require'];
90
    }
91
92
    private function getComposerPackageName(string $composerFilePath): string
93
    {
94
        return $this->parseComposerFile($composerFilePath)['name'];
95
    }
96
97
    private function getComposerReplaces(string $composerFilePath): array
98
    {
99
        return $this->parseComposerFile($composerFilePath)['replace'];
100
    }
101
102
    private function parseComposerFile(string $composerFilePath): array
103
    {
104
        return json_decode(file_get_contents($composerFilePath), true);
105
    }
106
}
107