Skip to content

Commit 34ae947

Browse files
PHPSpec to PHPUnit
1 parent 0335287 commit 34ae947

10 files changed

+1034
-613
lines changed

src/Component/spec/Symfony/Routing/Factory/AttributesOperationRouteFactorySpec.php

Lines changed: 127 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,76 +11,160 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace spec\Sylius\Resource\Symfony\Routing\Factory;
14+
namespace Sylius\Resource\Tests\Symfony\Routing\Factory;
1515

16-
use PhpSpec\ObjectBehavior;
17-
use Prophecy\Argument;
16+
use PHPUnit\Framework\TestCase;
1817
use Sylius\Component\Resource\Tests\Dummy\DummyResourceWithOperations;
1918
use Sylius\Resource\Metadata\Create;
2019
use Sylius\Resource\Metadata\Index;
2120
use Sylius\Resource\Metadata\MetadataInterface;
21+
use Sylius\Resource\Metadata\Operation;
22+
use Sylius\Resource\Metadata\Operations;
2223
use Sylius\Resource\Metadata\RegistryInterface;
2324
use Sylius\Resource\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory;
25+
use Sylius\Resource\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
26+
use Sylius\Resource\Metadata\Resource\ResourceMetadataCollection;
27+
use Sylius\Resource\Metadata\ResourceMetadata;
2428
use Sylius\Resource\Metadata\Show;
2529
use Sylius\Resource\Metadata\Update;
2630
use Sylius\Resource\Symfony\Routing\Factory\AttributesOperationRouteFactory;
2731
use Sylius\Resource\Symfony\Routing\Factory\OperationRouteFactory;
2832
use Sylius\Resource\Symfony\Routing\Factory\RouteName\OperationRouteNameFactory;
2933
use Sylius\Resource\Symfony\Routing\Factory\RoutePath\OperationRoutePathFactoryInterface;
3034
use Symfony\Component\Routing\RouteCollection;
31-
use Webmozart\Assert\Assert;
3235

33-
final class AttributesOperationRouteFactorySpec extends ObjectBehavior
36+
final class AttributesOperationRouteFactoryTest extends TestCase
3437
{
35-
function let(
36-
RegistryInterface $resourceRegistry,
37-
OperationRoutePathFactoryInterface $routePathFactory,
38-
): void {
39-
$this->beConstructedWith(
40-
$resourceRegistry,
41-
new OperationRouteFactory($routePathFactory->getWrappedObject()),
38+
private RegistryInterface $resourceRegistry;
39+
40+
private OperationRoutePathFactoryInterface $routePathFactory;
41+
42+
private AttributesOperationRouteFactory $attributesOperationRouteFactory;
43+
44+
protected function setUp(): void
45+
{
46+
$this->resourceRegistry = $this->createMock(RegistryInterface::class);
47+
$this->routePathFactory = $this->createMock(OperationRoutePathFactoryInterface::class);
48+
49+
$this->attributesOperationRouteFactory = new AttributesOperationRouteFactory(
50+
$this->resourceRegistry,
51+
new OperationRouteFactory($this->routePathFactory),
4252
new AttributesResourceMetadataCollectionFactory(
43-
$resourceRegistry->getWrappedObject(),
53+
$this->resourceRegistry,
4454
new OperationRouteNameFactory(),
4555
'symfony',
4656
),
4757
);
4858
}
4959

50-
function it_is_initializable(): void
60+
private function createDummyMetadataMock(): MetadataInterface
5161
{
52-
$this->shouldHaveType(AttributesOperationRouteFactory::class);
62+
$metadata = $this->createMock(MetadataInterface::class);
63+
$metadata->method('getServiceId')->with('repository')->willReturn('app.repository.dummy');
64+
$metadata->method('hasClass')->with('form')->willReturn(true);
65+
$metadata->method('getClass')->willReturnMap([
66+
['form', 'App\Form'],
67+
['model', 'App\Dummy'],
68+
]);
69+
$metadata->method('getApplicationName')->willReturn('app');
70+
$metadata->method('getName')->willReturn('dummy');
71+
$metadata->method('getPluralName')->willReturn('dummies');
72+
73+
return $metadata;
74+
}
75+
76+
public function testItCreatesRoutesWithOperations(): void
77+
{
78+
$routeCollection = new RouteCollection();
79+
$metadata = $this->createDummyMetadataMock();
80+
$this->resourceRegistry->method('get')->with('app.dummy')->willReturn($metadata);
81+
82+
$this->routePathFactory
83+
->expects($this->exactly(4))
84+
->method('createRoutePath')
85+
->willReturnCallback(function ($operation, $path) {
86+
if ($operation instanceof Index) {
87+
return '/dummies';
88+
}
89+
if ($operation instanceof Create) {
90+
return '/dummies/new';
91+
}
92+
if ($operation instanceof Update) {
93+
return '/dummies/{id}/edit';
94+
}
95+
if ($operation instanceof Show) {
96+
return '/dummies/{id}';
97+
}
98+
99+
return $path;
100+
});
101+
102+
$this->attributesOperationRouteFactory->createRouteForClass($routeCollection, DummyResourceWithOperations::class);
103+
104+
$this->assertCount(4, $routeCollection);
105+
$this->assertNotNull($routeCollection->get('app_dummy_index'), 'Route "app_dummy_index" not found but it should.');
106+
$this->assertNotNull($routeCollection->get('app_dummy_create'), 'Route "app_dummy_create" not found but it should.');
107+
$this->assertNotNull($routeCollection->get('app_dummy_update'), 'Route "app_dummy_update" not found but it should.');
108+
$this->assertNotNull($routeCollection->get('app_dummy_show'), 'Route "app_dummy_show" not found but it should.');
53109
}
54110

55-
function it_creates_routes_with_operations(
56-
RegistryInterface $resourceRegistry,
57-
MetadataInterface $metadata,
58-
OperationRoutePathFactoryInterface $routePathFactory,
59-
): void {
111+
public function testItSkipsNonHttpOperations(): void
112+
{
60113
$routeCollection = new RouteCollection();
61114

62-
$metadata->getServiceId('repository')->willReturn('app.repository.dummy');
63-
$metadata->hasClass('form')->willReturn(true);
64-
$metadata->getClass('form')->willReturn('App\Form');
65-
$metadata->getClass('model')->willReturn('App\Dummy');
66-
$metadata->getStateMachineComponent()->willReturn('symfony');
67-
$resourceRegistry->get('app.dummy')->willReturn($metadata);
68-
69-
$metadata->getApplicationName()->willReturn('app');
70-
$metadata->getName()->willReturn('dummy');
71-
$metadata->getPluralName()->willReturn('dummies');
72-
73-
$routePathFactory->createRoutePath(Argument::type(Index::class), 'dummies')->willReturn('/dummies')->shouldBeCalled();
74-
$routePathFactory->createRoutePath(Argument::type(Create::class), 'dummies')->willReturn('/dummies/new')->shouldBeCalled();
75-
$routePathFactory->createRoutePath(Argument::type(Update::class), 'dummies')->willReturn('/dummies/{id}/edit')->shouldBeCalled();
76-
$routePathFactory->createRoutePath(Argument::type(Show::class), 'dummies')->willReturn('/dummies/{id}')->shouldBeCalled();
77-
78-
$this->createRouteForClass($routeCollection, DummyResourceWithOperations::class);
79-
80-
Assert::count($routeCollection, 4);
81-
Assert::notNull($routeCollection->get('app_dummy_index'), 'Route "app_dummy_index" not found but it should.');
82-
Assert::notNull($routeCollection->get('app_dummy_create'), 'Route "app_dummy_create" not found but it should.');
83-
Assert::notNull($routeCollection->get('app_dummy_update'), 'Route "app_dummy_update" not found but it should.');
84-
Assert::notNull($routeCollection->get('app_dummy_show'), 'Route "app_dummy_show" not found but it should.');
115+
// Create a non-HTTP operation (directly extends Operation, not HttpOperation)
116+
$nonHttpOperation = new class() extends Operation {
117+
public function getShortName(): ?string
118+
{
119+
return 'custom';
120+
}
121+
};
122+
123+
// Create an HTTP operation
124+
$httpOperation = (new Index(name: 'app_dummy_index'))->withRouteName('app_dummy_index');
125+
126+
// Create resource with mixed operations
127+
$resource = new ResourceMetadata(
128+
alias: 'app.dummy',
129+
name: 'dummy',
130+
operations: [
131+
'app_dummy_custom' => $nonHttpOperation,
132+
'app_dummy_index' => $httpOperation,
133+
],
134+
);
135+
136+
$resourceCollection = new ResourceMetadataCollection();
137+
$resourceCollection[] = $resource;
138+
139+
// Mock resource metadata factory to return our custom collection
140+
$resourceMetadataFactory = $this->createMock(ResourceMetadataCollectionFactoryInterface::class);
141+
$resourceMetadataFactory
142+
->method('create')
143+
->with(\stdClass::class)
144+
->willReturn($resourceCollection);
145+
146+
// Mock metadata for registry
147+
$metadata = $this->createDummyMetadataMock();
148+
$this->resourceRegistry->method('get')->with('app.dummy')->willReturn($metadata);
149+
150+
$this->routePathFactory
151+
->expects($this->once())
152+
->method('createRoutePath')
153+
->with($httpOperation, 'dummies')
154+
->willReturn('/dummies');
155+
156+
// Create factory with mocked dependencies
157+
$factory = new AttributesOperationRouteFactory(
158+
$this->resourceRegistry,
159+
new OperationRouteFactory($this->routePathFactory),
160+
$resourceMetadataFactory,
161+
);
162+
163+
$factory->createRouteForClass($routeCollection, \stdClass::class);
164+
165+
// Only the HTTP operation should create a route
166+
$this->assertCount(1, $routeCollection);
167+
$this->assertNotNull($routeCollection->get('app_dummy_index'), 'Route "app_dummy_index" not found but it should.');
168+
$this->assertNull($routeCollection->get('app_dummy_custom'), 'Non-HTTP operation should not create a route.');
85169
}
86170
}

0 commit comments

Comments
 (0)