From c3c51d4ccda414d6be4a72f871017df1c2744034 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 31 Mar 2026 20:34:41 -0300 Subject: [PATCH] feat: add ErrorCategory enum and SocialPublishException base class --- app/Exceptions/Social/ErrorCategory.php | 15 ++++ .../Social/SocialPublishException.php | 37 ++++++++ .../Social/SocialPublishExceptionTest.php | 86 +++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 app/Exceptions/Social/ErrorCategory.php create mode 100644 app/Exceptions/Social/SocialPublishException.php create mode 100644 tests/Unit/Exceptions/Social/SocialPublishExceptionTest.php diff --git a/app/Exceptions/Social/ErrorCategory.php b/app/Exceptions/Social/ErrorCategory.php new file mode 100644 index 00000000..4000c1a1 --- /dev/null +++ b/app/Exceptions/Social/ErrorCategory.php @@ -0,0 +1,15 @@ + $this->platform(), + 'category' => $this->category->value, + 'platform_error_code' => $this->platformErrorCode, + 'user_message' => $this->userMessage, + 'raw_response' => $this->rawResponse, + ]; + } + + abstract public static function fromApiResponse(mixed $response): static; + + abstract public function platform(): string; +} diff --git a/tests/Unit/Exceptions/Social/SocialPublishExceptionTest.php b/tests/Unit/Exceptions/Social/SocialPublishExceptionTest.php new file mode 100644 index 00000000..4611ba24 --- /dev/null +++ b/tests/Unit/Exceptions/Social/SocialPublishExceptionTest.php @@ -0,0 +1,86 @@ +context())->toBe([ + 'platform' => 'test_platform', + 'category' => 'media_format', + 'platform_error_code' => 'MEDIA_TOO_LARGE', + 'user_message' => 'Your image is too large for Instagram.', + 'raw_response' => '{"error": "image too large"}', + ]); +}); + +test('context returns null for optional fields when not provided', function () { + $exception = new TestPlatformException( + userMessage: 'Something went wrong.', + category: ErrorCategory::Unknown, + ); + + expect($exception->context())->toBe([ + 'platform' => 'test_platform', + 'category' => 'unknown', + 'platform_error_code' => null, + 'user_message' => 'Something went wrong.', + 'raw_response' => null, + ]); +}); + +test('exception message matches user message', function () { + $exception = new TestPlatformException( + userMessage: 'Rate limit exceeded.', + category: ErrorCategory::RateLimit, + ); + + expect($exception->getMessage())->toBe('Rate limit exceeded.'); +}); + +test('fromApiResponse creates exception from response', function () { + $exception = TestPlatformException::fromApiResponse(['error' => 'test']); + + expect($exception) + ->toBeInstanceOf(SocialPublishException::class) + ->and($exception->userMessage)->toBe('Test error') + ->and($exception->category)->toBe(ErrorCategory::Unknown) + ->and($exception->rawResponse)->toBe('{"error":"test"}'); +}); + +test('error category enum has all expected cases', function () { + expect(ErrorCategory::cases())->toHaveCount(6) + ->and(ErrorCategory::MediaFormat->value)->toBe('media_format') + ->and(ErrorCategory::RateLimit->value)->toBe('rate_limit') + ->and(ErrorCategory::Permission->value)->toBe('permission') + ->and(ErrorCategory::ContentPolicy->value)->toBe('content_policy') + ->and(ErrorCategory::ServerError->value)->toBe('server_error') + ->and(ErrorCategory::Unknown->value)->toBe('unknown'); +});