Skip to content

Commit 35234ef

Browse files
committed
feat: add all test files
1 parent f376f69 commit 35234ef

33 files changed

+716
-16
lines changed

src/AbstractException.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ abstract class AbstractException extends \Exception implements Throwable
1313

1414
public function __construct(ErrorMessage $errorMessage, ?\Throwable $previous = null, array $context = [])
1515
{
16+
17+
$this->context = array_merge(['code' => $errorMessage->getCode()], $context);
18+
1619
parent::__construct($errorMessage->getMessage(), 0, $previous);
17-
$this->context = $context;
1820
}
1921

2022
public function getContext(): array

src/Contract/ErrorMessage.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
interface ErrorMessage
88
{
9-
public function getCode(): string;
9+
public function getCode(): int;
10+
11+
public function getErrorCode(): string;
1012

1113
public function getMessage(): string;
1214
}

src/ExceptionMessage.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@
99
final class ExceptionMessage implements ErrorMessage
1010
{
1111
public function __construct(
12-
private readonly string $code,
12+
private readonly int $code,
13+
private readonly string $errorCode,
1314
private readonly string $message
1415
) {
1516
}
1617

17-
public function getCode(): string
18+
public function getCode(): int
1819
{
1920
return $this->code;
2021
}
2122

23+
public function getErrorCode(): string
24+
{
25+
return $this->errorCode;
26+
}
27+
2228
public function getMessage(): string
2329
{
2430
return $this->message;

tests/AbstractErrorMessageTest.php

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/AbstractExceptionTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,69 @@
11
<?php
22

33
declare(strict_types=1);
4+
5+
namespace KaririCode\Exception\Tests;
6+
7+
use KaririCode\Exception\AbstractException;
8+
use KaririCode\Exception\ExceptionMessage;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class AbstractExceptionTest extends TestCase
12+
{
13+
private ConcreteTestException $exception;
14+
15+
protected function setUp(): void
16+
{
17+
$errorMessage = new ExceptionMessage('TEST_CODE', 'Test message');
18+
$this->exception = new ConcreteTestException($errorMessage);
19+
}
20+
21+
public function testExceptionCreation(): void
22+
{
23+
$this->assertSame('Test message', $this->exception->getMessage());
24+
$this->assertSame(['code' => 'TEST_CODE'], $this->exception->getContext());
25+
}
26+
27+
public function testExceptionWithContext(): void
28+
{
29+
$errorMessage = new ExceptionMessage('TEST_CODE', 'Test message');
30+
$context = ['key' => 'value'];
31+
$exception = new ConcreteTestException($errorMessage, null, $context);
32+
33+
$this->assertSame(['code' => 'TEST_CODE', 'key' => 'value'], $exception->getContext());
34+
}
35+
36+
public function testAddContext(): void
37+
{
38+
$this->exception->addTestContext('newKey', 'newValue');
39+
40+
$expectedContext = ['code' => 'TEST_CODE', 'newKey' => 'newValue'];
41+
$this->assertSame($expectedContext, $this->exception->getContext());
42+
}
43+
44+
public function testExceptionWithPrevious(): void
45+
{
46+
$previousException = new \Exception('Previous exception');
47+
$errorMessage = new ExceptionMessage('TEST_CODE', 'Test message');
48+
$exception = new ConcreteTestException($errorMessage, $previousException);
49+
50+
$this->assertSame($previousException, $exception->getPrevious());
51+
}
52+
53+
protected function assertExceptionStructure(AbstractException $exception, string $expectedCode, string $expectedMessage): void
54+
{
55+
$this->assertInstanceOf(AbstractException::class, $exception);
56+
$this->assertSame($expectedMessage, $exception->getMessage());
57+
$this->assertArrayHasKey('code', $exception->getContext());
58+
$this->assertSame($expectedCode, $exception->getContext()['code']);
59+
}
60+
}
61+
62+
// Concrete implementation of AbstractException for testing
63+
final class ConcreteTestException extends AbstractException
64+
{
65+
public function addTestContext(string $key, mixed $value): self
66+
{
67+
return $this->addContext($key, $value);
68+
}
69+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
11
<?php
22

33
declare(strict_types=1);
4+
5+
namespace KaririCode\Exception\Tests\Auth;
6+
7+
use KaririCode\Exception\Auth\AuthenticationException;
8+
use KaririCode\Exception\Tests\AbstractExceptionTest;
9+
10+
final class AuthenticationExceptionTest extends AbstractExceptionTest
11+
{
12+
public function testInvalidCredentials(): void
13+
{
14+
$exception = AuthenticationException::invalidCredentials();
15+
$this->assertExceptionStructure($exception, 'INVALID_CREDENTIALS', 'Invalid credentials provided');
16+
}
17+
18+
public function testAccountLocked(): void
19+
{
20+
$exception = AuthenticationException::accountLocked();
21+
$this->assertExceptionStructure($exception, 'ACCOUNT_LOCKED', 'Account is locked');
22+
}
23+
24+
public function testTwoFactorRequired(): void
25+
{
26+
$exception = AuthenticationException::twoFactorRequired();
27+
$this->assertExceptionStructure($exception, 'TWO_FACTOR_REQUIRED', 'Two-factor authentication is required');
28+
}
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
11
<?php
22

33
declare(strict_types=1);
4+
5+
namespace KaririCode\Exception\Tests\Auth;
6+
7+
use KaririCode\Exception\Auth\AuthorizationException;
8+
use KaririCode\Exception\Tests\AbstractExceptionTest;
9+
10+
final class AuthorizationExceptionTest extends AbstractExceptionTest
11+
{
12+
public function testInsufficientPermissions(): void
13+
{
14+
$action = 'delete_user';
15+
$exception = AuthorizationException::insufficientPermissions($action);
16+
$this->assertExceptionStructure($exception, 'INSUFFICIENT_PERMISSIONS', "Insufficient permissions for action: {$action}");
17+
}
18+
19+
public function testRoleRequired(): void
20+
{
21+
$role = 'admin';
22+
$exception = AuthorizationException::roleRequired($role);
23+
$this->assertExceptionStructure($exception, 'ROLE_REQUIRED', "Required role not present: {$role}");
24+
}
25+
}

tests/Cache/CacheExceptionTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
11
<?php
22

33
declare(strict_types=1);
4+
5+
namespace KaririCode\Exception\Tests\Cache;
6+
7+
use KaririCode\Exception\Cache\CacheException;
8+
use KaririCode\Exception\Tests\AbstractExceptionTest;
9+
10+
final class CacheExceptionTest extends AbstractExceptionTest
11+
{
12+
public function testItemNotFound(): void
13+
{
14+
$key = 'user_profile_1';
15+
$exception = CacheException::itemNotFound($key);
16+
$this->assertExceptionStructure($exception, 'CACHE_ITEM_NOT_FOUND', "Cache item not found: {$key}");
17+
}
18+
19+
public function testStorageError(): void
20+
{
21+
$details = 'Redis connection failed';
22+
$exception = CacheException::storageError($details);
23+
$this->assertExceptionStructure($exception, 'CACHE_STORAGE_ERROR', "Cache storage error: {$details}");
24+
}
25+
26+
public function testInvalidTtl(): void
27+
{
28+
$ttl = -1;
29+
$exception = CacheException::invalidTtl($ttl);
30+
$this->assertExceptionStructure($exception, 'INVALID_TTL', "Invalid TTL value: {$ttl}");
31+
}
32+
}

tests/CommonErrorMessagesTest.php

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
11
<?php
22

33
declare(strict_types=1);
4+
5+
namespace KaririCode\Exception\Tests\Config;
6+
7+
use KaririCode\Exception\Config\ConfigurationException;
8+
use KaririCode\Exception\Tests\AbstractExceptionTest;
9+
10+
final class ConfigurationExceptionTest extends AbstractExceptionTest
11+
{
12+
public function testMissingKey(): void
13+
{
14+
$key = 'database.host';
15+
$exception = ConfigurationException::missingKey($key);
16+
$this->assertExceptionStructure($exception, 'MISSING_CONFIG_KEY', "Missing configuration key: {$key}");
17+
}
18+
19+
public function testInvalidValue(): void
20+
{
21+
$key = 'app.debug';
22+
$value = 'not_a_boolean';
23+
$exception = ConfigurationException::invalidValue($key, $value);
24+
$this->assertExceptionStructure($exception, 'INVALID_CONFIG_VALUE', "Invalid configuration value for key '{$key}': " . var_export($value, true));
25+
}
26+
27+
public function testEnvironmentNotSet(): void
28+
{
29+
$envVar = 'APP_KEY';
30+
$exception = ConfigurationException::environmentNotSet($envVar);
31+
$this->assertExceptionStructure($exception, 'ENVIRONMENT_NOT_SET', "Environment variable not set: {$envVar}");
32+
}
33+
}

0 commit comments

Comments
 (0)