Completed
Push — master ( 1b348d...0e0888 )
by Jaap
08:01
created

TraitDescriptorTest::provideMagicProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of phpDocumentor.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @link http://phpdoc.org
12
 */
13
14
namespace phpDocumentor\Descriptor;
15
16
use Mockery as m;
17
use Mockery\Adapter\Phpunit\MockeryTestCase;
18
use phpDocumentor\Descriptor\Tag\MethodDescriptor as TagMethodDescriptor;
19
use phpDocumentor\Descriptor\Tag\PropertyDescriptor as TagPropertyDescriptor;
20
use phpDocumentor\Reflection\Fqsen;
21
use phpDocumentor\Reflection\Type;
22
use phpDocumentor\Reflection\Types\Mixed_;
23
24
/**
25
 * Tests the functionality for the TraitDescriptor class.
26
 *
27
 * @coversDefaultClass \phpDocumentor\Descriptor\TraitDescriptor
28
 */
29
final class TraitDescriptorTest extends MockeryTestCase
30
{
31
    /** @var TraitDescriptor $fixture */
32
    private $fixture;
33
34
    /**
35
     * Creates a new (empty) fixture object.
36
     */
37
    protected function setUp() : void
38
    {
39
        $this->fixture = new TraitDescriptor();
40
        $this->fixture->setFullyQualifiedStructuralElementName(new Fqsen('\My\Trait'));
41
    }
42
43
    /**
44
     * @covers ::setProperties
45
     * @covers ::getProperties
46
     */
47
    public function testSettingAndGettingProperties() : void
48
    {
49
        $this->assertInstanceOf(Collection::class, $this->fixture->getProperties());
50
51
        $collection = new Collection();
52
53
        $this->fixture->setProperties($collection);
54
55
        $this->assertSame($collection, $this->fixture->getProperties());
56
    }
57
58
    /**
59
     * @covers ::setMethods
60
     * @covers ::getMethods
61
     */
62
    public function testSettingAndGettingMethods() : void
63
    {
64
        $this->assertInstanceOf(Collection::class, $this->fixture->getMethods());
65
66
        $collection = new Collection();
67
68
        $this->fixture->setMethods($collection);
69
70
        $this->assertSame($collection, $this->fixture->getMethods());
71
    }
72
73
    /**
74
     * @covers ::getInheritedMethods
75
     */
76
    public function testGetInheritedMethods() : void
77
    {
78
        $this->assertInstanceOf(Collection::class, $this->fixture->getInheritedMethods());
79
80
        $collection = $this->fixture->getInheritedMethods();
81
82
        $this->assertEquals(0, $collection->count());
83
    }
84
85
    /**
86
     * @covers ::getMagicMethods
87
     */
88
    public function testMagicMethodsReturnsEmptyCollectionWhenNoTags() : void
89
    {
90
        $this->assertInstanceOf(Collection::class, $this->fixture->getMagicMethods());
91
92
        $collection = $this->fixture->getMagicMethods();
93
94
        $this->assertEquals(0, $collection->count());
95
    }
96
97
    /**
98
     * @covers ::getMagicMethods
99
     * @dataProvider provideMagicMethodProperties
100
     */
101
    public function testMagicMethodsReturnsExpectedCollectionWithTags(bool $isStatic) : void
102
    {
103
        $mockMethodDescriptor = m::mock(TagMethodDescriptor::class);
104
        $mockMethodDescriptor->shouldReceive('getMethodName')->andReturn('Sample');
0 ignored issues
show
Bug introduced by
The method andReturn does only exist in Mockery\ExpectationInterface, but not in Mockery\HigherOrderMessage.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
105
        $mockMethodDescriptor->shouldReceive('isStatic')->andReturn($isStatic);
106
        $mockMethodDescriptor->shouldReceive('getDescription')->andReturn('Sample description');
107
108
        $methodCollection = new Collection([$mockMethodDescriptor]);
0 ignored issues
show
Documentation introduced by
array($mockMethodDescriptor) is of type array<integer,object<Moc...LegacyMockInterface>"}>, but the function expects a array<integer,object<phpDocumentor\Descriptor\T>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
109
        $this->fixture->getTags()->set('method', $methodCollection);
0 ignored issues
show
Documentation introduced by
$methodCollection is of type object<phpDocumentor\Descriptor\Collection>, but the function expects a object<phpDocumentor\Descriptor\T>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
110
111
        $magicMethodsCollection = $this->fixture->getMagicMethods();
112
        $this->assertInstanceOf(Collection::class, $magicMethodsCollection);
113
        $this->assertSame(1, $magicMethodsCollection->count());
114
        $this->assertSame('Sample', $magicMethodsCollection[0]->getName());
115
        $this->assertSame('Sample description', $magicMethodsCollection[0]->getDescription());
116
        $this->assertSame($isStatic, $magicMethodsCollection[0]->isStatic());
117
        $this->assertSame($this->fixture, $magicMethodsCollection[0]->getParent());
118
    }
119
120
    /**
121
     * Provider to test different properties for a trait magic method
122
     * (provides isStatic)
123
     *
124
     * @return bool[][]
125
     */
126
    public function provideMagicMethodProperties() : array
127
    {
128
        return [
129
            // Instance magic method (default)
130
            [false],
131
            // Static magic method
132
            [true],
133
        ];
134
    }
135
136
    /**
137
     * @covers ::getInheritedProperties
138
     */
139
    public function testGetInheritedProperties() : void
140
    {
141
        $this->assertInstanceOf(Collection::class, $this->fixture->getInheritedProperties());
142
143
        $collection = $this->fixture->getInheritedProperties();
144
145
        $this->assertEquals(0, $collection->count());
146
    }
147
148
    /**
149
     * @covers ::getMagicProperties
150
     */
151
    public function testMagicPropertiesReturnsEmptyCollectionWhenNoTags() : void
152
    {
153
        $this->assertInstanceOf(Collection::class, $this->fixture->getMagicProperties());
154
155
        $collection = $this->fixture->getMagicProperties();
156
157
        $this->assertEquals(0, $collection->count());
158
    }
159
160
    /**
161
     * @covers ::getMagicProperties
162
     * @dataProvider provideMagicProperties
163
     */
164
    public function testMagicPropertiesReturnsExpectedCollectionWithTags(
165
        string $name,
166
        string $description,
167
        Type $type
168
    ) : void {
169
        $mockTagPropertyDescriptor = m::mock(TagPropertyDescriptor::class);
170
        $mockTagPropertyDescriptor->shouldReceive('getVariableName')->andReturn($name);
0 ignored issues
show
Bug introduced by
The method andReturn does only exist in Mockery\ExpectationInterface, but not in Mockery\HigherOrderMessage.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
171
        $mockTagPropertyDescriptor->shouldReceive('getDescription')->andReturn($description);
172
        $mockTagPropertyDescriptor->shouldReceive('getType')->andReturn($type);
173
174
        $propertyCollection = new Collection([$mockTagPropertyDescriptor]);
0 ignored issues
show
Documentation introduced by
array($mockTagPropertyDescriptor) is of type array<integer,object<Moc...LegacyMockInterface>"}>, but the function expects a array<integer,object<phpDocumentor\Descriptor\T>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
175
        $this->fixture->getTags()->set('property', $propertyCollection);
0 ignored issues
show
Documentation introduced by
$propertyCollection is of type object<phpDocumentor\Descriptor\Collection>, but the function expects a object<phpDocumentor\Descriptor\T>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
177
        $this->assertInstanceOf(Collection::class, $this->fixture->getMagicProperties());
178
179
        $magicPropertiesCollection = $this->fixture->getMagicProperties();
180
        $this->assertSame(1, $magicPropertiesCollection->count());
181
        $this->assertSame($name, $magicPropertiesCollection[0]->getName());
182
        $this->assertSame($description, $magicPropertiesCollection[0]->getDescription());
183
        $this->assertEquals($type, $magicPropertiesCollection[0]->getType());
184
        $this->assertSame($this->fixture, $magicPropertiesCollection[0]->getParent());
185
    }
186
187
    /**
188
     * @return array<string, mixed[]>
0 ignored issues
show
Documentation introduced by
The doc-type array<string, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
189
     */
190
    public function provideMagicProperties() : array
191
    {
192
        return [
193
            'normal sample' => [
194
                'name' => 'Sample',
195
                'description' => 'Sample Description',
196
                'type' => new Mixed_(),
197
            ],
198
            'without name' => [
199
                'name' => '',
200
                'description' => 'Sample Description',
201
                'type' => new Mixed_(),
202
            ],
203
        ];
204
    }
205
206
    /**
207
     * @covers ::setPackage
208
     */
209
    public function testSettingAndGettingPackage() : void
210
    {
211
        $package = new PackageDescriptor();
212
        $mockPropertyDescriptor = m::mock(PropertyDescriptor::class);
213
        $mockPropertyDescriptor->shouldReceive('setPackage')->with($package);
214
215
        $mockMethodDescriptor = m::mock(MethodDescriptor::class);
216
        $mockMethodDescriptor->shouldReceive('setPackage')->with($package);
217
218
        $propertyCollection = new Collection([$mockPropertyDescriptor]);
0 ignored issues
show
Documentation introduced by
array($mockPropertyDescriptor) is of type array<integer,object<Moc...LegacyMockInterface>"}>, but the function expects a array<integer,object<phpDocumentor\Descriptor\T>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
219
        $methodCollection = new Collection([$mockMethodDescriptor]);
0 ignored issues
show
Documentation introduced by
array($mockMethodDescriptor) is of type array<integer,object<Moc...LegacyMockInterface>"}>, but the function expects a array<integer,object<phpDocumentor\Descriptor\T>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
220
        $this->fixture->setProperties($propertyCollection);
221
        $this->fixture->setMethods($methodCollection);
222
223
        $this->fixture->setPackage($package);
224
225
        $this->assertSame($package, $this->fixture->getPackage());
226
    }
227
228
    /**
229
     * @covers ::getUsedTraits
230
     * @covers ::setUsedTraits
231
     */
232
    public function testSettingAndGettingUsedTraits() : void
233
    {
234
        $this->assertInstanceOf(Collection::class, $this->fixture->getUsedTraits());
235
236
        $usedTraitsCollection = new Collection();
237
        $this->fixture->setUsedTraits($usedTraitsCollection);
238
239
        $this->assertSame($usedTraitsCollection, $this->fixture->getUsedTraits());
240
    }
241
}
242