Skip to content

Commit a0d388e

Browse files
committed
test: add OpenApi and JsonSchema tests for defaults parameters
1 parent 30063a1 commit a0d388e

3 files changed

Lines changed: 284 additions & 0 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\Tests\Functional;
15+
16+
use ApiPlatform\Metadata\HeaderParameter;
17+
use Symfony\Component\Config\Loader\LoaderInterface;
18+
use Symfony\Component\DependencyInjection\ContainerBuilder;
19+
20+
/**
21+
* @author Maxence Castel <maxence.castel59@gmail.com>
22+
*/
23+
class DefaultParametersAppKernel extends \AppKernel
24+
{
25+
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void
26+
{
27+
parent::configureContainer($c, $loader);
28+
29+
$loader->load(static function (ContainerBuilder $container) {
30+
if ($container->hasDefinition('phpunit_resource_name_collection')) {
31+
$container->removeDefinition('phpunit_resource_name_collection');
32+
}
33+
34+
$container->loadFromExtension('api_platform', [
35+
'defaults' => [
36+
'extra_properties' => [
37+
'deduplicate_resource_short_names' => true,
38+
],
39+
'parameters' => [
40+
HeaderParameter::class => [
41+
'key' => 'X-API-Key',
42+
'required' => false,
43+
'description' => 'API key for authentication',
44+
'schema' => ['type' => 'string'],
45+
],
46+
],
47+
],
48+
]);
49+
});
50+
}
51+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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\Tests\Functional;
15+
16+
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
17+
18+
/**
19+
* Tests that default parameters configured via api_platform.defaults.parameters
20+
* appear in all resources and operations in the OpenAPI and JSONSchema documentation.
21+
*
22+
* @author Maxence Castel <maxence.castel59@gmail.com>
23+
*/
24+
final class DefaultParametersTest extends ApiTestCase
25+
{
26+
protected static ?bool $alwaysBootKernel = true;
27+
28+
protected static function getKernelClass(): string
29+
{
30+
return DefaultParametersAppKernel::class;
31+
}
32+
33+
/**
34+
* Test that default header parameter appears in all operations in OpenAPI documentation.
35+
*
36+
* This test verifies that when default parameters are configured via
37+
* api_platform.defaults.parameters with:
38+
* HeaderParameter:
39+
* key: 'X-API-Key'
40+
* required: false
41+
* description: 'API key for authentication'
42+
*
43+
* The parameter appears in ALL resources and ALL their operations in the OpenAPI output.
44+
*/
45+
public function testDefaultParameterAppearsInOpenApiForAllOperations(): void
46+
{
47+
$response = self::createClient()->request('GET', '/docs', [
48+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
49+
]);
50+
51+
$this->assertResponseIsSuccessful();
52+
$content = $response->toArray();
53+
54+
$this->assertArrayHasKey('openapi', $content);
55+
$this->assertArrayHasKey('paths', $content);
56+
57+
$foundParameter = false;
58+
$operationsWithParameter = [];
59+
60+
foreach ($content['paths'] as $pathName => $pathItem) {
61+
foreach (['get', 'post', 'put', 'patch', 'delete'] as $method) {
62+
if (!isset($pathItem[$method]['parameters'])) {
63+
continue;
64+
}
65+
66+
$parameters = $pathItem[$method]['parameters'];
67+
foreach ($parameters as $param) {
68+
if ('X-API-Key' === $param['name'] && 'header' === $param['in']) {
69+
$foundParameter = true;
70+
$operationsWithParameter[] = [
71+
'path' => $pathName,
72+
'method' => $method,
73+
];
74+
75+
$this->assertSame('X-API-Key', $param['name']);
76+
$this->assertSame('header', $param['in']);
77+
$this->assertSame('API key for authentication', $param['description']);
78+
$this->assertFalse($param['required']);
79+
$this->assertFalse($param['deprecated']);
80+
$this->assertArrayHasKey('schema', $param);
81+
$this->assertSame('string', $param['schema']['type']);
82+
break;
83+
}
84+
}
85+
}
86+
}
87+
88+
$this->assertTrue(
89+
$foundParameter,
90+
\sprintf(
91+
'Default header parameter "X-API-Key" not found in any operation. Operations checked: %d',
92+
\count($content['paths'] ?? [])
93+
)
94+
);
95+
96+
$this->assertGreaterThanOrEqual(2, \count($operationsWithParameter),
97+
'Default parameter should appear in multiple operations (collection and item)'
98+
);
99+
}
100+
101+
/**
102+
* Test that default parameters appear in both collection and item operations.
103+
*/
104+
public function testDefaultParameterAppearsInMultipleOperationTypes(): void
105+
{
106+
$response = self::createClient()->request('GET', '/docs', [
107+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
108+
]);
109+
110+
$this->assertResponseIsSuccessful();
111+
$content = $response->toArray();
112+
113+
$operationMethodsWithParameter = [];
114+
115+
foreach ($content['paths'] as $pathName => $pathItem) {
116+
foreach (['get', 'post', 'put', 'patch', 'delete'] as $method) {
117+
if (!isset($pathItem[$method]['parameters'])) {
118+
continue;
119+
}
120+
121+
$parameters = $pathItem[$method]['parameters'];
122+
foreach ($parameters as $param) {
123+
if ('X-API-Key' === $param['name'] && 'header' === $param['in']) {
124+
$operationMethodsWithParameter[$method] = true;
125+
break;
126+
}
127+
}
128+
}
129+
}
130+
131+
$this->assertGreaterThanOrEqual(2, \count($operationMethodsWithParameter),
132+
\sprintf('Default parameter should appear in at least 2 different HTTP methods, found in: %s',
133+
implode(', ', array_keys($operationMethodsWithParameter)))
134+
);
135+
}
136+
137+
public function testDefaultParametersDoNotBreakJsonLdDocumentation(): void
138+
{
139+
$response = self::createClient()->request('GET', '/docs.jsonld', [
140+
'headers' => ['Accept' => 'application/ld+json'],
141+
]);
142+
143+
$this->assertResponseIsSuccessful();
144+
$content = $response->toArray();
145+
146+
$this->assertArrayHasKey('@context', $content);
147+
148+
$this->assertTrue(
149+
isset($content['entrypoint']) || isset($content['hydra:supportedClass']),
150+
'JSON-LD response should have either "entrypoint" or "hydra:supportedClass" key'
151+
);
152+
}
153+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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\Tests\Functional\JsonSchema;
15+
16+
use ApiPlatform\JsonSchema\SchemaFactoryInterface;
17+
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
18+
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
19+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5793\BagOfTests;
20+
use ApiPlatform\Tests\Functional\DefaultParametersAppKernel;
21+
22+
/**
23+
* Test that JsonSchema can be generated when default parameters are configured.
24+
*
25+
* @author Maxence Castel <maxence.castel59@gmail.com>
26+
*/
27+
final class JsonSchemaWithDefaultParametersTest extends ApiTestCase
28+
{
29+
protected SchemaFactoryInterface $schemaFactory;
30+
protected OperationMetadataFactoryInterface $operationMetadataFactory;
31+
32+
protected static ?bool $alwaysBootKernel = true;
33+
34+
protected static function getKernelClass(): string
35+
{
36+
return DefaultParametersAppKernel::class;
37+
}
38+
39+
protected function setUp(): void
40+
{
41+
parent::setUp();
42+
$this->schemaFactory = self::getContainer()->get('api_platform.json_schema.schema_factory');
43+
$this->operationMetadataFactory = self::getContainer()->get('api_platform.metadata.operation.metadata_factory');
44+
}
45+
46+
public function testJsonSchemaCanBeGeneratedWithDefaultParameters(): void
47+
{
48+
$hasDefaultParameters = false;
49+
$resourceMetadata = self::getContainer()->get('api_platform.metadata.resource.metadata_collection_factory')->create(BagOfTests::class);
50+
51+
foreach ($resourceMetadata as $operation) {
52+
$parameters = $operation->getParameters() ?? [];
53+
foreach ($parameters as $parameter) {
54+
if ('X-API-Key' === $parameter->getKey()) {
55+
$hasDefaultParameters = true;
56+
$this->assertFalse($parameter->getRequired());
57+
$this->assertSame('API key for authentication', $parameter->getDescription());
58+
break;
59+
}
60+
}
61+
if ($hasDefaultParameters) {
62+
break;
63+
}
64+
}
65+
66+
$this->assertTrue($hasDefaultParameters, 'Default parameter "X-API-Key" should be applied to resource operations');
67+
68+
$schema = $this->schemaFactory->buildSchema(BagOfTests::class, 'jsonld');
69+
70+
$this->assertInstanceOf(\ArrayObject::class, $schema);
71+
72+
$this->assertArrayHasKey('definitions', $schema);
73+
$this->assertNotEmpty($schema['definitions']);
74+
75+
foreach ($schema['definitions'] as $key => $definition) {
76+
$this->assertIsString($key);
77+
$this->assertNotNull($definition);
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)