265 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			265 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
| 
								 | 
							
								<?php declare(strict_types=1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @license Apache 2.0
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace OpenApi\Tests;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use OpenApi\Analyser;
							 | 
						||
| 
								 | 
							
								use OpenApi\Annotations\Property;
							 | 
						||
| 
								 | 
							
								use OpenApi\Annotations\Schema;
							 | 
						||
| 
								 | 
							
								use OpenApi\Context;
							 | 
						||
| 
								 | 
							
								use OpenApi\Generator;
							 | 
						||
| 
								 | 
							
								use OpenApi\StaticAnalyser;
							 | 
						||
| 
								 | 
							
								use OpenApi\Tests\Fixtures\Parser\User;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class StaticAnalyserTest extends OpenApiTestCase
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    public function singleDefinitionCases()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [
							 | 
						||
| 
								 | 
							
								            'global-class' => ['class AClass {}', '\AClass', 'AClass', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'global-interface' => ['interface AInterface {}', '\AInterface', 'AInterface', 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'global-trait' => ['trait ATrait {}', '\ATrait', 'ATrait', 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'namespaced-class' => ['namespace Foo; class AClass {}', '\Foo\AClass', 'AClass', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface' => ['namespace Foo; interface AInterface {}', '\Foo\AInterface', 'AInterface', 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait' => ['namespace Foo; trait ATrait {}', '\Foo\ATrait', 'ATrait', 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								        ];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @dataProvider singleDefinitionCases
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testSingleDefinition($code, $fqdn, $name, $type, $typeKey)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromCode($code);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertSame([$fqdn], array_keys($analysis->$type));
							 | 
						||
| 
								 | 
							
								        $definition = $analysis->$type[$fqdn];
							 | 
						||
| 
								 | 
							
								        $this->assertSame($name, $definition[$typeKey]);
							 | 
						||
| 
								 | 
							
								        $this->assertTrue(!array_key_exists('extends', $definition) || !$definition['extends']);
							 | 
						||
| 
								 | 
							
								        $this->assertSame([], $definition['properties']);
							 | 
						||
| 
								 | 
							
								        $this->assertSame([], $definition['methods']);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function extendsDefinitionCases()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [
							 | 
						||
| 
								 | 
							
								            'global-class' => ['class AClass extends Other {}', '\AClass', 'AClass', '\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class' => ['namespace Foo; class AClass extends \Other {}', '\Foo\AClass', 'AClass', '\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'global-class-explicit' => ['class AClass extends \Bar\Other {}', '\AClass', 'AClass', '\Bar\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-explicit' => ['namespace Foo; class AClass extends \Bar\Other {}', '\Foo\AClass', 'AClass', '\Bar\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'global-class-use' => ['use Bar\Other; class AClass extends Other {}', '\AClass', 'AClass', '\Bar\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-use' => ['namespace Foo; use Bar\Other; class AClass extends Other {}', '\Foo\AClass', 'AClass', '\Bar\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-as' => ['namespace Foo; use Bar\Some as Other; class AClass extends Other {}', '\Foo\AClass', 'AClass', '\Bar\Some', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-same' => ['namespace Foo; class AClass extends Other {}', '\Foo\AClass', 'AClass', '\Foo\Other', 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'global-interface' => ['interface AInterface extends Other {}', '\AInterface', 'AInterface', ['\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface' => ['namespace Foo; interface AInterface extends \Other {}', '\Foo\AInterface', 'AInterface', ['\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'global-interface-explicit' => ['interface AInterface extends \Bar\Other {}', '\AInterface', 'AInterface', ['\Bar\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface-explicit' => ['namespace Foo; interface AInterface extends \Bar\Other {}', '\Foo\AInterface', 'AInterface', ['\Bar\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'global-interface-use' => ['use Bar\Other; interface AInterface extends Other {}', '\AInterface', 'AInterface', ['\Bar\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface-use' => ['namespace Foo; use Bar\Other; interface AInterface extends Other {}', '\Foo\AInterface', 'AInterface', ['\Bar\Other'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface-use-multi' => ['namespace Foo; use Bar\Other; interface AInterface extends Other, \More {}', '\Foo\AInterface', 'AInterface', ['\Bar\Other', '\More'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								            'namespaced-interface-as' => ['namespace Foo; use Bar\Some as Other; interface AInterface extends Other {}', '\Foo\AInterface', 'AInterface', ['\Bar\Some'], 'interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								        ];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @dataProvider extendsDefinitionCases
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testExtendsDefinition($code, $fqdn, $name, $extends, $type, $typeKey)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromCode($code);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertSame([$fqdn], array_keys($analysis->$type));
							 | 
						||
| 
								 | 
							
								        $definition = $analysis->$type[$fqdn];
							 | 
						||
| 
								 | 
							
								        $this->assertSame($name, $definition[$typeKey]);
							 | 
						||
| 
								 | 
							
								        $this->assertSame($extends, $definition['extends']);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function usesDefinitionCases()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [
							 | 
						||
| 
								 | 
							
								            'global-class-use' => ['class AClass { use Other; }', '\AClass', 'AClass', ['\Other'], 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-use' => ['namespace Foo; class AClass { use \Other; }', '\Foo\AClass', 'AClass', ['\Other'], 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-use-namespaced' => ['namespace Foo; use Bar\Other; class AClass { use Other; }', '\Foo\AClass', 'AClass', ['\Bar\Other'], 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								            'namespaced-class-use-namespaced-as' => ['namespace Foo; use Bar\Other as Some; class AClass { use Some; }', '\Foo\AClass', 'AClass', ['\Bar\Other'], 'classes', 'class'],
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            'global-trait-use' => ['trait ATrait { use Other; }', '\ATrait', 'ATrait', ['\Other'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait-use' => ['namespace Foo; trait ATrait { use \Other; }', '\Foo\ATrait', 'ATrait', ['\Other'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait-use-explicit' => ['namespace Foo; trait ATrait { use \Bar\Other; }', '\Foo\ATrait', 'ATrait', ['\Bar\Other'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait-use-multi' => ['namespace Foo; trait ATrait { use \Other; use \More; }', '\Foo\ATrait', 'ATrait', ['\Other', '\More'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait-use-mixed' => ['namespace Foo; use Bar\Other; trait ATrait { use Other, \More; }', '\Foo\ATrait', 'ATrait', ['\Bar\Other', '\More'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								            'namespaced-trait-use-as' => ['namespace Foo; use Bar\Other as Some; trait ATrait { use Some; }', '\Foo\ATrait', 'ATrait', ['\Bar\Other'], 'traits', 'trait'],
							 | 
						||
| 
								 | 
							
								        ];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @dataProvider usesDefinitionCases
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testUsesDefinition($code, $fqdn, $name, $traits, $type, $typeKey)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromCode($code);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertSame([$fqdn], array_keys($analysis->$type));
							 | 
						||
| 
								 | 
							
								        $definition = $analysis->$type[$fqdn];
							 | 
						||
| 
								 | 
							
								        $this->assertSame($name, $definition[$typeKey]);
							 | 
						||
| 
								 | 
							
								        $this->assertSame($traits, $definition['traits']);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function testWrongCommentType()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analyser = new StaticAnalyser();
							 | 
						||
| 
								 | 
							
								        $this->assertOpenApiLogEntryContains('Annotations are only parsed inside `/**` DocBlocks');
							 | 
						||
| 
								 | 
							
								        $analyser->fromCode("<?php\n/*\n * @OA\Parameter() */", new Context());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function testIndentationCorrection()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromFixtures('StaticAnalyser/routes.php');
							 | 
						||
| 
								 | 
							
								        $this->assertCount(20, $analysis->annotations);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function testThirdPartyAnnotations()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $backup = Analyser::$whitelist;
							 | 
						||
| 
								 | 
							
								        Analyser::$whitelist = ['OpenApi\\Annotations\\'];
							 | 
						||
| 
								 | 
							
								        $analyser = new StaticAnalyser();
							 | 
						||
| 
								 | 
							
								        $defaultAnalysis = $analyser->fromFile(__DIR__ . '/Fixtures/ThirdPartyAnnotations.php');
							 | 
						||
| 
								 | 
							
								        $this->assertCount(3, $defaultAnalysis->annotations, 'Only read the @OA annotations, skip the others.');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Allow the analyser to parse 3rd party annotations, which might
							 | 
						||
| 
								 | 
							
								        // contain useful info that could be extracted with a custom processor
							 | 
						||
| 
								 | 
							
								        Analyser::$whitelist[] = 'AnotherNamespace\\Annotations\\';
							 | 
						||
| 
								 | 
							
								        $openapi = Generator::scan([__DIR__ . '/Fixtures/ThirdPartyAnnotations.php']);
							 | 
						||
| 
								 | 
							
								        $this->assertSame('api/3rd-party', $openapi->paths[0]->path);
							 | 
						||
| 
								 | 
							
								        $this->assertCount(4, $openapi->_unmerged);
							 | 
						||
| 
								 | 
							
								        Analyser::$whitelist = $backup;
							 | 
						||
| 
								 | 
							
								        $analysis = $openapi->_analysis;
							 | 
						||
| 
								 | 
							
								        $annotations = $analysis->getAnnotationsOfType('AnotherNamespace\Annotations\Unrelated');
							 | 
						||
| 
								 | 
							
								        $this->assertCount(4, $annotations);
							 | 
						||
| 
								 | 
							
								        $context = $analysis->getContext($annotations[0]);
							 | 
						||
| 
								 | 
							
								        $this->assertInstanceOf('OpenApi\Context', $context);
							 | 
						||
| 
								 | 
							
								        $this->assertSame('ThirdPartyAnnotations', $context->class);
							 | 
						||
| 
								 | 
							
								        $this->assertSame('\OpenApi\Tests\Fixtures\ThirdPartyAnnotations', $context->fullyQualifiedName($context->class));
							 | 
						||
| 
								 | 
							
								        $this->assertCount(1, $context->annotations);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function testAnonymousClassProducesNoError()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        try {
							 | 
						||
| 
								 | 
							
								            $analyser = new StaticAnalyser($this->fixtures('StaticAnalyser/php7.php')[0]);
							 | 
						||
| 
								 | 
							
								            $this->assertNotNull($analyser);
							 | 
						||
| 
								 | 
							
								        } catch (\Throwable $t) {
							 | 
						||
| 
								 | 
							
								            $this->fail("Analyser produced an error: {$t->getMessage()}");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * dataprovider.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function descriptions()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [
							 | 
						||
| 
								 | 
							
								            'class' => [
							 | 
						||
| 
								 | 
							
								                ['classes', 'class'],
							 | 
						||
| 
								 | 
							
								                'User',
							 | 
						||
| 
								 | 
							
								                'Parser/User.php',
							 | 
						||
| 
								 | 
							
								                '\OpenApi\Tests\Fixtures\Parser\User',
							 | 
						||
| 
								 | 
							
								                '\OpenApi\Tests\Fixtures\Parser\Sub\SubClass',
							 | 
						||
| 
								 | 
							
								                ['getFirstName'],
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                ['\OpenApi\Tests\Fixtures\Parser\HelloTrait'], // use ... as ...
							 | 
						||
| 
								 | 
							
								            ],
							 | 
						||
| 
								 | 
							
								            'interface' => [
							 | 
						||
| 
								 | 
							
								                ['interfaces', 'interface'],
							 | 
						||
| 
								 | 
							
								                'UserInterface',
							 | 
						||
| 
								 | 
							
								                'Parser/UserInterface.php',
							 | 
						||
| 
								 | 
							
								                '\OpenApi\Tests\Fixtures\Parser\UserInterface',
							 | 
						||
| 
								 | 
							
								                ['\OpenApi\Tests\Fixtures\Parser\OtherInterface'],
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								            ],
							 | 
						||
| 
								 | 
							
								            'trait' => [
							 | 
						||
| 
								 | 
							
								                ['traits', 'trait'],
							 | 
						||
| 
								 | 
							
								                'HelloTrait',
							 | 
						||
| 
								 | 
							
								                'Parser/HelloTrait.php',
							 | 
						||
| 
								 | 
							
								                '\OpenApi\Tests\Fixtures\Parser\HelloTrait',
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                null,
							 | 
						||
| 
								 | 
							
								                ['\OpenApi\Tests\Fixtures\Parser\OtherTrait', '\OpenApi\Tests\Fixtures\Parser\AsTrait'],
							 | 
						||
| 
								 | 
							
								            ],
							 | 
						||
| 
								 | 
							
								        ];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @dataProvider descriptions
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testDescription($type, $name, $fixture, $fqdn, $extends, $methods, $interfaces, $traits)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromFixtures($fixture);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        list($pType, $sType) = $type;
							 | 
						||
| 
								 | 
							
								        $description = $analysis->$pType[$fqdn];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertSame($name, $description[$sType]);
							 | 
						||
| 
								 | 
							
								        if (null !== $extends) {
							 | 
						||
| 
								 | 
							
								            $this->assertSame($extends, $description['extends']);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (null !== $methods) {
							 | 
						||
| 
								 | 
							
								            $this->assertSame($methods, array_keys($description['methods']));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (null !== $interfaces) {
							 | 
						||
| 
								 | 
							
								            $this->assertSame($interfaces, $description['interfaces']);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (null !== $traits) {
							 | 
						||
| 
								 | 
							
								            $this->assertSame($traits, $description['traits']);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function testNamespacedConstAccess()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromFixtures('Parser/User.php');
							 | 
						||
| 
								 | 
							
								        $schemas = $analysis->getAnnotationsOfType(Schema::class, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertCount(1, $schemas);
							 | 
						||
| 
								 | 
							
								        $this->assertEquals(User::CONSTANT, $schemas[0]->example);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @requires PHP 8
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testPhp8AttributeMix()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromFixtures('StaticAnalyser/Php8AttrMix.php');
							 | 
						||
| 
								 | 
							
								        $schemas = $analysis->getAnnotationsOfType(Schema::class, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertCount(1, $schemas);
							 | 
						||
| 
								 | 
							
								        $analysis->process();
							 | 
						||
| 
								 | 
							
								        $properties = $analysis->getAnnotationsOfType(Property::class, true);
							 | 
						||
| 
								 | 
							
								        $this->assertCount(2, $properties);
							 | 
						||
| 
								 | 
							
								        $this->assertEquals('id', $properties[0]->property);
							 | 
						||
| 
								 | 
							
								        $this->assertEquals('otherId', $properties[1]->property);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @requires PHP 8
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function testPhp8NamedProperty()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $analysis = $this->analysisFromFixtures('StaticAnalyser/Php8NamedProperty.php');
							 | 
						||
| 
								 | 
							
								        $schemas = $analysis->getAnnotationsOfType(Schema::class, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->assertCount(1, $schemas);
							 | 
						||
| 
								 | 
							
								        $analysis->process();
							 | 
						||
| 
								 | 
							
								        $properties = $analysis->getAnnotationsOfType(Property::class, true);
							 | 
						||
| 
								 | 
							
								        $this->assertCount(1, $properties);
							 | 
						||
| 
								 | 
							
								        $this->assertEquals('labels', $properties[0]->property);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |