new: pkg: add test cases to back-end w/ real database connection in it #10
This commit is contained in:
109
tests/Service/MercureJwtServiceTest.php
Normal file
109
tests/Service/MercureJwtServiceTest.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the SplendidBear Websites' projects.
|
||||
*
|
||||
* Copyright (c) 2026 @ www.splendidbear.org
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Service;
|
||||
|
||||
use App\Service\MercureJwtService;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\TestDox;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Class MercureJwtServiceTest
|
||||
*
|
||||
* @package App\Tests\Service
|
||||
* @author Lang <https://www.splendidbear.org>
|
||||
* @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.
|
||||
*/
|
||||
#[TestDox('Mercure Jwt Service')]
|
||||
class MercureJwtServiceTest extends TestCase
|
||||
{
|
||||
/** JWT HS256 requires at least 32 characters for the secret key */
|
||||
private const SECRET = 'test-mercure-secret-key-12345678901234567890';
|
||||
|
||||
private MercureJwtService $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->service = new MercureJwtService(self::SECRET);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Mint subscriber token returns valid jwt')]
|
||||
public function mintSubscriberTokenReturnsValidJwt(): void
|
||||
{
|
||||
$token = $this->service->mintSubscriberToken('game123', 'player1');
|
||||
|
||||
$this->assertIsString($token);
|
||||
$this->assertNotEmpty($token);
|
||||
|
||||
/** Token should have 3 parts (header.payload.signature) */
|
||||
$parts = explode('.', $token);
|
||||
$this->assertCount(3, $parts);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Mint subscriber token with different game assoc')]
|
||||
public function mintSubscriberTokenWithDifferentGameAssoc(): void
|
||||
{
|
||||
$token1 = $this->service->mintSubscriberToken('gameA', 'player1');
|
||||
$token2 = $this->service->mintSubscriberToken('gameB', 'player1');
|
||||
|
||||
/** Different gameAssoc should result in different tokens */
|
||||
$this->assertNotSame($token1, $token2);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Mint subscriber token with different user names')]
|
||||
public function mintSubscriberTokenWithDifferentUserNames(): void
|
||||
{
|
||||
$token1 = $this->service->mintSubscriberToken('game1', 'playerA');
|
||||
$token2 = $this->service->mintSubscriberToken('game1', 'playerB');
|
||||
|
||||
/** Different usernames should result in different tokens */
|
||||
$this->assertNotSame($token1, $token2);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Mint subscriber token contains proper structure')]
|
||||
public function mintSubscriberTokenContainsProperStructure(): void
|
||||
{
|
||||
$token = $this->service->mintSubscriberToken('game123', 'testplayer');
|
||||
|
||||
/** Decode without verification to check structure */
|
||||
$parts = explode('.', $token);
|
||||
|
||||
/** Decode payload (middle part) */
|
||||
$payload = json_decode(base64_decode($parts[1] . str_repeat('=', (4 - strlen($parts[1]) % 4))), true);
|
||||
|
||||
$this->assertIsArray($payload);
|
||||
$this->assertArrayHasKey('mercure', $payload);
|
||||
$this->assertArrayHasKey('subscribe', $payload['mercure']);
|
||||
$this->assertArrayHasKey('payload', $payload['mercure']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Mint subscriber token payload contains correct data')]
|
||||
public function mintSubscriberTokenPayloadContainsCorrectData(): void
|
||||
{
|
||||
$token = $this->service->mintSubscriberToken('test-game', 'test-user');
|
||||
|
||||
$parts = explode('.', $token);
|
||||
$payload = json_decode(base64_decode($parts[1] . str_repeat('=', (4 - strlen($parts[1]) % 4))), true);
|
||||
|
||||
$this->assertSame('test-user', $payload['mercure']['payload']['username']);
|
||||
$this->assertSame('test-game', $payload['mercure']['payload']['gameAssoc']);
|
||||
$this->assertContains('*', $payload['mercure']['subscribe']);
|
||||
}
|
||||
}
|
||||
188
tests/Service/RecaptchaServiceTest.php
Normal file
188
tests/Service/RecaptchaServiceTest.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the SplendidBear Websites' projects.
|
||||
*
|
||||
* Copyright (c) 2026 @ www.splendidbear.org
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Service;
|
||||
|
||||
use App\Service\RecaptchaService;
|
||||
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\TestDox;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpClient\MockHttpClient;
|
||||
use Symfony\Component\HttpClient\Response\MockResponse;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
/**
|
||||
* Class RecaptchaServiceTest
|
||||
*
|
||||
* @package App\Tests\Service
|
||||
* @author Lang <https://www.splendidbear.org>
|
||||
* @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 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::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,
|
||||
'error-codes' => ['invalid-input-secret'],
|
||||
], 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::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('invalid-token');
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Verify returns true when api returns success and high score')]
|
||||
public function verifyReturnsTrueWhenApiReturnsSuccessAndHighScore(): void
|
||||
{
|
||||
$mockResponse = new MockResponse(json_encode([
|
||||
'success' => true,
|
||||
'score' => 0.8,
|
||||
'hostname' => 'test.com',
|
||||
], 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::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('valid-token');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Verify returns false when score below threshold')]
|
||||
public function verifyReturnsFalseWhenScoreBelowThreshold(): void
|
||||
{
|
||||
$mockResponse = new MockResponse(json_encode([
|
||||
'success' => true,
|
||||
'score' => 0.3,
|
||||
'hostname' => 'test.com',
|
||||
], 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::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('low-score-token');
|
||||
|
||||
$this->assertFalse($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::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('test-token');
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Verify includes remote ip when provided')]
|
||||
public function verifyIncludesRemoteIpWhenProvided(): void
|
||||
{
|
||||
$mockResponse = new MockResponse(json_encode([
|
||||
'success' => true,
|
||||
'score' => 0.9,
|
||||
], 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::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('test-token', '192.168.1.1');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Verify with score at threshold')]
|
||||
public function verifyWithScoreAtThreshold(): void
|
||||
{
|
||||
$mockResponse = new MockResponse(json_encode([
|
||||
'success' => true,
|
||||
'score' => 0.5,
|
||||
], JSON_THROW_ON_ERROR));
|
||||
|
||||
$httpClient = new MockHttpClient($mockResponse);
|
||||
$logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
$service = new RecaptchaService($httpClient, $logger, self::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('threshold-token');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[TestDox('Verify with no score fails')]
|
||||
public function verifyWithNoScoreFails(): void
|
||||
{
|
||||
$mockResponse = new MockResponse(json_encode([
|
||||
'success' => true,
|
||||
], JSON_THROW_ON_ERROR));
|
||||
|
||||
$httpClient = new MockHttpClient($mockResponse);
|
||||
$logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
$service = new RecaptchaService($httpClient, $logger, self::SECRET_KEY);
|
||||
|
||||
$result = $service->verify('no-score-token');
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user