Completed
Push — master ( 85853a...5df06c )
by James
20s queued 12s
created

testSkipsReflectingInternalClassAlikeSymbols()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 18
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 22
rs 9.6666
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();
0 ignored issues
show
Bug introduced by
The method setUp() does not exist on PHPUnit\Framework\TestCase. It seems like you code against a sub-type of PHPUnit\Framework\TestCase such as Symfony\Component\Yaml\Tests\InlineTest or SebastianBergmann\Diff\ParserTest or PHP_Token_FunctionTest or SebastianBergmann\Compar...ockObjectComparatorTest or PharIo\Manifest\BundlesElementTest or SebastianBergmann\Diff\O...tBuilderIntegrationTest or PharIo\Manifest\LicenseElementTest or RoaveTest\BackwardCompat...ed\OpenClassChangedTest or ExceptionInSetUpTest or PharIo\Manifest\ManifestTest or SebastianBergmann\GlobalState\BlacklistTest or PHPUnit\Runner\DefaultTestResultCacheTest or RoaveTest\BackwardCompat...tectedMethodChangedTest or PHPUnit\Util\ConfigurationTest or PHPUnit\Framework\TestListenerTest or SebastianBergmann\Diff\U...ertTraitIntegrationTest or BankAccountWithCustomExtensionTest or RoaveTest\BackwardCompat...ipMethodBasedErrorsTest or PHP_Token_IncludeTest or RoaveTest\BackwardCompat...essibleMethodChangeTest or SebastianBergmann\Comparator\DoubleComparatorTest or SebastianBergmann\Compar...\DateTimeComparatorTest or PharIo\Manifest\RequiresElementTest or RoaveTest\BackwardCompat...PropertyBasedErrorsTest or RoaveTest\BackwardCompat...nterfaceBasedErrorsTest or Symfony\Component\Consol...s\Question\QuestionTest or SebastianBergmann\Comparator\ScalarComparatorTest or SebastianBergmann\Comparator\ObjectComparatorTest or PHP_Token_ClassTest or Symfony\Component\Consol...\Helper\ProgressBarTest or PharIo\Manifest\CopyrightElementTest or Symfony\Component\Filesy...ests\FilesystemTestCase or RoaveTest\BackwardCompat...kipTraitBasedErrorsTest or Symfony\Component\Console\Tests\ApplicationTest or PHP_CodeSniffer\Tests\St...s\AbstractSniffUnitTest or PHP_CodeSniffer\Tests\Co...ndExtendedClassNameTest or PHP_CodeSniffer\Tests\Co...GetMethodParametersTest or SebastianBergmann\CodeUnitReverseLookup\WizardTest or PharIo\Manifest\BundledComponentCollectionTest or PHP_CodeSniffer\Tests\Co...entedInterfaceNamesTest or TheSeer\Tokenizer\XMLSerializerTest or PHPUnit\Runner\PhptTestCaseTest or SebastianBergmann\Environment\ConsoleTest or RoaveTest\BackwardCompat...ctedPropertyChangedTest or SebastianBergmann\Type\ObjectTypeTest or RoaveTest\BackwardCompat...lassConstantChangedTest or ExceptionInAssertPreConditionsTest or ExceptionInTearDownTest or RoaveTest\BackwardCompat...d\FinalClassChangedTest or ExceptionInAssertPostConditionsTest or PHPUnit\Framework\TestSuiteTest or TheSeer\Tokenizer\TokenCollectionTest or SebastianBergmann\Object...tor\ObjectReflectorTest or RoaveTest\BackwardCompat...blicPropertyChangedTest or SebastianBergmann\RecursionContext\ContextTest or PHPUnit\SelfTest\Basic\SetUpTest or Symfony\Component\Consol...\Style\SymfonyStyleTest or PharIo\Manifest\ComponentElementTest or Symfony\Component\Consol...ester\CommandTesterTest or PHPUnit\Util\PHP\AbstractPhpProcessTest or SebastianBergmann\Type\IterableTypeTest or SebastianBergmann\Environment\OperatingSystemTest or PharIo\Manifest\LicenseTest or SebastianBergmann\Comparator\TypeComparatorTest or PharIo\Manifest\ExtensionTest or PHPUnit\SelfTest\Basic\SetUpBeforeClassTest or RoaveTest\BackwardCompatibility\CompareClassesTest or SebastianBergmann\CodeCoverage\FilterTest or RoaveTest\BackwardCompat...iblePropertyChangedTest or Humbug\Test\FunctionTest or Symfony\Component\Consol...Output\StreamOutputTest or PharIo\Manifest\ExtElementTest or Symfony\Component\Consol...onsoleSectionOutputTest or GeneratorTest or SebastianBergmann\Compar...\ResourceComparatorTest or ExceptionInTest or RoaveTest\BackwardCompat...FunctionBasedErrorsTest or TemplateMethodsTest or RoaveTest\BackwardCompat...onFromGitRepositoryTest or PharIo\Manifest\AuthorCollectionTest or SebastianBergmann\Comparator\DOMNodeComparatorTest or RoaveTest\BackwardCompat...onDefinitionChangedTest or SebastianBergmann\Exporter\ExporterTest or PharIo\Manifest\RequirementCollectionTest or RoaveTest\BackwardCompat...BackwardsCompatibleTest or PharIo\Manifest\AuthorElementTest or Symfony\Component\Consol...r\ApplicationTesterTest or PHP_CodeSniffer\Tests\Co...GetMemberPropertiesTest or RoaveTest\BackwardCompat...assMapSourceLocatorTest or SebastianBergmann\FileIterator\FactoryTest or PharIo\Manifest\BundledComponentTest or SebastianBergmann\Diff\O...tBuilderIntegrationTest or PharIo\Manifest\AuthorTest or RoaveTest\BackwardCompat...kipClassBasedErrorsTest or PharIo\Manifest\PhpVersionRequirementTest or RoaveE2ETest\BackwardCom...BackwardsCompatibleTest or PHP_CodeSniffer\Tests\Co...GetMethodPropertiesTest or SebastianBergmann\GlobalState\SnapshotTest or Symfony\Component\Console\Tests\TerminalTest or PHP_CodeSniffer\Tests\Co...\FindEndOfStatementTest or PHP_CodeSniffer\Tests\Core\File\IsReferenceTest or PHPUnit\Runner\ResultCacheExtensionTest or TheSeer\Tokenizer\TokenTest or PHPUnit\Util\TestDox\NamePrettifierTest or SebastianBergmann\Comparator\NumericComparatorTest or PHPUnit\Util\TestDox\CliTestDoxPrinterColorTest or PHP_Token_ClosureTest or SebastianBergmann\Diff\LineTest or Symfony\Component\Yaml\Tests\DumperTest or SebastianBergmann\Type\GenericObjectTypeTest or SebastianBergmann\Compar...ctStorageComparatorTest or PharIo\Manifest\LibraryTest or SebastianBergmann\Diff\DifferTest or RoaveTest\BackwardCompat...ConstantBasedErrorsTest or SebastianBergmann\Comparator\ArrayComparatorTest or PhpParser\Builder\InterfaceTest or PharIo\Manifest\CopyrightInformationTest or Symfony\Component\Yaml\T...Command\LintCommandTest or PHPUnit\Util\TestDox\CliTestDoxPrinterTest or SebastianBergmann\Environment\RuntimeTest or RoaveTest\BackwardCompat...rcesViaComposerJsonTest or SebastianBergmann\ObjectEnumerator\EnumeratorTest or SebastianBergmann\Diff\L...stCommonSubsequenceTest or PharIo\Manifest\ContainsElementTest or Issue1374Test or PharIo\Manifest\ApplicationTest or PharIo\Manifest\ExtensionElementTest or BankAccountTest or SebastianBergmann\Type\CallableTypeTest or PharIo\Manifest\PhpElementTest or RoaveTest\BackwardCompat...ndenciesViaComposerTest or SebastianBergmann\Type\NullTypeTest or SebastianBergmann\Type\UnknownTypeTest or PHP_Token_InterfaceTest or RoaveTest\BackwardCompat...lassConstantChangedTest or SebastianBergmann\Compar...ExceptionComparatorTest or SebastianBergmann\Diff\ChunkTest or RoaveTest\BackwardCompat...PublicMethodChangedTest or SebastianBergmann\CodeCoverage\CodeCoverageTest or SebastianBergmann\CodeCoverage\Report\BuilderTest. ( Ignorable by Annotation )

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

43
        parent::/** @scrutinizer ignore-call */ 
44
                setUp();
Loading history...
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 testSkipsReflectingInternalClassAlikeSymbols() : void
186
    {
187
        $this->classBasedComparatorWillNotBeCalled();
188
        $this->interfaceBasedComparatorWillNotBeCalled();
189
        $this->traitBasedComparatorWillNotBeCalled();
190
191
        Assertion::assertChangesEqual(
192
            Changes::empty(),
193
            $this->compareClasses->__invoke(
194
                self::$stringReflectorFactory->__invoke(<<<'PHP'
195
<?php
196
197
/** @internal */
198
class A {}
199
/** @internal */
200
interface B {}
201
/** @internal */
202
trait C {}
203
PHP
204
                ),
205
                self::$stringReflectorFactory->__invoke('<?php '),
206
                self::$stringReflectorFactory->__invoke('<?php ')
207
            )
208
        );
209
    }
210
211
    public function testRemovingAClassCausesABreak() : void
212
    {
213
        $this->classBasedComparatorWillNotBeCalled();
214
        $this->interfaceBasedComparatorWillNotBeCalled();
215
        $this->traitBasedComparatorWillNotBeCalled();
216
217
        Assertion::assertChangesEqual(
218
            Changes::fromList(Change::removed('Class A has been deleted', true)),
219
            $this->compareClasses->__invoke(
220
                self::$stringReflectorFactory->__invoke('<?php class A { private function foo() {} }'),
221
                self::$stringReflectorFactory->__invoke('<?php class A { private function foo() {} }'),
222
                self::$stringReflectorFactory->__invoke('<?php ')
223
            )
224
        );
225
    }
226
227
    private function classBasedComparatorWillBeCalled() : void
228
    {
229
        $this
230
            ->classBasedComparison
231
            ->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

231
            ->/** @scrutinizer ignore-call */ 
232
              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...
Bug introduced by
The method expects() does not exist on PHPUnit\Framework\MockObject\MockObject. ( Ignorable by Annotation )

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

231
            ->/** @scrutinizer ignore-call */ 
232
              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...
Bug introduced by
The method atLeastOnce() does not exist on RoaveTest\BackwardCompatibility\CompareClassesTest. ( Ignorable by Annotation )

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

231
            ->expects(self::/** @scrutinizer ignore-call */ 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...
232
            ->method('__invoke')
233
            ->willReturn(Changes::fromList(Change::changed('class change', true)));
234
    }
235
236
    private function classBasedComparatorWillNotBeCalled() : void
237
    {
238
        $this
239
            ->classBasedComparison
240
            ->expects(self::never())
0 ignored issues
show
Bug introduced by
The method never() does not exist on RoaveTest\BackwardCompatibility\CompareClassesTest. ( Ignorable by Annotation )

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

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

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...
241
            ->method('__invoke');
242
    }
243
244
    private function interfaceBasedComparatorWillBeCalled() : void
245
    {
246
        $this
247
            ->interfaceBasedComparison
248
            ->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

248
            ->/** @scrutinizer ignore-call */ 
249
              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...
249
            ->method('__invoke')
250
            ->willReturn(Changes::fromList(Change::changed('interface change', true)));
251
    }
252
253
    private function interfaceBasedComparatorWillNotBeCalled() : void
254
    {
255
        $this
256
            ->interfaceBasedComparison
257
            ->expects(self::never())
258
            ->method('__invoke');
259
    }
260
261
    private function traitBasedComparatorWillBeCalled() : void
262
    {
263
        $this
264
            ->traitBasedComparison
265
            ->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

265
            ->/** @scrutinizer ignore-call */ 
266
              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...
266
            ->method('__invoke')
267
            ->willReturn(Changes::fromList(Change::changed('trait change', true)));
268
    }
269
270
    private function traitBasedComparatorWillNotBeCalled() : void
271
    {
272
        $this
273
            ->traitBasedComparison
274
            ->expects(self::never())
275
            ->method('__invoke');
276
    }
277
}
278