Compare commits

..

13 Commits

Author SHA1 Message Date
Veyra Hermes Agent
c1e8294f77 Add Symfony 8 and PHP 8.5 compatibility
Some checks failed
Build / PHP 8.3 + Symfony 7.4.* (pull_request) Has been cancelled
Build / PHP 8.4 + Symfony 7.4.* (pull_request) Has been cancelled
Build / PHP 8.5 + Symfony 7.4.* (pull_request) Has been cancelled
Build / Symfony 8 + PHP 8.5 consumer install (pull_request) Has been cancelled
Build / Run Psalm (pull_request) Has been cancelled
Build / Validate composer.json (pull_request) Has been cancelled
Build / Validate Coding Standards (pull_request) Has been cancelled
Build / PHP 8.3 + Symfony 7.4.* (push) Has been cancelled
Build / PHP 8.4 + Symfony 7.4.* (push) Has been cancelled
Build / PHP 8.5 + Symfony 7.4.* (push) Has been cancelled
Build / Symfony 8 + PHP 8.5 consumer install (push) Has been cancelled
Build / Run Psalm (push) Has been cancelled
Build / Validate composer.json (push) Has been cancelled
Build / Validate Coding Standards (push) Has been cancelled
2026-06-15 15:13:58 +02:00
Kamil Kokot
d746aede0d Merge pull request #227 from FriendsOfBehat/ci/avoid-duplicate-workflow-runs
Some checks failed
Build / PHP 8.3 + Symfony 7.4.* (push) Has been cancelled
Build / PHP 8.4 + Symfony 7.4.* (push) Has been cancelled
Build / PHP 8.5 + Symfony 7.4.* (push) Has been cancelled
Build / Run Psalm (push) Has been cancelled
Build / Validate composer.json (push) Has been cancelled
Build / Validate Coding Standards (push) Has been cancelled
Restrict push trigger to master to avoid duplicate CI runs
2026-06-12 12:34:51 +02:00
Kamil Kokot
23def58759 Merge pull request #228 from FriendsOfBehat/ci/add-php-8.5
Add PHP 8.5 to CI matrix
2026-06-12 12:34:41 +02:00
Kamil Kokot
c253eded0f Add PHP 8.5 to CI matrix
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-12 12:32:47 +02:00
Kamil Kokot
590bd4b228 Restrict push trigger to master to avoid duplicate CI runs
Previously every branch push triggered both the push and pull_request
workflows when a PR was open. Limiting push to master means branch
pushes only trigger via pull_request.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-12 12:31:43 +02:00
Kamil Kokot
4f6a7b0d0f Merge pull request #226 from FriendsOfBehat/drop/unsupported-php-and-symfony
Drop support for PHP <8.3 and Symfony <7.4
2026-06-12 12:31:17 +02:00
Kamil Kokot
56052d8d65 Drop support for PHP <8.3 and Symfony <7.4
PHP 8.1 reached EOL in November 2024, PHP 8.2 active support ended
December 2024. Symfony 6.4 LTS support continues but aligning with
the Symfony 7.4 LTS-only stance simplifies the matrix and removes
the separate include entry.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-12 12:28:15 +02:00
Kamil Kokot
04d3f12293 Merge pull request #225 from FriendsOfBehat/fix/ci-symfony-7.4
Fix CI: update matrix to Symfony 7.4, fix Psalm MissingTemplateParam
2026-06-12 12:19:16 +02:00
Kamil Kokot
4737051992 Fix CI: update matrix to Symfony 7.4, fix Psalm template param
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-12 12:10:04 +02:00
Łukasz Chruściel
3ed86d7792 Merge pull request #217 from loic425/fix/lazy-object-with-sf-7.3
Fix Mink lazy object with SF7.3 and PHP 8.4
2025-06-03 15:32:20 +02:00
Loïc Frémont
08c7d24d03 Bump package versions and fix errors 2025-06-03 14:18:53 +02:00
Loïc Frémont
b1b9b34606 Add deprecated message 2025-06-03 08:49:50 +02:00
Loïc Frémont
7fd0fb77eb Fix Mink lazy object with SF7.3 and PHP 8.4 2025-06-02 17:47:18 +02:00
15 changed files with 178 additions and 38 deletions

View File

@@ -2,6 +2,8 @@ name: Build
on:
push:
branches:
- master
pull_request:
release:
types: [created]
@@ -17,15 +19,11 @@ jobs:
fail-fast: false
matrix:
php-version:
- '8.1'
- '8.2'
- '8.3'
- '8.4'
- '8.5'
symfony-version:
- '6.2.*'
- '6.4.*'
- '7.0.*'
exclude:
- php-version: '8.1'
symfony-version: '7.0.*'
- '7.4.*'
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -52,6 +50,46 @@ jobs:
- name: Run tests
run: composer test
symfony8-php85-consumer-install:
name: Symfony 8 + PHP 8.5 consumer install
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
coverage: none
ini-values: "memory_limit=-1"
php-version: '8.5'
tools: composer:v2
- name: Verify installability in a Symfony 8 consumer project
run: |
mkdir /tmp/fob-symfony8-consumer
cat > /tmp/fob-symfony8-consumer/composer.json <<'JSON'
{
"name": "friends-of-behat/symfony8-consumer-probe",
"type": "project",
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": [
{"type": "path", "url": "${{ github.workspace }}", "options": {"symlink": false}}
],
"require-dev": {
"behat/behat": "4.x-dev",
"friends-of-behat/symfony-extension": "*",
"symfony/framework-bundle": "^8.0",
"symfony/yaml": "^8.0"
},
"config": {
"sort-packages": true
}
}
JSON
composer update --working-dir=/tmp/fob-symfony8-consumer --no-interaction --no-plugins --prefer-dist --no-progress
psalm:
name: Run Psalm
runs-on: ubuntu-22.04
@@ -64,7 +102,7 @@ jobs:
with:
coverage: none
ini-values: "memory_limit=-1, zend.assertions=1"
php-version: 8.1
php-version: 8.3
tools: composer:v2, flex
- name: Install dependencies
@@ -88,7 +126,7 @@ jobs:
with:
coverage: none
ini-values: "memory_limit=-1, zend.assertions=1"
php-version: 8.2
php-version: 8.3
tools: composer:v2, flex
- name: Validate composer.json
@@ -107,7 +145,7 @@ jobs:
with:
coverage: none
ini-values: "memory_limit=-1, zend.assertions=1"
php-version: 8.2
php-version: 8.3
tools: composer:v2, flex
- name: Install dependencies

1
.php-version Normal file
View File

@@ -0,0 +1 @@
8.3

View File

@@ -1,3 +1,17 @@
# CHANGELOG FOR `2.3.x`
## v2.3.0 (unreleased)
#### TL;DR
- **Added installability support for Symfony 8 and PHP 8.5**.
#### Details
- Allow `symfony/dependency-injection` and `symfony/http-kernel` `^8.0`.
- Allow Behat `^4.0`, which is required by Symfony 8 because Behat 3.x only supports Symfony components up to 7.x.
- Keep Symfony 7.4 / Behat 3.31 compatibility and add a CI consumer-install probe for Symfony 8 on PHP 8.5.
# CHANGELOG FOR `2.1.x`
## v2.2.0 (2021-02-04)

View File

@@ -11,24 +11,24 @@
}
],
"require": {
"php": "^8.1",
"behat/behat": "^3.6.1",
"symfony/dependency-injection": "^6.2 || ^7.0",
"symfony/http-kernel": "^6.2 || ^7.0"
"php": ">=8.3 <8.6",
"behat/behat": "^3.31 || ^4.0",
"symfony/dependency-injection": "^7.4 || ^8.0",
"symfony/http-kernel": "^7.4 || ^8.0"
},
"require-dev": {
"behat/mink-browserkit-driver": "^2.0",
"behat/mink-selenium2-driver": "^1.3",
"behat/mink": "^1.9",
"friends-of-behat/mink-extension": "^2.5",
"friends-of-behat/page-object-extension": "^0.3.2",
"friends-of-behat/service-container-extension": "^1.1",
"friends-of-behat/page-object-extension": "^0.4",
"friends-of-behat/service-container-extension": "^2.0",
"sylius-labs/coding-standard": ">=4.1.1, <=4.2.1",
"symfony/browser-kit": "^6.2 || ^7.0",
"symfony/framework-bundle": "^6.2 || ^7.0",
"symfony/process": "^6.2 || ^7.0",
"symfony/yaml": "^6.2 || ^7.0",
"vimeo/psalm": "4.30.0"
"symfony/browser-kit": "^7.4 || ^8.0",
"symfony/framework-bundle": "^7.4 || ^8.0",
"symfony/process": "^7.4 || ^8.0",
"symfony/yaml": "^7.4 || ^8.0",
"vimeo/psalm": "^6.0"
},
"suggest": {
"behat/mink-browserkit-driver": "^2.0",
@@ -43,7 +43,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-master": "2.3-dev"
}
},
"autoload": {

View File

@@ -14,24 +14,68 @@
</projectFiles>
<issueHandlers>
<UndefinedClass>
<errorLevel type="suppress">
<referencedClass name="Symfony\Component\BrowserKit\AbstractBrowser" />
<referencedClass name="Symfony\Component\BrowserKit\Client" />
<referencedClass name="Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator" />
</errorLevel>
</UndefinedClass>
<InvalidAttribute>
<errorLevel type="suppress">
<file name="src/Mink/MinkParameters.php" />
</errorLevel>
</InvalidAttribute>
<InvalidOperand>
<errorLevel type="suppress">
<file name="src/ServiceContainer/SymfonyExtension.php" />
</errorLevel>
</InvalidOperand>
<InvalidReturnStatement>
<errorLevel type="suppress">
<file name="src/Context/Environment/InitializedSymfonyExtensionEnvironment.php" />
</errorLevel>
</InvalidReturnStatement>
<InvalidReturnType>
<errorLevel type="suppress">
<file name="src/Context/Environment/InitializedSymfonyExtensionEnvironment.php" />
</errorLevel>
</InvalidReturnType>
<MissingTemplateParam>
<errorLevel type="suppress">
<file name="src/Mink/MinkParameters.php" />
</errorLevel>
</MissingTemplateParam>
<!-- Workaround for https://github.com/vimeo/psalm/issues/7026 -->
<ReservedWord>
<errorLevel type="suppress">
<directory name="src" />
</errorLevel>
</ReservedWord>
<UndefinedClass>
<errorLevel type="suppress">
<referencedClass name="Symfony\Component\BrowserKit\AbstractBrowser" />
<referencedClass name="Symfony\Component\BrowserKit\Client" />
<referencedClass name="Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator" />
</errorLevel>
</UndefinedClass>
<UndefinedInterfaceMethod>
<errorLevel type="suppress">
<file name="src/ServiceContainer/SymfonyExtension.php" />
</errorLevel>
</UndefinedInterfaceMethod>
<UnusedForeachValue>
<errorLevel type="suppress">
<file name="src/Bundle/DependencyInjection/FriendsOfBehatSymfonyExtensionExtension.php" />
<file name="src/ServiceContainer/SymfonyExtension.php" />
</errorLevel>
</UnusedForeachValue>
<UnusedMethodCall>
<errorLevel type="suppress">
<file name="src/ServiceContainer/SymfonyExtension.php" />
</errorLevel>
</UnusedMethodCall>
</issueHandlers>
</psalm>

View File

@@ -22,6 +22,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
final class FriendsOfBehatSymfonyExtensionExtension extends Extension implements CompilerPassInterface
{
#[\Override]
public function load(array $configs, ContainerBuilder $container): void
{
$this->provideMinkIntegration($container);
@@ -31,6 +32,7 @@ final class FriendsOfBehatSymfonyExtensionExtension extends Extension implements
$container->registerForAutoconfiguration(Context::class)->addTag('fob.context');
}
#[\Override]
public function process(ContainerBuilder $container): void
{
$this->provideBrowserKitIntegration($container);

View File

@@ -51,11 +51,13 @@ final class ContextServiceEnvironmentHandler implements EnvironmentHandler
$this->contextInitializers[] = $contextInitializer;
}
#[\Override]
public function supportsSuite(Suite $suite): bool
{
return $suite->hasSetting('contexts');
}
#[\Override]
public function buildEnvironment(Suite $suite): Environment
{
$symfonyContexts = [];
@@ -65,7 +67,6 @@ final class ContextServiceEnvironmentHandler implements EnvironmentHandler
continue;
}
/** @var object $service */
$service = $this->getContainer()->get($serviceId);
$symfonyContexts[$serviceId] = get_class($service);
@@ -79,6 +80,7 @@ final class ContextServiceEnvironmentHandler implements EnvironmentHandler
return new UninitializedSymfonyExtensionEnvironment($suite, $symfonyContexts, $delegatedEnvironment);
}
#[\Override]
public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null): bool
{
return $environment instanceof UninitializedSymfonyExtensionEnvironment;
@@ -87,6 +89,7 @@ final class ContextServiceEnvironmentHandler implements EnvironmentHandler
/**
* @throws EnvironmentIsolationException
*/
#[\Override]
public function isolateEnvironment(Environment $environment, $testSubject = null): Environment
{
$this->assertEnvironmentCanBeIsolated($environment, $testSubject);
@@ -158,7 +161,12 @@ final class ContextServiceEnvironmentHandler implements EnvironmentHandler
return new GenericSuite($suite->getName(), array_merge($suite->getSettings(), ['contexts' => $contexts]));
}
private function normalizeContext($context): string
/**
* @return (int|string)|false
*
* @psalm-return array-key|false
*/
private function normalizeContext($context)
{
if (is_array($context)) {
return current(array_keys($context));

View File

@@ -43,11 +43,13 @@ final class InitializedSymfonyExtensionEnvironment implements SymfonyExtensionEn
$this->contexts[get_class($context)] = $context;
}
#[\Override]
public function getSuite(): Suite
{
return $this->suite;
}
#[\Override]
public function bindCallee(Callee $callee): callable
{
$callable = $callee->getCallable();
@@ -59,16 +61,24 @@ final class InitializedSymfonyExtensionEnvironment implements SymfonyExtensionEn
return $callable;
}
#[\Override]
public function hasContexts(): bool
{
return count($this->contexts) > 0;
}
#[\Override]
/**
* @return key-of<TArray>[]
*
* @psalm-return list<key-of<class-string-map<T as Behat\Behat\Context\Context, T:class-string-map as Behat\Behat\Context\Context>>>
*/
public function getContextClasses(): array
{
return array_keys($this->contexts);
}
#[\Override]
public function hasContextClass($class): bool
{
return isset($this->contexts[$class]);

View File

@@ -42,16 +42,19 @@ final class UninitializedSymfonyExtensionEnvironment extends StaticEnvironment i
return array_keys($this->contexts);
}
#[\Override]
public function hasContexts(): bool
{
return count($this->contexts) > 0 || $this->delegatedEnvironment->hasContexts();
}
#[\Override]
public function getContextClasses(): array
{
return array_merge(array_values($this->contexts), $this->delegatedEnvironment->getContextClasses());
}
#[\Override]
public function hasContextClass($class): bool
{
return in_array($class, $this->contexts, true) || $this->delegatedEnvironment->hasContextClass($class);

View File

@@ -25,20 +25,24 @@ final class SymfonyDriverFactory implements DriverFactory
$this->kernel = $kernel;
}
#[\Override]
public function getDriverName(): string
{
return $this->name;
}
#[\Override]
public function supportsJavascript(): bool
{
return false;
}
#[\Override]
public function configure(ArrayNodeDefinition $builder): void
{
}
#[\Override]
public function buildDriver(array $config): Definition
{
if (!class_exists(BrowserKitDriver::class)) {

View File

@@ -6,8 +6,13 @@ namespace FriendsOfBehat\SymfonyExtension\Driver;
use Behat\Mink\Driver\BrowserKitDriver;
use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
/**
* @extends BrowserKitDriver<Request, Response>
*/
final class SymfonyDriver extends BrowserKitDriver
{
/** @var KernelInterface */
@@ -34,6 +39,7 @@ final class SymfonyDriver extends BrowserKitDriver
parent::__construct($this->createBrowser(), $this->baseUrl);
}
#[\Override]
public function reset()
{
parent::reset();
@@ -61,7 +67,6 @@ final class SymfonyDriver extends BrowserKitDriver
private function createBrowser(): AbstractBrowser
{
/** @var object $testClient */
$testClient = $this->kernel->getContainer()->get('test.client');
if (!$testClient instanceof AbstractBrowser) {

View File

@@ -28,6 +28,7 @@ final class KernelOrchestrator implements EventSubscriberInterface
$this->behatContainer = $behatContainer;
}
#[\Override]
public static function getSubscribedEvents(): array
{
return [

View File

@@ -6,6 +6,9 @@ namespace FriendsOfBehat\SymfonyExtension\Mink;
use Behat\Mink\Mink as BaseMink;
/**
* @deprecated use Behat\Mink\Mink instead, it will be removed on 3.0.
*/
class Mink extends BaseMink
{
/**
@@ -15,6 +18,7 @@ class Mink extends BaseMink
* in an invalid state. Therefore, not stopping all the sessions while destructing Mink
* saves our sanity.
*/
#[\Override]
public function __destruct()
{
// Intentionally left empty

View File

@@ -17,11 +17,13 @@ class MinkParameters implements \Countable, \IteratorAggregate, \ArrayAccess
$this->minkParameters = $minkParameters;
}
#[\Override]
public function getIterator(): \Traversable
{
return new \ArrayIterator($this->minkParameters);
}
#[\Override]
public function offsetExists($offset): bool
{
return array_key_exists($offset, $this->minkParameters);
@@ -30,22 +32,26 @@ class MinkParameters implements \Countable, \IteratorAggregate, \ArrayAccess
/**
* @return mixed
*/
#[\Override]
#[ReturnTypeWillChange]
public function offsetGet($offset)
{
return $this->minkParameters[$offset] ?? null;
}
#[\Override]
public function offsetSet($offset, $value): void
{
throw new \BadMethodCallException(sprintf('"%s" is immutable.', self::class));
}
#[\Override]
public function offsetUnset($offset): void
{
throw new \BadMethodCallException(sprintf('"%s" is immutable.', self::class));
}
#[\Override]
public function count(): int
{
return count($this->minkParameters);

View File

@@ -14,7 +14,6 @@ use Behat\Testwork\ServiceContainer\ExtensionManager;
use FriendsOfBehat\SymfonyExtension\Context\Environment\Handler\ContextServiceEnvironmentHandler;
use FriendsOfBehat\SymfonyExtension\Driver\Factory\SymfonyDriverFactory;
use FriendsOfBehat\SymfonyExtension\Listener\KernelOrchestrator;
use FriendsOfBehat\SymfonyExtension\Mink\Mink;
use FriendsOfBehat\SymfonyExtension\Mink\MinkParameters;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\Alias;
@@ -41,16 +40,19 @@ final class SymfonyExtension implements Extension
/** @var bool */
private $minkExtensionFound = false;
#[\Override]
public function getConfigKey(): string
{
return 'fob_symfony';
}
#[\Override]
public function initialize(ExtensionManager $extensionManager): void
{
$this->registerMinkDriver($extensionManager);
}
#[\Override]
public function configure(ArrayNodeDefinition $builder): void
{
$builder
@@ -70,6 +72,7 @@ final class SymfonyExtension implements Extension
;
}
#[\Override]
public function load(ContainerBuilder $container, array $config): void
{
$this->setupTestEnvironment($config['kernel']['environment'] ?? 'test');
@@ -90,13 +93,10 @@ final class SymfonyExtension implements Extension
}
}
#[\Override]
public function process(ContainerBuilder $container): void
{
$this->processEnvironmentHandler($container);
if ($this->minkExtensionFound) {
$container->getDefinition(MinkExtension::MINK_ID)->setClass(Mink::class);
}
}
private function registerMinkDriver(ExtensionManager $extensionManager): void