Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,55 @@ jobs:
- name: Run Behat tests
run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction

# remove once behat can be installed with symfony 8.1
phpunit-symfony-edge:
Copy link
Copy Markdown
Member Author

@soyuka soyuka May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will get removed once behat (and its dependencies) aligns for the symfony's dependencies

Comment thread
soyuka marked this conversation as resolved.
name: PHPUnit (PHP ${{ matrix.php }}) (Symfony 8.1)
runs-on: ubuntu-latest
timeout-minutes: 20
continue-on-error: true
strategy:
matrix:
php:
- '8.5'
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: pecl, composer
extensions: intl, bcmath, curl, openssl, mbstring
coverage: none
ini-values: memory_limit=-1
- name: Get composer cache directory
id: composercache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Allow unstable project dependencies
run: composer config minimum-stability dev
- name: Drop Behat dev dependencies (incompatible with Symfony 8.1)
run: composer remove --no-update --no-interaction --dev behat/behat behat/mink soyuka/contexts friends-of-behat/symfony-extension friends-of-behat/mink-browserkit-driver friends-of-behat/mink-extension
- name: Force Symfony 8.1 dev for framework-bundle and json-streamer
run: composer require --dev --no-update --no-interaction "symfony/framework-bundle:8.1.x-dev" "symfony/json-streamer:8.1.x-dev"
- name: Cache dependencies
uses: actions/cache@v5
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-symfony-edge-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-symfony-edge-
- name: Remove cache
run: rm -Rf tests/Fixtures/app/var/cache/*
- name: Update project dependencies
run: |
composer global require soyuka/pmu
composer global config allow-plugins.soyuka/pmu true --no-interaction
composer global link .
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Run PHPUnit tests
run: vendor/bin/phpunit

windows-behat:
name: Windows Behat (PHP ${{ matrix.php }}) (SQLite)
runs-on: windows-latest
Expand Down
10 changes: 7 additions & 3 deletions src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
use Symfony\Component\HttpClient\ScopingHttpClient;
use Symfony\Component\JsonStreamer\JsonStreamWriter;
use Symfony\Component\ObjectMapper\ObjectMapper;
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\NumberNormalizer;
use Symfony\Component\Uid\AbstractUid;
Expand Down Expand Up @@ -201,15 +202,18 @@ public function load(array $configs, ContainerBuilder $container): void
$this->registerLinkSecurityConfiguration($loader, $config);
$this->registerJsonStreamerConfiguration($container, $loader, $formats, $config);

// TranslationExtractCommand was introduced in framework-bundle/7.3 with the object mapper service
if (class_exists(ObjectMapper::class) && class_exists(TranslationExtractCommand::class)) {
// TranslationExtractCommand was introduced in framework-bundle/7.3 with the object mapper service.
// willBeAvailable mirrors FrameworkBundle's own gate: when symfony/object-mapper is in dev-only,
// FrameworkBundle skips object_mapper.php and the "object_mapper" service we alias to does not exist.
if (class_exists(ObjectMapper::class) && class_exists(TranslationExtractCommand::class) && ContainerBuilder::willBeAvailable('symfony/object-mapper', ObjectMapperInterface::class, ['symfony/framework-bundle'])) {
$loader->load('state/object_mapper.php');
$loader->load($config['use_symfony_listeners'] ? 'symfony/object_mapper.php' : 'state/object_mapper_processor.php');
}

$container->setParameter('api_platform.mcp.format', $config['mcp']['format'] ?? null);

if (($config['mcp']['enabled'] ?? false) && class_exists(McpBundle::class)) {
// McpToolProvider requires Symfony's object_mapper service; mirror FrameworkBundle's gate so we don't try to wire it when object-mapper is dev-only.
if (($config['mcp']['enabled'] ?? false) && class_exists(McpBundle::class) && ContainerBuilder::willBeAvailable('symfony/object-mapper', ObjectMapperInterface::class, ['symfony/framework-bundle'])) {
$loader->load('mcp/mcp.php');
$loader->load($config['use_symfony_listeners'] ? 'mcp/events.php' : 'mcp/state.php');
}
Expand Down
5 changes: 3 additions & 2 deletions src/Symfony/Bundle/Resources/config/json_streamer/common.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\IriValueTransformer;
use ApiPlatform\JsonLd\JsonStreamer\ValueTransformer\TypeValueTransformer;
use ApiPlatform\JsonLd\JsonStreamer\WritePropertyMetadataLoader;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DeprecateJsonStreamerValueTransformerTagPass;
use Symfony\Component\JsonStreamer\CacheWarmer\LazyGhostCacheWarmer;
use Symfony\Component\JsonStreamer\JsonStreamReader;
use Symfony\Component\JsonStreamer\JsonStreamWriter;
Expand Down Expand Up @@ -77,9 +78,9 @@
->args([service('api_platform.router')])
->tag('json_streamer.value_transformer');

if (class_exists(DateTimeValueObjectTransformer::class)) {
// FrameworkBundle 8.1+ registers DateTimeValueObjectTransformer itself; skip to avoid duplicate registration and TransformerPass validation breakage (issue #7954).
if (class_exists(DateTimeValueObjectTransformer::class) && !class_exists(DeprecateJsonStreamerValueTransformerTagPass::class)) {
$services->set('api_platform.jsonld.json_streamer.value_transformer.date_time', DateTimeValueObjectTransformer::class)
->tag('json_streamer.value_transformer', ['key' => \DateTimeInterface::class])
->tag('json_streamer.value_object_transformer');
}
};
7 changes: 5 additions & 2 deletions tests/Fixtures/app/AppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function registerBundles(): array
new MakerBundle(),
];

if (null === ($_ENV['APP_PHPUNIT'] ?? null)) {
if (null === ($_ENV['APP_PHPUNIT'] ?? null) && class_exists(FriendsOfBehatSymfonyExtensionBundle::class)) {
$bundles[] = new FriendsOfBehatSymfonyExtensionBundle();
}

Expand Down Expand Up @@ -126,7 +126,10 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load

$loader->load(__DIR__."/config/config_{$this->getEnvironment()}.yml");

$c->getDefinition(DoctrineContext::class)->setArgument('$passwordHasher', class_exists(NativePasswordHasher::class) ? 'security.user_password_encoder' : 'security.user_password_hasher');
if (interface_exists(Behat\Behat\Context\Context::class) && class_exists(DoctrineContext::class)) {
$loader->load(__DIR__.('mongodb' === $this->getEnvironment() ? '/config/config_behat_mongodb.yml' : '/config/config_behat_orm.yml'));
$c->getDefinition(DoctrineContext::class)->setArgument('$passwordHasher', class_exists(NativePasswordHasher::class) ? 'security.user_password_encoder' : 'security.user_password_hasher');
}

$messengerConfig = [
'default_bus' => 'messenger.bus.default',
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_elasticsearch.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
imports:
- { resource: config_common.yml }
- { resource: config_behat_orm.yml }

parameters:
env(ELASTICSEARCH_URL): http://localhost:9200
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_mongodb.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
imports:
- { resource: config_common.yml }
- { resource: config_behat_mongodb.yml }

parameters:
env(MONGODB_DB): api_platform_test
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_mysql.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
imports:
- { resource: config_common.yml }
- { resource: config_doctrine.yml }
- { resource: config_behat_orm.yml }

parameters:
env(DATABASE_URL): mysql://root:@localhost/api_platform_test
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_opensearch.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
imports:
- { resource: config_common.yml }
- { resource: config_behat_orm.yml }

parameters:
env(ELASTICSEARCH_URL): http://localhost:9200
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_postgres.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
imports:
- { resource: config_common.yml }
- { resource: config_doctrine.yml }
- { resource: config_behat_orm.yml }

parameters:
env(DATABASE_URL): postgres://postgres:@localhost/api_platform_test
Expand Down
1 change: 0 additions & 1 deletion tests/Fixtures/app/config/config_sqlite.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
imports:
- { resource: config_common.yml }
- { resource: config_doctrine.yml }
- { resource: config_behat_orm.yml }

parameters:
env(DATABASE_URL): sqlite:///%kernel.project_dir%/var/data.db
Expand Down
17 changes: 11 additions & 6 deletions tests/Fixtures/app/config/config_swagger.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\Config\ApiPlatformConfig;

return static function (ApiPlatformConfig $apiPlatformConfig): void {
$apiPlatformConfig->swagger()->apiKeys('Some_Authorization_Name')
->name('Authorization')
->type('header');
return static function (ContainerConfigurator $container): void {
$container->extension('api_platform', [
'swagger' => [
'api_keys' => [
'Some_Authorization_Name' => [
'name' => 'Authorization',
'type' => 'header',
],
],
],
]);
};
14 changes: 7 additions & 7 deletions tests/Symfony/Bundle/SwaggerUi/SwaggerUiProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@
use ApiPlatform\State\ProviderInterface;
use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;

class SwaggerUiProviderTest extends TestCase
{
public function testProvideWithBaseUrl(): void
{
$openapiFactory = $this->createMock(OpenApiFactoryInterface::class);
$request = $this->createStub(Request::class);
$request->attributes = new ParameterBag();
$request->query = new InputBag();
$request->method('getRequestFormat')->willReturn('html');
$request->method('getBaseUrl')->willReturn('test');
$request = new class extends Request {
public function getBaseUrl(): string
{
return 'test';
}
};
$request->setRequestFormat('html');
$decorated = $this->createStub(ProviderInterface::class);
$provider = new SwaggerUiProvider($decorated, $openapiFactory);
$openapiFactory->expects($this->once())->method('__invoke')->with(['base_url' => 'test', 'filter_tags' => []])->willReturn(new OpenApi(new Info('test', '1'), [], new Paths()));
Expand Down
Loading