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
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ This is a library/bundle — there is no runnable application here. It is exerci

PHP 8.1+ is required (CI runs 8.1 and 8.2). Use the `8.1`/`8.2` shell switchers if needed. The dev tooling is the individually-pinned set from `setono/code-quality-pack` (inlined into `require-dev` rather than depending on the meta-package); PHPUnit is held at `^10.5` so PHP 8.1 stays supported (PHPUnit 11 needs 8.2).

- Tests: `composer phpunit` (or `vendor/bin/phpunit`)
- Single test: `vendor/bin/phpunit --filter after_loading_the_correct_parameter_has_been_set` or by path `vendor/bin/phpunit tests/DependencyInjection/SetonoClientExtensionTest.php`
- Tests: `composer phpunit` (or `vendor/bin/phpunit`). Unit tests live in `tests/Unit` (the `unit` suite: `vendor/bin/phpunit --testsuite unit`)
Comment thread
loevgaard marked this conversation as resolved.
- Single test: `vendor/bin/phpunit --filter after_loading_the_correct_parameter_has_been_set` or by path `vendor/bin/phpunit tests/Unit/DependencyInjection/SetonoClientExtensionTest.php`
- Static analysis: `composer analyse` (PHPStan at `level: max`, config in `phpstan.neon.dist`; auto-loads the doctrine/symfony/phpunit/strict-rules extensions via `phpstan/extension-installer`)
- Check style: `composer check-style` (ECS, Sylius Labs ruleset)
- Fix style: `composer fix-style`
Expand Down Expand Up @@ -69,4 +69,4 @@ setono_client:

- Strict types everywhere (`declare(strict_types=1)`); concrete classes are `final`, except the metadata/entity classes (`ChangeAwareMetadata`, `LazyChangeAwareMetadata`, `Entity\Metadata`) which are intentionally extensible.
- New services go in `config/services.xml` using the `setono_client.<concern>.<variant>` id scheme, with a `setono_client.<concern>.default` alias and an interface alias for autowiring. To insert behavior into a chain, add a decorator with an appropriate `decoration-priority` rather than editing existing classes.
- Tests use `matthiasnoback/symfony-dependency-injection-test` (e.g. `AbstractExtensionTestCase`) and Prophecy (`ProphecyTrait`), with the `@test` annotation and snake_case method-name style. Keep the suite at 100% MSI — when adding logic, add a test that kills the corresponding mutant.
- Tests use `matthiasnoback/symfony-dependency-injection-test` (e.g. `AbstractExtensionTestCase`), `matthiasnoback/symfony-config-test` (`ConfigurationTestCaseTrait`) and Prophecy (`ProphecyTrait`), with the `@test` annotation and snake_case method-name style. Keep the suite at 100% MSI — when adding logic, add a test that kills the corresponding mutant.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"ergebnis/composer-normalize": "^2.50",
"infection/infection": "^0.27 || ^0.28",
"jangregor/phpstan-prophecy": "^2.3",
"matthiasnoback/symfony-config-test": "^4.3 || ^5.1",
"matthiasnoback/symfony-dependency-injection-test": "^4.3.1 || ^5.1",
"phpspec/prophecy": "^1.20",
"phpspec/prophecy-phpunit": "^2.5",
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ parameters:
identifier: constructor.call
path: src/MetadataProvider/DoctrineOrmBasedMetadataProvider.php
count: 1
-
identifier: constructor.call
path: tests/Unit/MetadataPersister/DoctrineOrmBasedMetadataPersisterTest.php
count: 1
4 changes: 2 additions & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php"
colors="true" cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Setono Client Bundle Test Suite">
<directory>tests</directory>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<logging/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Client;
namespace Setono\ClientBundle\Tests\Unit\Client;

use PHPUnit\Framework\TestCase;
use Setono\ClientBundle\Client\ChangeAwareMetadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Context;
namespace Setono\ClientBundle\Tests\Unit\Context;
Comment thread
loevgaard marked this conversation as resolved.

use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Context;
namespace Setono\ClientBundle\Tests\Unit\Context;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Context;
namespace Setono\ClientBundle\Tests\Unit\Context;

use PHPUnit\Framework\TestCase;
use Setono\ClientBundle\Client\ChangeAwareMetadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Controller;
namespace Setono\ClientBundle\Tests\Unit\Controller;

use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\CookieProvider;
namespace Setono\ClientBundle\Tests\Unit\CookieProvider;

use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
Expand Down Expand Up @@ -47,6 +47,44 @@ public function it_resolves_the_cookie_once_per_request(): void
self::assertSame($cookie, $provider->getCookie($request));
}

/**
* @test
*/
public function it_caches_a_missing_cookie(): void
Comment thread
loevgaard marked this conversation as resolved.
{
$request = new Request();

$decorated = $this->prophesize(CookieProviderInterface::class);
$decorated->getCookie($request)->willReturn(null)->shouldBeCalledOnce();

$provider = new CachedCookieProvider($decorated->reveal(), new RequestStack());

self::assertNull($provider->getCookie($request));
self::assertNull($provider->getCookie($request));
}

/**
* @test
*/
public function it_resolves_the_cookie_of_each_request_separately(): void
Comment thread
loevgaard marked this conversation as resolved.
{
// The requests are equal, so only their identity tells them apart. Prophecy compares arguments with ==, so the stub checks the identity itself
$firstRequest = new Request();
$firstCookie = new Cookie('first-client-id');
$secondRequest = new Request();
$secondCookie = new Cookie('second-client-id');

$decorated = $this->prophesize(CookieProviderInterface::class);
$decorated->getCookie(Argument::type(Request::class))->will(
static fn (array $arguments): Cookie => $arguments[0] === $firstRequest ? $firstCookie : $secondCookie,
);

$provider = new CachedCookieProvider($decorated->reveal(), new RequestStack());

self::assertSame($firstCookie, $provider->getCookie($firstRequest));
self::assertSame($secondCookie, $provider->getCookie($secondRequest));
}

/**
* @test
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\CookieProvider;
namespace Setono\ClientBundle\Tests\Unit\CookieProvider;
Comment thread
loevgaard marked this conversation as resolved.

use PHPUnit\Framework\TestCase;
use Setono\Client\Cookie;
Expand Down
73 changes: 73 additions & 0 deletions tests/Unit/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Unit\DependencyInjection;

use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
use PHPUnit\Framework\TestCase;
use Setono\ClientBundle\DependencyInjection\Configuration;
use Setono\ClientBundle\Entity\Metadata;
use Setono\ClientBundle\Tests\Unit\DependencyInjection\Fixture\CustomMetadata;

final class ConfigurationTest extends TestCase
{
use ConfigurationTestCaseTrait;

protected function getConfiguration(): Configuration
{
return new Configuration();
}

/**
* @test
*/
public function it_has_default_values(): void
{
$this->assertProcessedConfigurationEquals([], [
'cookie' => [
'name' => 'setono_client_id',
'expiration' => '+365 days',
],
'metadata_class' => Metadata::class,
]);
}

/**
* @test
*/
public function it_allows_overriding_the_values(): void
{
$this->assertProcessedConfigurationEquals([
[
Comment thread
loevgaard marked this conversation as resolved.
'cookie' => [
'name' => 'client_id',
'expiration' => '+30 days',
],
'metadata_class' => CustomMetadata::class,
],
], [
'cookie' => [
'name' => 'client_id',
'expiration' => '+30 days',
],
'metadata_class' => CustomMetadata::class,
]);
}

/**
* @test
*/
public function it_keeps_the_default_of_a_cookie_option_that_is_not_overridden(): void
{
$this->assertProcessedConfigurationEquals([
['cookie' => ['name' => 'client_id']],
], [
'cookie' => [
'name' => 'client_id',
'expiration' => '+365 days',
],
'metadata_class' => Metadata::class,
]);
}
}
11 changes: 11 additions & 0 deletions tests/Unit/DependencyInjection/Fixture/CustomMetadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Unit\DependencyInjection\Fixture;

use Setono\ClientBundle\Entity\Metadata;

final class CustomMetadata extends Metadata
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\DependencyInjection;
namespace Setono\ClientBundle\Tests\Unit\DependencyInjection;

use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
use Setono\ClientBundle\Context\ClientContextInterface;
use Setono\ClientBundle\Context\DefaultClientContext;
use Setono\ClientBundle\CookieProvider\RequestBasedCookieProvider;
use Setono\ClientBundle\DependencyInjection\SetonoClientExtension;
use Setono\ClientBundle\Entity\Metadata;
use Setono\ClientBundle\Tests\Unit\DependencyInjection\Fixture\CustomMetadata;

final class SetonoClientExtensionTest extends AbstractExtensionTestCase
{
Expand All @@ -32,6 +33,24 @@ public function after_loading_the_correct_parameter_has_been_set(): void
$this->assertContainerBuilderHasParameter('setono_client.metadata_class', Metadata::class);
}

/**
* @test
*/
public function after_loading_with_custom_values_the_parameters_reflect_them(): void
{
$this->load([
'cookie' => [
'name' => 'client_id',
'expiration' => '+30 days',
],
'metadata_class' => CustomMetadata::class,
Comment thread
loevgaard marked this conversation as resolved.
]);

$this->assertContainerBuilderHasParameter('setono_client.cookie.name', 'client_id');
$this->assertContainerBuilderHasParameter('setono_client.cookie.expiration', '+30 days');
$this->assertContainerBuilderHasParameter('setono_client.metadata_class', CustomMetadata::class);
}

/**
* @test
*/
Expand All @@ -44,6 +63,21 @@ public function after_loading_the_services_are_registered(): void
$this->assertContainerBuilderHasAlias(ClientContextInterface::class, 'setono_client.client_context.default');
}

/**
* @test
*/
public function after_loading_the_services_hooking_into_symfony_and_doctrine_are_tagged(): void
{
$this->load();

$this->assertContainerBuilderHasServiceDefinitionWithTag('setono_client.event_subscriber.store_cookie', 'kernel.event_subscriber');
$this->assertContainerBuilderHasServiceDefinitionWithTag('setono_client.event_subscriber.store_metadata', 'kernel.event_subscriber');
$this->assertContainerBuilderHasServiceDefinitionWithTag('setono_client.controller.client_value_resolver', 'controller.argument_value_resolver');
$this->assertContainerBuilderHasServiceDefinitionWithTag('setono_client.event_listener_doctrine.convert_to_entity', 'doctrine.event_listener', [
'event' => 'loadClassMetadata',
]);
}

/**
* @test
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\Entity;
namespace Setono\ClientBundle\Tests\Unit\Entity;

use PHPUnit\Framework\TestCase;
use Setono\ClientBundle\Entity\Metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\ClientBundle\Tests\EventListener\Doctrine;
namespace Setono\ClientBundle\Tests\Unit\EventListener\Doctrine;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
Expand Down
Loading
Loading