From 28d986ff7b716f822d9d0b15be404c493c450c8a Mon Sep 17 00:00:00 2001 From: turegjorup Date: Thu, 11 Jun 2026 11:07:38 +0200 Subject: [PATCH] test: pin request factory wiring and zero-boundary option values Mutation testing showed the constructor's setRequestFactory call could be removed (silently falling back to the parent's default factory) and the < 0 guards on cacheDuration/leeway could become <= 0 (rejecting the valid boundary value 0) without a failing test. Kills 3 escaped mutants. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 7 ++++ .../OpenIdConfigurationProviderTest.php | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b50b6e..c5b0a7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Strengthened constructor tests guided by mutation testing: the `jwt` + collaborator is asserted to become the request factory, and `0` is + asserted to be an accepted boundary value for `cacheDuration` and + `leeway` + ## [5.0.0] - 2026-06-02 Reworked exception hierarchy and tightened IdP-payload validations. The runtime diff --git a/tests/Security/OpenIdConfigurationProviderTest.php b/tests/Security/OpenIdConfigurationProviderTest.php index 9bffc5d..234a4a8 100644 --- a/tests/Security/OpenIdConfigurationProviderTest.php +++ b/tests/Security/OpenIdConfigurationProviderTest.php @@ -20,6 +20,7 @@ use ItkDev\OpenIdConnect\Security\OpenIdConfigurationProvider; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use League\OAuth2\Client\Token\AccessToken; +use League\OAuth2\Client\Tool\RequestFactory; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemInterface; @@ -124,6 +125,40 @@ public function testConstructLeeway(): void ], []); } + public function testConstructZeroCacheDurationAndLeewayAccepted(): void + { + $mockCacheItemPool = $this->createStub(CacheItemPoolInterface::class); + + // Zero is a valid boundary value for both options: cache nothing, + // tolerate no clock skew. Only negative values are rejected. + $provider = new OpenIdConfigurationProvider([ + 'cacheItemPool' => $mockCacheItemPool, + 'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration', + 'cacheDuration' => 0, + 'leeway' => 0, + ], []); + + $this->assertInstanceOf(OpenIdConfigurationProvider::class, $provider); + } + + public function testConstructWiresJwtCollaboratorAsRequestFactory(): void + { + $mockCacheItemPool = $this->createStub(CacheItemPoolInterface::class); + $requestFactory = new RequestFactory(); + + $provider = new OpenIdConfigurationProvider([ + 'cacheItemPool' => $mockCacheItemPool, + 'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration', + ], [ + 'jwt' => $requestFactory, + ]); + + // The 'jwt' collaborator must become the provider's request factory; + // without the explicit wiring the parent's default factory would be + // silently used instead. + $this->assertSame($requestFactory, $provider->getRequestFactory()); + } + public function testGenerateState(): void { $state = $this->provider->generateState(32);