Completed
Push — develop ( 80740b...61b5c3 )
by Mike
10:20
created

Transformer/Writer/Xml/DocBlockConverterTest.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Plugin\Core\Transformer\Writer\Xml;
13
14
use Mockery as m;
15
use phpDocumentor\Descriptor\DescriptorAbstract;
16
use phpDocumentor\Transformer\Router\RouterAbstract;
17
18
/**
19
 * Test class for \phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter.
20
 */
21
class DocBlockConverterTest extends \Mockery\Adapter\Phpunit\MockeryTestCase
22
{
23
    /** @var DocBlockConverter */
24
    protected $fixture;
25
26
    /** @var m\MockInterface|RouterAbstract */
27
    protected $routerMock;
28
29
    /** @var m\MockInterface|TagConverter */
30
    protected $tagConverterMock;
31
32
    /**
33
     * Sets up the fixture with mocked dependencies.
34
     */
35
    protected function setUp()
36
    {
37
        $this->tagConverterMock = $this->givenATagConverter();
38
        $this->routerMock = $this->givenARouter();
39
        $this->fixture = new DocBlockConverter($this->tagConverterMock, $this->routerMock);
40
    }
41
42
    /**
43
     * Tests whether the XML Element representing a DocBlock is properly created.
44
     *
45
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::__construct
46
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::convert
47
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addSummary
48
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addDescription
49
     */
50
    public function testIfXmlElementForDocBlockIsCreated()
51
    {
52
        // Arrange
53
        $descriptor = $this->givenADescriptorWithSummaryDescriptionAndTags('summary', 'description', []);
54
55
        // Act
56
        $convertedElement = $this->fixture->convert($this->prepareParentXMLElement(), $descriptor);
0 ignored issues
show
It seems like $descriptor defined by $this->givenADescriptorW...'description', array()) on line 53 can also be of type object<Mockery\MockInterface>; however, phpDocumentor\Plugin\Cor...ockConverter::convert() does only seem to accept object<phpDocumentor\Des...tor\DescriptorAbstract>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
57
58
        // Assert
59
        $this->assertSame('100', $convertedElement->getAttribute('line'));
60
        $this->assertSame('summary', $convertedElement->getElementsByTagName('description')->item(0)->nodeValue);
61
        $this->assertSame(
62
            'description',
63
            $convertedElement->getElementsByTagName('long-description')->item(0)->nodeValue
64
        );
65
        $this->assertSame(0, $convertedElement->getElementsByTagName('tag')->length);
66
    }
67
68
    /**
69
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::convert
70
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addTags
71
     */
72
    public function testParentPackageIsSetByDocBlocksPackage()
73
    {
74
        // Arrange
75
        $parent = $this->prepareParentXMLElement();
76
        $descriptor = $this->givenADescriptorWithSummaryDescriptionAndTags('summary', 'description', [null]);
77
78
        // Act
79
        $this->fixture->convert($parent, $descriptor);
0 ignored issues
show
It seems like $descriptor defined by $this->givenADescriptorW...cription', array(null)) on line 76 can also be of type object<Mockery\MockInterface>; however, phpDocumentor\Plugin\Cor...ockConverter::convert() does only seem to accept object<phpDocumentor\Des...tor\DescriptorAbstract>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
80
81
        // Assert
82
        $this->assertSame('This\Is\A\Package', $parent->getAttribute('package'));
83
    }
84
85
    /**
86
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::convert
87
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addTags
88
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addInheritedFromTag
89
     */
90
    public function testConvertTagsOntoDocBlock()
91
    {
92
        // Arrange
93
        $parent = $this->prepareParentXMLElement();
94
        $tag = m::mock('phpDocumentor\Descriptor\TagDescriptor');
95
        $this->tagConverterMock->shouldReceive('convert')->with(m::type('DOMElement'), $tag);
0 ignored issues
show
The method shouldReceive does only exist in Mockery\MockInterface, but not in phpDocumentor\Plugin\Cor...Writer\Xml\TagConverter.

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...
96
97
        $descriptor = $this->givenADescriptorWithSummaryDescriptionAndTags(
98
            'summary',
99
            'description',
100
            [[$tag]]
101
        );
102
103
        // Act
104
        $this->fixture->convert($parent, $descriptor);
0 ignored issues
show
It seems like $descriptor defined by $this->givenADescriptorW...n', array(array($tag))) on line 97 can also be of type object<Mockery\MockInterface>; however, phpDocumentor\Plugin\Cor...ockConverter::convert() does only seem to accept object<phpDocumentor\Des...tor\DescriptorAbstract>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
105
106
        // Assert
107
        $this->assertTrue(true);
108
    }
109
110
    /**
111
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::convert
112
     * @covers phpDocumentor\Plugin\Core\Transformer\Writer\Xml\DocBlockConverter::addInheritedFromTag
113
     */
114
    public function testAddInheritedFromTag()
115
    {
116
        // Arrange
117
        $fqcn = 'fqcn';
118
        $url = 'url';
119
        $parent = $this->prepareParentXMLElement();
120
121
        $parentDescriptor = $this->givenADescriptor()
122
            ->shouldReceive('getFullyQualifiedStructuralElementName')
123
            ->andReturn($fqcn)
124
            ->getMock();
125
126
        $descriptor = $this->givenADescriptorWithSummaryDescriptionAndTags('summary', 'description', [])
127
            ->shouldReceive('getInheritedElement')->andReturn($parentDescriptor)
128
            ->getMock();
129
130
        $ruleMock = $this->givenARuleThatGeneratesTheGivenUrl($url);
131
        $this->routerMock->shouldReceive('match')->with($parentDescriptor)->andReturn($ruleMock);
132
133
        // Act
134
        $this->fixture->convert($parent, $descriptor);
135
136
        // Assert
137
        $this->assertSame('inherited_from', $parent->getElementsByTagName('tag')->item(0)->getAttribute('name'));
138
        $this->assertSame($fqcn, $parent->getElementsByTagName('tag')->item(0)->getAttribute('refers'));
139
        $this->assertSame($fqcn, $parent->getElementsByTagName('tag')->item(0)->getAttribute('description'));
140
        $this->assertSame($url, $parent->getElementsByTagName('tag')->item(0)->getAttribute('link'));
141
    }
142
143
    /**
144
     * Creates an XML Element that can serve as parent.
145
     *
146
     * @return \DOMElement
147
     */
148
    protected function prepareParentXMLElement()
149
    {
150
        $document = new \DOMDocument();
151
        $parent = new \DOMElement('function');
152
        $document->appendChild($parent);
153
154
        return $parent;
155
    }
156
157
    /**
158
     * Creates a mock for the ArgumentDescriptor class.
159
     *
160
     * @return m\MockInterface|DescriptorAbstract
161
     */
162
    protected function givenADescriptor()
163
    {
164
        $tag = m::mock('phpDocumentor\\Descriptor\\DescriptorAbstract');
165
        $tag->shouldReceive('getLine')->andReturn(100);
166
        $tag->shouldReceive('getPackage')->andReturn('This\Is\A\Package');
167
        $tag->shouldIgnoreMissing();
168
169
        return $tag;
170
    }
171
172
    /**
173
     * Returns a tag converter mock.
174
     *
175
     * @return m\MockInterface|TagConverter
176
     */
177
    protected function givenATagConverter()
178
    {
179
        return m::mock('phpDocumentor\Plugin\Core\Transformer\Writer\Xml\TagConverter');
180
    }
181
182
    /**
183
     * Returns a router mock.
184
     *
185
     * @return m\MockInterface|RouterAbstract
186
     */
187
    protected function givenARouter()
188
    {
189
        return m::mock('phpDocumentor\Transformer\Router\RouterAbstract');
190
    }
191
192
    /**
193
     * Returns a mock for a descriptor, including summary, description and tags.
194
     *
195
     * @param string $summary
196
     * @param string $description
197
     * @param array  $tags
198
     *
199
     * @return m\MockInterface|DescriptorAbstract
200
     */
201
    protected function givenADescriptorWithSummaryDescriptionAndTags($summary, $description, $tags)
202
    {
203
        $descriptor = $this->givenADescriptor();
204
        $this->whenDescriptorHasTags($descriptor, $tags);
205
        $this->whenDescriptorHasSummary($descriptor, $summary);
206
        $this->whenDescriptorHasDescription($descriptor, $description);
207
208
        return $descriptor;
209
    }
210
211
    /**
212
     * Describes when a descriptor has a summary.
213
     *
214
     * @param DescriptorAbstract|m\MockInterface $descriptor
215
     * @param string                             $summary
216
     */
217
    protected function whenDescriptorHasSummary($descriptor, $summary)
218
    {
219
        $descriptor->shouldReceive('getSummary')->andReturn($summary);
220
    }
221
222
    /**
223
     * Describes when a descriptor has a description.
224
     *
225
     * @param DescriptorAbstract|m\MockInterface $descriptor
226
     * @param string                             $description
227
     */
228
    protected function whenDescriptorHasDescription($descriptor, $description)
229
    {
230
        $descriptor->shouldReceive('getDescription')->andReturn($description);
231
    }
232
233
    /**
234
     * Describes when a descriptor has tags.
235
     *
236
     * @param DescriptorAbstract|m\MockInterface $descriptor
237
     * @param array                              $tags
238
     */
239
    protected function whenDescriptorHasTags($descriptor, $tags)
240
    {
241
        $descriptor->shouldReceive('getTags')->andReturn($tags);
242
    }
243
244
    /**
245
     * Returns a mock for a Rule and generates the given URL.
246
     *
247
     * @param string $url
248
     *
249
     * @return m\MockInterface
250
     */
251
    protected function givenARuleThatGeneratesTheGivenUrl($url)
252
    {
253
        $ruleMock = m::mock('phpDocumentor\Transformer\Router\Rule');
254
        $ruleMock->shouldReceive('generate')->andReturn($url);
255
256
        return $ruleMock;
257
    }
258
}
259