• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 14500959057

16 Apr 2025 07:29PM UTC coverage: 8.532% (+0.3%) from 8.189%
14500959057

push

github

web-flow
feat: Use `Type` of `TypeInfo` instead of `PropertyInfo` (#6979)

Co-authored-by: soyuka <soyuka@users.noreply.github.com>

scopes: metadata, doctrine, json-schema

300 of 616 new or added lines in 25 files covered. (48.7%)

285 existing lines in 18 files now uncovered.

13513 of 158381 relevant lines covered (8.53%)

22.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Metadata/Tests/Resource/Factory/LinkFactoryTest.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Metadata\Tests\Resource\Factory;
15

16
use ApiPlatform\Metadata\ApiProperty;
17
use ApiPlatform\Metadata\Get;
18
use ApiPlatform\Metadata\Link;
19
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory;
20
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
21
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
22
use ApiPlatform\Metadata\Property\PropertyNameCollection;
23
use ApiPlatform\Metadata\Resource\Factory\LinkFactory;
24
use ApiPlatform\Metadata\ResourceClassResolverInterface;
25
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\AttributeResource;
26
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\Dummy;
27
use ApiPlatform\Metadata\Tests\Fixtures\ApiResource\RelatedDummy;
28
use PHPUnit\Framework\TestCase;
29
use Prophecy\Argument;
30
use Prophecy\PhpUnit\ProphecyTrait;
31
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
32
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
33
use Symfony\Component\TypeInfo\Type;
34

35
final class LinkFactoryTest extends TestCase
36
{
37
    use ProphecyTrait;
38

39
    #[\PHPUnit\Framework\Attributes\DataProvider('provideCreateLinksFromIdentifiersCases')]
40
    public function testCreateLinksFromIdentifiers(array $propertyNames, bool $compositeIdentifier, array $expectedLinks, ?bool $idAsIdentifier = null): void
41
    {
42
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
43
        $propertyNameCollectionFactoryProphecy->create(Argument::cetera())->willReturn(new PropertyNameCollection($propertyNames));
×
44
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
45
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'id')->willReturn(null === $idAsIdentifier ? new ApiProperty() : new ApiProperty(identifier: $idAsIdentifier));
×
46
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'name')->willReturn((new ApiProperty())->withIdentifier(true));
×
47
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'slug')->willReturn(new ApiProperty());
×
48
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'composite1')->willReturn((new ApiProperty())->withIdentifier(true));
×
49
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'composite2')->willReturn((new ApiProperty())->withIdentifier(true));
×
50
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
51
        $linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
×
52

53
        self::assertEquals(
×
54
            $expectedLinks,
×
55
            $linkFactory->createLinksFromIdentifiers((new Get())->withClass(AttributeResource::class))
×
56
        );
×
57
    }
58

59
    public static function provideCreateLinksFromIdentifiersCases(): \Generator
60
    {
61
        yield 'no identifiers no id' => [
×
62
            ['slug'],
×
63
            false,
×
64
            [],
×
65
        ];
×
66
        yield 'id detected as identifier' => [
×
67
            ['id'],
×
68
            false,
×
69
            [(new Link())->withFromClass(AttributeResource::class)->withParameterName('id')->withIdentifiers(['id'])],
×
70
        ];
×
71
        yield 'id forced as identifier' => [
×
72
            ['id'],
×
73
            false,
×
74
            [(new Link())->withFromClass(AttributeResource::class)->withParameterName('id')->withIdentifiers(['id'])],
×
75
            true,
×
76
        ];
×
77
        yield 'id forced as no identifier' => [
×
78
            ['id'],
×
79
            false,
×
80
            [],
×
81
            false,
×
82
        ];
×
83
        yield 'name identifier' => [
×
84
            ['id', 'name'],
×
85
            false,
×
86
            [(new Link())->withFromClass(AttributeResource::class)->withParameterName('name')->withIdentifiers(['name'])],
×
87
        ];
×
88
        yield 'composite identifier' => [
×
89
            ['composite1', 'composite2'],
×
90
            true,
×
91
            [(new Link())->withFromClass(AttributeResource::class)->withParameterName('id')->withIdentifiers(['composite1', 'composite2'])->withCompositeIdentifier(true)],
×
92
        ];
×
93
    }
94

95
    #[\PHPUnit\Framework\Attributes\DataProvider('provideCreateLinksFromAttributesCases')]
96
    public function testCreateLinksFromAttributes(?Type $nativeType, array $expectedLinks): void
97
    {
98
        $propertyNameCollectionFactory = new PropertyInfoPropertyNameCollectionFactory(new PropertyInfoExtractor([new ReflectionExtractor()]));
×
99
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
NEW
100
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'dummy')->willReturn((new ApiProperty())->withNativeType($nativeType));
×
101
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
102
        $linkFactory = new LinkFactory($propertyNameCollectionFactory, $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
×
103

104
        self::assertEquals(
×
105
            $expectedLinks,
×
106
            $linkFactory->createLinksFromAttributes((new Get())->withClass(AttributeResource::class))
×
107
        );
×
108
    }
109

110
    public static function provideCreateLinksFromAttributesCases(): \Generator
111
    {
NEW
112
        yield 'no PHP type' => [
×
NEW
113
            null,
×
114
            [(new Link())->withFromClass(AttributeResource::class)->withFromProperty('dummy')->withToClass(AttributeResource::class)->withParameterName('dummyId')],
×
115
        ];
×
NEW
116
        yield 'with PHP type' => [
×
NEW
117
            Type::object(Dummy::class),
×
118
            [(new Link())->withFromClass(AttributeResource::class)->withFromProperty('dummy')->withToClass(Dummy::class)->withParameterName('dummyId')],
×
119
        ];
×
NEW
120
        yield 'with collection PHP type' => [
×
NEW
121
            Type::list(Type::object(RelatedDummy::class)),
×
122
            [(new Link())->withFromClass(AttributeResource::class)->withFromProperty('dummy')->withToClass(RelatedDummy::class)->withParameterName('dummyId')],
×
123
        ];
×
124
    }
125

126
    public function testCompleteLink(): void
127
    {
128
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
129
        $propertyNameCollectionFactoryProphecy->create(Argument::cetera())->willReturn(new PropertyNameCollection(['slug', 'composite1', 'composite2']));
×
130
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
131
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'slug')->willReturn(new ApiProperty());
×
132
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'composite1')->willReturn((new ApiProperty())->withIdentifier(true));
×
133
        $propertyMetadataFactoryProphecy->create(AttributeResource::class, 'composite2')->willReturn((new ApiProperty())->withIdentifier(true));
×
134
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
135
        $linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
×
136

137
        self::assertEquals(
×
138
            (new Link())->withFromClass(AttributeResource::class)->withIdentifiers(['composite1', 'composite2'])->withCompositeIdentifier(true),
×
139
            $linkFactory->completeLink((new Link())->withFromClass(AttributeResource::class))
×
140
        );
×
141
    }
142

143
    public function testCreateLinkFromProperty(): void
144
    {
145
        $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
×
146

147
        $property = 'test';
×
148
        $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
×
NEW
149
        $propertyMetadataFactoryProphecy->create(Dummy::class, 'test')->willReturn(new ApiProperty(nativeType: Type::object(RelatedDummy::class)));
×
150

151
        $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
×
152
        $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(false);
×
153

154
        $linkFactory = new LinkFactory($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal());
×
155

156
        self::assertEquals(
×
157
            new Link(fromClass: RelatedDummy::class, toProperty: 'test', identifiers: ['id'], parameterName: 'test'),
×
158
            $linkFactory->createLinkFromProperty(new Get(class: Dummy::class), 'test')
×
159
        );
×
160
    }
161
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc