SchemaSnapshotContext::compareWithCurrentSchema()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 6
ccs 0
cts 6
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Behat\Context;
12
13
use Behat\Behat\Context\Context;
14
use Behat\Behat\Hook\Scope\BeforeFeatureScope;
15
use Behat\Symfony2Extension\Context\KernelAwareContext;
16
use PHPUnit\Framework\Assert;
17
use PHPUnit\Framework\ExpectationFailedException;
18
use SebastianBergmann\Comparator\ComparisonFailure;
19
use Symfony\Component\HttpKernel\Kernel;
20
use Symfony\Component\HttpKernel\KernelInterface;
21
use Ynlo\GraphQLBundle\Schema\SchemaSnapshot;
22
23
class SchemaSnapshotContext implements Context, KernelAwareContext
24
{
25
    /**
26
     * @var Kernel
27
     */
28
    private $kernel;
29
30
    /**
31
     * @var string
32
     */
33
    private static $featureDir;
34
35
    /**
36
     * @var string
37
     */
38
    private $endpoint;
39
40
    /**
41
     * @var array
42
     */
43
    private $savedSnapshot = [];
44
45
    /**
46
     * @var array
47
     */
48
    private $currentSnapshot = [];
49
50
    /**
51
     * @inheritDoc
52
     */
53
    public function setKernel(KernelInterface $kernel)
54
    {
55
        $this->kernel = $kernel;
0 ignored issues
show
Documentation Bug introduced by
$kernel is of type Symfony\Component\HttpKernel\KernelInterface, but the property $kernel was declared to be of type Symfony\Component\HttpKernel\Kernel. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
56
    }
57
58
    /**
59
     * @BeforeFeature
60
     */
61
    public static function beforeFEature(BeforeFeatureScope $scope)
62
    {
63
        self::$featureDir = (new \SplFileInfo($scope->getFeature()->getFile()))->getPathInfo()->getRealPath();
64
    }
65
66
    /**
67
     * @Given /^previous schema snapshot of "([^"]*)" endpoint$/
68
     */
69
    public function previousSnapshotOfEndpointSchema($endpoint)
70
    {
71
        $this->endpoint = $endpoint;
72
        $file = sprintf('%s/%s.snapshot.json', self::$featureDir, $endpoint);
73
        $this->savedSnapshot = json_decode(file_get_contents($file), true);
74
    }
75
76
    /**
77
     * @When /^compare with current schema$/
78
     */
79
    public function compareWithCurrentSchema()
80
    {
81
        $this->currentSnapshot = $this->kernel
82
            ->getContainer()
83
            ->get(SchemaSnapshot::class)
84
            ->createSnapshot($this->endpoint);
85
    }
86
87
    /**
88
     * @Then /^current schema is compatible with latest snapshot$/
89
     */
90
    public function currentSchemaIsCompatibleWithTheLatestSnapshot()
91
    {
92
        try {
93
            Assert::assertArraySubset($this->savedSnapshot, $this->currentSnapshot);
94
        } catch (ExpectationFailedException $exception) {
95
            $changeSet = $this->arrayRecursiveDiff($this->savedSnapshot, $this->currentSnapshot);
96
            $changeSetString = json_encode($changeSet, JSON_PRETTY_PRINT);
97
            $comparison = new ComparisonFailure($changeSet, [], $changeSetString, '');
98
99
            throw new ExpectationFailedException(
100
                'Your current schema is not compatible with the latest snapshot, some fields, types or arguments has been deleted.',
101
                $comparison
102
            );
103
        }
104
    }
105
106
    /**
107
     * @Given /^current schema is same after latest snapshot$/
108
     */
109
    public function currentSchemaDoesNotExposeMoreDefinitionsThanLatestSnapshot()
110
    {
111
        try {
112
            Assert::assertEquals($this->currentSnapshot, $this->savedSnapshot);
113
        } catch (ExpectationFailedException $exception) {
114
            $current = json_encode($this->savedSnapshot, JSON_PRETTY_PRINT);
115
            $snapshot = json_encode($this->currentSnapshot, JSON_PRETTY_PRINT);
116
            $comparison = new ComparisonFailure($this->savedSnapshot, $this->currentSnapshot, $current, $snapshot);
117
118
            throw new ExpectationFailedException('Your current schema has ben changed after latest snapshot.', $comparison);
119
        }
120
    }
121
122
    private function arrayRecursiveDiff($aArray1, $aArray2)
123
    {
124
        $aReturn = [];
125
126
        foreach ($aArray1 as $mKey => $mValue) {
127
            if (array_key_exists($mKey, $aArray2)) {
128
                if (is_array($mValue)) {
129
                    $aRecursiveDiff = $this->arrayRecursiveDiff($mValue, $aArray2[$mKey]);
130
                    if (count($aRecursiveDiff)) {
131
                        $aReturn[$mKey] = $aRecursiveDiff;
132
                    }
133
                } else {
134
                    if ($mValue != $aArray2[$mKey]) {
135
                        $aReturn[$mKey] = $mValue;
136
                    }
137
                }
138
            } else {
139
                $aReturn[$mKey] = $mValue;
140
            }
141
        }
142
143
        return $aReturn;
144
    }
145
}
146