* @category Class * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License * @link www.splendidbear.org * @since 2026. 04. 21. */ #[AllowMockObjectsWithoutExpectations] #[TestDox('Recaptcha Service')] class RecaptchaServiceTest extends TestCase { private const API_ENDPOINT = 'http://localhost:3000/test-site-key/'; private const SECRET_KEY = 'test-secret-key'; #[Test] #[TestDox('Verify returns false for empty token')] public function verifyReturnsFalseForEmptyToken(): void { $httpClient = $this->createMock(HttpClientInterface::class); $logger = $this->createMock(LoggerInterface::class); $service = new RecaptchaService($httpClient, $logger, self::API_ENDPOINT, self::SECRET_KEY); $result = $service->verify(''); $this->assertFalse($result); } #[Test] #[TestDox('Verify returns false when api returns failure')] public function verifyReturnsFalseWhenApiReturnsFailure(): void { $mockResponse = new MockResponse(json_encode([ 'success' => false, ], JSON_THROW_ON_ERROR)); $httpClient = new MockHttpClient($mockResponse); $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once())->method('info'); $service = new RecaptchaService($httpClient, $logger, self::API_ENDPOINT, self::SECRET_KEY); $result = $service->verify('invalid-token'); $this->assertFalse($result); } #[Test] #[TestDox('Verify returns true when api returns success')] public function verifyReturnsTrueWhenApiReturnsSuccess(): void { $mockResponse = new MockResponse(json_encode([ 'success' => true, ], JSON_THROW_ON_ERROR)); $httpClient = new MockHttpClient($mockResponse); $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once())->method('info'); $service = new RecaptchaService($httpClient, $logger, self::API_ENDPOINT, self::SECRET_KEY); $result = $service->verify('valid-token'); $this->assertTrue($result); } #[Test] #[TestDox('Verify returns false when api throws exception')] public function verifyReturnsFalseWhenApiThrowsException(): void { $mockResponse = new MockResponse('', ['http_code' => 500]); $httpClient = new MockHttpClient($mockResponse); $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once())->method('error'); $service = new RecaptchaService($httpClient, $logger, self::API_ENDPOINT, self::SECRET_KEY); $result = $service->verify('test-token'); $this->assertFalse($result); } #[Test] #[TestDox('Siteverify URL is derived from api endpoint')] public function siteverifyUrlIsDerivedFromApiEndpoint(): void { $mockResponse = new MockResponse(json_encode(['success' => true], JSON_THROW_ON_ERROR)); $httpClient = new MockHttpClient(function (string $method, string $url) use ($mockResponse): MockResponse { $this->assertSame('http://localhost:3000/test-site-key/siteverify', $url); return $mockResponse; }); $logger = $this->createMock(LoggerInterface::class); $service = new RecaptchaService($httpClient, $logger, self::API_ENDPOINT, self::SECRET_KEY); $service->verify('test-token'); } }