Passed
Pull Request — master (#108)
by Marco
02:35
created

CompareClassesTest::assertEqualsIgnoringOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RoaveTest\BackwardCompatibility;
6
7
use PHPUnit\Framework\MockObject\MockObject;
8
use PHPUnit\Framework\TestCase;
9
use Roave\BackwardCompatibility\Change;
10
use Roave\BackwardCompatibility\Changes;
11
use Roave\BackwardCompatibility\CompareClasses;
12
use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBased;
13
use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBased;
14
use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBased;
15
16
/**
17
 * @covers \Roave\BackwardCompatibility\CompareClasses
18
 */
19
final class CompareClassesTest extends TestCase
20
{
21
    /** @var StringReflectorFactory */
22
    private static $stringReflectorFactory;
23
24
    /** @var ClassBased|MockObject */
25
    private $classBasedComparison;
26
27
    /** @var InterfaceBased|MockObject */
28
    private $interfaceBasedComparison;
29
30
    /** @var TraitBased|MockObject */
31
    private $traitBasedComparison;
32
33
    /** @var CompareClasses */
34
    private $compareClasses;
35
36
    public static function setUpBeforeClass() : void
37
    {
38
        self::$stringReflectorFactory = new StringReflectorFactory();
39
    }
40
41
    protected function setUp() : void
42
    {
43
        parent::setUp();
44
45
        $this->classBasedComparison     = $this->createMock(ClassBased::class);
46
        $this->interfaceBasedComparison = $this->createMock(InterfaceBased::class);
47
        $this->traitBasedComparison     = $this->createMock(TraitBased::class);
48
        $this->compareClasses           = new CompareClasses(
49
            $this->classBasedComparison,
50
            $this->interfaceBasedComparison,
51
            $this->traitBasedComparison
52
        );
53
    }
54
55
    public function testWillRunSubComparators() : void
56
    {
57
        $this->classBasedComparatorWillBeCalled();
58
        $this->interfaceBasedComparatorWillNotBeCalled();
59
        $this->traitBasedComparatorWillNotBeCalled();
60
61
        Assertion::assertChangesEqual(
62
            Changes::fromList(Change::changed('class change', true)),
63
            $this->compareClasses->__invoke(
64
                self::$stringReflectorFactory->__invoke('<?php class A {}'),
65
                self::$stringReflectorFactory->__invoke(
66
                    <<<'PHP'
67
<?php
68
69
class A {
70
    const A_CONSTANT = 'foo';
71
    public $aProperty;
72
    public function aMethod() {}
73
}
74
PHP
75
                ),
76
                self::$stringReflectorFactory->__invoke(
77
                    <<<'PHP'
78
<?php
79
80
class A {
81
    const A_CONSTANT = 'foo';
82
    public $aProperty;
83
    public function aMethod() {}
84
}
85
PHP
86
                )
87
            )
88
        );
89
    }
90
91
    public function testWillNotRunSubComparatorsIfSymbolsWereDeleted() : void
92
    {
93
        $this->classBasedComparatorWillBeCalled();
94
        $this->interfaceBasedComparatorWillNotBeCalled();
95
        $this->traitBasedComparatorWillNotBeCalled();
96
97
        Assertion::assertChangesEqual(
98
            Changes::fromList(Change::changed('class change', true)),
99
            $this->compareClasses->__invoke(
100
                self::$stringReflectorFactory->__invoke('<?php class A {}'),
101
                self::$stringReflectorFactory->__invoke(
102
                    <<<'PHP'
103
<?php
104
105
class A {
106
    const A_CONSTANT = 'foo';
107
    public $aProperty;
108
    public function aMethod() {}
109
}
110
PHP
111
                ),
112
                self::$stringReflectorFactory->__invoke(
113
                    <<<'PHP'
114
<?php
115
116
class A {}
117
PHP
118
                )
119
            )
120
        );
121
    }
122
123
    public function testWillRunInterfaceComparators() : void
124
    {
125
        $this->classBasedComparatorWillNotBeCalled();
126
        $this->interfaceBasedComparatorWillBeCalled();
127
        $this->traitBasedComparatorWillNotBeCalled();
128
129
        Assertion::assertChangesEqual(
130
            Changes::fromList(Change::changed('interface change', true)),
131
            $this->compareClasses->__invoke(
132
                self::$stringReflectorFactory->__invoke('<?php interface A {}'),
133
                self::$stringReflectorFactory->__invoke('<?php interface A {}'),
134
                self::$stringReflectorFactory->__invoke('<?php interface A {}')
135
            )
136
        );
137
    }
138
139
    public function testWillRunTraitComparators() : void
140
    {
141
        $this->classBasedComparatorWillNotBeCalled();
142
        $this->interfaceBasedComparatorWillNotBeCalled();
143
        $this->traitBasedComparatorWillBeCalled();
144
145
        Assertion::assertChangesEqual(
146
            Changes::fromList(Change::changed('trait change', true)),
147
            $this->compareClasses->__invoke(
148
                self::$stringReflectorFactory->__invoke('<?php trait A {}'),
149
                self::$stringReflectorFactory->__invoke('<?php trait A {}'),
150
                self::$stringReflectorFactory->__invoke('<?php trait A {}')
151
            )
152
        );
153
    }
154
155
    public function testAnonymousClassesAreFilteredOut() : void
156
    {
157
        $this->classBasedComparatorWillNotBeCalled();
158
        $this->interfaceBasedComparatorWillNotBeCalled();
159
        $this->traitBasedComparatorWillNotBeCalled();
160
161
        Assertion::assertChangesEqual(
162
            Changes::empty(),
163
            $this->compareClasses->__invoke(
164
                self::$stringReflectorFactory->__invoke('<?php $x = new class () {};'),
165
                self::$stringReflectorFactory->__invoke('<?php $x = new class () {};'),
166
                self::$stringReflectorFactory->__invoke('<?php $x = new class () {};')
167
            )
168
        );
169
    }
170
171
    public function testSkipsReflectingUndefinedApi() : void
172
    {
173
        $this->classBasedComparatorWillNotBeCalled();
174
175
        Assertion::assertChangesEqual(
176
            Changes::empty(),
177
            $this->compareClasses->__invoke(
178
                self::$stringReflectorFactory->__invoke('<?php '),
179
                self::$stringReflectorFactory->__invoke('<?php class A { private function foo() {} }'),
180
                self::$stringReflectorFactory->__invoke('<?php ')
181
            )
182
        );
183
    }
184
185
    public function testRemovingAClassCausesABreak() : void
186
    {
187
        $this->classBasedComparatorWillNotBeCalled();
188
        $this->interfaceBasedComparatorWillNotBeCalled();
189
        $this->traitBasedComparatorWillNotBeCalled();
190
191
        Assertion::assertChangesEqual(
192
            Changes::fromList(Change::removed('Class A has been deleted', true)),
193
            $this->compareClasses->__invoke(
194
                self::$stringReflectorFactory->__invoke('<?php class A { private function foo() {} }'),
195
                self::$stringReflectorFactory->__invoke('<?php class A { private function foo() {} }'),
196
                self::$stringReflectorFactory->__invoke('<?php ')
197
            )
198
        );
199
    }
200
201
    private function classBasedComparatorWillBeCalled() : void
202
    {
203
        $this
204
            ->classBasedComparison
205
            ->expects(self::atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Roave\BackwardCompatibil...k\ClassBased\ClassBased. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

205
            ->/** @scrutinizer ignore-call */ 
206
              expects(self::atLeastOnce())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
206
            ->method('__invoke')
207
            ->willReturn(Changes::fromList(Change::changed('class change', true)));
208
    }
209
210
    private function classBasedComparatorWillNotBeCalled() : void
211
    {
212
        $this
213
            ->classBasedComparison
214
            ->expects(self::never())
215
            ->method('__invoke');
216
    }
217
218
    private function interfaceBasedComparatorWillBeCalled() : void
219
    {
220
        $this
221
            ->interfaceBasedComparison
222
            ->expects(self::atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Roave\BackwardCompatibil...aceBased\InterfaceBased. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

222
            ->/** @scrutinizer ignore-call */ 
223
              expects(self::atLeastOnce())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
223
            ->method('__invoke')
224
            ->willReturn(Changes::fromList(Change::changed('interface change', true)));
225
    }
226
227
    private function interfaceBasedComparatorWillNotBeCalled() : void
228
    {
229
        $this
230
            ->interfaceBasedComparison
231
            ->expects(self::never())
232
            ->method('__invoke');
233
    }
234
235
    private function traitBasedComparatorWillBeCalled() : void
236
    {
237
        $this
238
            ->traitBasedComparison
239
            ->expects(self::atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Roave\BackwardCompatibil...k\TraitBased\TraitBased. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
            ->/** @scrutinizer ignore-call */ 
240
              expects(self::atLeastOnce())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
240
            ->method('__invoke')
241
            ->willReturn(Changes::fromList(Change::changed('trait change', true)));
242
    }
243
244
    private function traitBasedComparatorWillNotBeCalled() : void
245
    {
246
        $this
247
            ->traitBasedComparison
248
            ->expects(self::never())
249
            ->method('__invoke');
250
    }
251
}
252