Completed
Push — master ( 43f90a...f256f0 )
by Jaap
21:44 queued 11:35
created

testInvalidTagIsReturnedOnFailure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 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\Reflection\DocBlock;
15
16
use Mockery as m;
17
use phpDocumentor\Reflection\DocBlock\Tags\Author;
18
use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
19
use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
20
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
21
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
22
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
23
use phpDocumentor\Reflection\DocBlock\Tags\See;
24
use phpDocumentor\Reflection\Fqsen;
25
use phpDocumentor\Reflection\FqsenResolver;
26
use phpDocumentor\Reflection\TypeResolver;
27
use phpDocumentor\Reflection\Types\Context;
28
use PHPUnit\Framework\TestCase;
29
30
/**
31
 * @coversDefaultClass \phpDocumentor\Reflection\DocBlock\StandardTagFactory
32
 * @covers ::<private>
33
 */
34
class StandardTagFactoryTest extends TestCase
35
{
36
    /**
37
     * Call Mockery::close after each test.
38
     */
39
    public function tearDown() : void
40
    {
41
        m::close();
42
    }
43
44
    /**
45
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
46
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic
47
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
48
     * @uses \phpDocumentor\Reflection\DocBlock\Description
49
     *
50
     * @covers ::__construct
51
     * @covers ::create
52
     */
53
    public function testCreatingAGenericTag() : void
54
    {
55
        $expectedTagName         = 'unknown-tag';
56
        $expectedDescriptionText = 'This is a description';
57
        $expectedDescription     = new Description($expectedDescriptionText);
58
        $context                 = new Context('');
59
60
        $descriptionFactory = m::mock(DescriptionFactory::class);
61
        $descriptionFactory
62
            ->shouldReceive('create')
63
            ->once()
64
            ->with($expectedDescriptionText, $context)
65
            ->andReturn($expectedDescription);
66
67
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class));
68
        $tagFactory->addService($descriptionFactory, DescriptionFactory::class);
69
70
        /** @var Generic $tag */
71
        $tag = $tagFactory->create('@' . $expectedTagName . ' This is a description', $context);
72
73
        $this->assertInstanceOf(Generic::class, $tag);
74
        $this->assertSame($expectedTagName, $tag->getName());
75
        $this->assertSame($expectedDescription, $tag->getDescription());
76
    }
77
78
    /**
79
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
80
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author
81
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
82
     *
83
     * @covers ::__construct
84
     * @covers ::create
85
     */
86
    public function testCreatingASpecificTag() : void
87
    {
88
        $context    = new Context('');
89
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class));
90
91
        /** @var Author $tag */
92
        $tag = $tagFactory->create('@author Mike van Riel <[email protected]>', $context);
93
94
        $this->assertInstanceOf(Author::class, $tag);
95
        $this->assertSame('author', $tag->getName());
96
    }
97
98
    /**
99
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
100
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\See
101
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
102
     * @uses \phpDocumentor\Reflection\Fqsen
103
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen
104
     *
105
     * @covers ::__construct
106
     * @covers ::create
107
     */
108
    public function testAnEmptyContextIsCreatedIfNoneIsProvided() : void
109
    {
110
        $fqsen              = '\Tag';
111
        $resolver           = m::mock(FqsenResolver::class)
112
            ->shouldReceive('resolve')
113
            ->with('Tag', m::type(Context::class))
114
            ->andReturn(new Fqsen($fqsen))
115
            ->getMock();
116
        $descriptionFactory = m::mock(DescriptionFactory::class);
117
        $descriptionFactory->shouldIgnoreMissing();
118
119
        $tagFactory = new StandardTagFactory($resolver);
120
        $tagFactory->addService($descriptionFactory, DescriptionFactory::class);
121
122
        /** @var See $tag */
123
        $tag = $tagFactory->create('@see Tag');
124
125
        $this->assertInstanceOf(See::class, $tag);
126
        $this->assertSame($fqsen, (string) $tag->getReference());
127
    }
128
129
    /**
130
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
131
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author
132
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
133
     *
134
     * @covers ::__construct
135
     * @covers ::create
136
     */
137
    public function testPassingYourOwnSetOfTagHandlers() : void
138
    {
139
        $context    = new Context('');
140
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class), ['user' => Author::class]);
141
142
        /** @var Author $tag */
143
        $tag = $tagFactory->create('@user Mike van Riel <[email protected]>', $context);
144
145
        $this->assertInstanceOf(Author::class, $tag);
146
        $this->assertSame('author', $tag->getName());
147
    }
148
149
    /**
150
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
151
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
152
     *
153
     * @covers ::create
154
     */
155
    public function testExceptionIsThrownIfProvidedTagIsNotWellformed() : void
156
    {
157
        $this->expectException('InvalidArgumentException');
158
        $this->expectExceptionMessage(
159
            'The tag "@user[myuser" does not seem to be wellformed, please check it for errors'
160
        );
161
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class));
162
        $tagFactory->create('@user[myuser');
163
    }
164
165
    /**
166
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
167
     *
168
     * @covers ::__construct
169
     * @covers ::addParameter
170
     */
171
    public function testAddParameterToServiceLocator() : void
172
    {
173
        $resolver   = m::mock(FqsenResolver::class);
174
        $tagFactory = new StandardTagFactory($resolver);
175
        $tagFactory->addParameter('myParam', 'myValue');
176
177
        $this->assertAttributeSame(
178
            [FqsenResolver::class => $resolver, 'myParam' => 'myValue'],
179
            'serviceLocator',
180
            $tagFactory
181
        );
182
    }
183
184
    /**
185
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
186
     *
187
     * @covers ::addService
188
     */
189
    public function testAddServiceToServiceLocator() : void
190
    {
191
        $service = new PassthroughFormatter();
192
193
        $resolver   = m::mock(FqsenResolver::class);
194
        $tagFactory = new StandardTagFactory($resolver);
195
        $tagFactory->addService($service);
196
197
        $this->assertAttributeSame(
198
            [FqsenResolver::class => $resolver, PassthroughFormatter::class => $service],
199
            'serviceLocator',
200
            $tagFactory
201
        );
202
    }
203
204
    /**
205
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
206
     *
207
     * @covers ::addService
208
     */
209
    public function testInjectConcreteServiceForInterfaceToServiceLocator() : void
210
    {
211
        $interfaceName = Formatter::class;
212
        $service       = new PassthroughFormatter();
213
214
        $resolver   = m::mock(FqsenResolver::class);
215
        $tagFactory = new StandardTagFactory($resolver);
216
        $tagFactory->addService($service, $interfaceName);
217
218
        $this->assertAttributeSame(
219
            [FqsenResolver::class => $resolver, $interfaceName => $service],
220
            'serviceLocator',
221
            $tagFactory
222
        );
223
    }
224
225
    /**
226
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
227
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
228
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::create
229
     * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author
230
     *
231
     * @covers ::registerTagHandler
232
     */
233
    public function testRegisteringAHandlerForANewTag() : void
234
    {
235
        $resolver   = m::mock(FqsenResolver::class);
236
        $tagFactory = new StandardTagFactory($resolver);
237
238
        $tagFactory->registerTagHandler('my-tag', Author::class);
239
240
        // Assert by trying to create one
241
        $tag = $tagFactory->create('@my-tag Mike van Riel <[email protected]>');
242
        $this->assertInstanceOf(Author::class, $tag);
243
    }
244
245
    /**
246
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
247
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
248
     *
249
     * @covers ::registerTagHandler
250
     */
251
    public function testHandlerRegistrationFailsIfProvidedTagNameIsNamespaceButNotFullyQualified() : void
252
    {
253
        $this->expectException('InvalidArgumentException');
254
        $resolver   = m::mock(FqsenResolver::class);
255
        $tagFactory = new StandardTagFactory($resolver);
256
        // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
257
        $tagFactory->registerTagHandler(\Name\Spaced\Tag::class, Author::class);
258
    }
259
260
    /**
261
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
262
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
263
     *
264
     * @covers ::registerTagHandler
265
     */
266
    public function testHandlerRegistrationFailsIfProvidedHandlerIsEmpty() : void
267
    {
268
        $this->expectException('InvalidArgumentException');
269
        $resolver   = m::mock(FqsenResolver::class);
270
        $tagFactory = new StandardTagFactory($resolver);
271
        $tagFactory->registerTagHandler('my-tag', '');
272
    }
273
274
    /**
275
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
276
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
277
     *
278
     * @covers ::registerTagHandler
279
     */
280
    public function testHandlerRegistrationFailsIfProvidedHandlerIsNotAnExistingClassName() : void
281
    {
282
        $this->expectException('InvalidArgumentException');
283
        $resolver   = m::mock(FqsenResolver::class);
284
        $tagFactory = new StandardTagFactory($resolver);
285
        $tagFactory->registerTagHandler('my-tag', 'IDoNotExist');
286
    }
287
288
    /**
289
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
290
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
291
     *
292
     * @covers ::registerTagHandler
293
     */
294
    public function testHandlerRegistrationFailsIfProvidedHandlerDoesNotImplementTheTagInterface() : void
295
    {
296
        $this->expectException('InvalidArgumentException');
297
        $resolver   = m::mock(FqsenResolver::class);
298
        $tagFactory = new StandardTagFactory($resolver);
299
        $tagFactory->registerTagHandler('my-tag', 'stdClass');
300
    }
301
302
    /**
303
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct
304
     * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService
305
     * @uses \phpDocumentor\Reflection\Docblock\Description
306
     * @uses \phpDocumentor\Reflection\Docblock\Tags\Return_
307
     * @uses \phpDocumentor\Reflection\Docblock\Tags\BaseTag
308
     *
309
     * @covers ::create
310
     */
311
    public function testReturnTagIsMappedCorrectly() : void
312
    {
313
        $context = new Context('');
314
315
        $descriptionFactory = m::mock(DescriptionFactory::class);
316
        $descriptionFactory
317
            ->shouldReceive('create')
318
            ->once()
319
            ->with('', $context)
320
            ->andReturn(new Description(''));
321
322
        $typeResolver = new TypeResolver();
323
324
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class));
325
        $tagFactory->addService($descriptionFactory, DescriptionFactory::class);
326
        $tagFactory->addService($typeResolver, TypeResolver::class);
327
328
        /** @var Return_ $tag */
329
        $tag = $tagFactory->create('@return mixed', $context);
330
331
        $this->assertInstanceOf(Return_::class, $tag);
332
        $this->assertSame('return', $tag->getName());
333
    }
334
335
    public function testInvalidTagIsReturnedOnFailure() : void
336
    {
337
        $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class));
338
339
        /** @var InvalidTag $tag */
340
        $tag = $tagFactory->create('@see $name some invalid tag');
341
342
        $this->assertInstanceOf(InvalidTag::class, $tag);
343
    }
344
}
345