From 50df56a0cbfb5331d64ad91a748ab63f868aa79b Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Fri, 26 Jun 2026 10:50:21 +0300 Subject: [PATCH] test set creation endpoint --- backend/tests/Feature/SetsEndpointTest.php | 122 +++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/backend/tests/Feature/SetsEndpointTest.php b/backend/tests/Feature/SetsEndpointTest.php index 2f8264b..74592cc 100644 --- a/backend/tests/Feature/SetsEndpointTest.php +++ b/backend/tests/Feature/SetsEndpointTest.php @@ -2,11 +2,20 @@ namespace Tests\Feature; +use App\Auth\CreateSessionDto; +use App\Auth\SessionRepository; use App\Element\CreateElementDto; use App\Element\ElementRepository; use App\Set\CreateSetDto; use App\Set\SetRepository; +use App\Shared\ValueObject\EmailAddress; +use App\User\CreateUserDto; +use App\User\UserRepository; +use DateTimeImmutable; +use DateTimeZone; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Http\UploadedFile; +use Illuminate\Support\Facades\Storage; use Tests\TestCase; class SetsEndpointTest extends TestCase @@ -63,4 +72,117 @@ class SetsEndpointTest extends TestCase ], ]); } + + public function testCreateSetRequiresAuthentication(): void + { + $response = $this->postJson('/api/sets', [ + 'name' => 'New Series', + 'description' => 'A new learning series', + ]); + + $response->assertUnauthorized(); + $response->assertExactJson([ + 'error' => 'unauthenticated', + ]); + } + + public function testAuthenticatedCreateSetCreatesRootElement(): void + { + Storage::fake('public'); + $setRepository = app(SetRepository::class); + $elementRepository = app(ElementRepository::class); + $this->createSession('valid-token'); + + $response = $this->withCredentials() + ->withUnencryptedCookie('auth_token', 'valid-token') + ->post('/api/sets', [ + 'name' => 'New Series', + 'description' => 'A new learning series', + 'iconImage' => $this->iconImageUpload(), + ]); + + $response->assertCreated(); + $body = $response->json(); + $setId = $body['set']['id']; + $rootElementId = $body['set']['rootElementId']; + $this->assertIsInt($setId); + $this->assertIsInt($rootElementId); + $this->assertSame('New Series', $body['set']['name']); + $this->assertSame( + 'A new learning series', + $body['set']['description'], + ); + $this->assertStringContainsString( + '/storage/set-icons/', + $body['set']['iconImageUrl'], + ); + + $createdSet = $setRepository->find($setId); + $this->assertNotNull($createdSet); + $rootElement = $elementRepository->findRootBySet($createdSet); + $this->assertNotNull($rootElement); + $this->assertSame($rootElementId, $rootElement->getId()); + $this->assertSame('New Series', $rootElement->getTitle()); + $this->assertSame( + 'A new learning series', + $rootElement->getDescription(), + ); + $storedIconPath = $createdSet->getIconImageUrl(); + $this->assertStringStartsWith('set-icons/', $storedIconPath); + $this->assertSame($storedIconPath, $rootElement->getIconImageUrl()); + Storage::disk('public')->assertExists($storedIconPath); + } + + public function testCreateSetRequiresIconImage(): void + { + $this->createSession('valid-token'); + + $response = $this->withCredentials() + ->withUnencryptedCookie('auth_token', 'valid-token') + ->post('/api/sets', [ + 'name' => 'New Series', + 'description' => 'A new learning series', + ]); + + $response->assertBadRequest(); + $response->assertExactJson([ + 'error' => 'icon image is required', + ]); + } + + private function createSession(string $token): void + { + $userRepository = app(UserRepository::class); + $sessionRepository = app(SessionRepository::class); + $user = $userRepository->create(new CreateUserDto( + email: new EmailAddress('admin@example.com'), + passwordHash: 'password-hash', + )); + $now = new DateTimeImmutable( + '2026-05-01T00:00:00', + new DateTimeZone('UTC'), + ); + $sessionRepository->create(new CreateSessionDto( + token: $token, + user: $user, + createdAt: $now, + expiresAt: new DateTimeImmutable( + '2099-01-01T00:00:00', + new DateTimeZone('UTC'), + ), + )); + } + + private function iconImageUpload(): UploadedFile + { + $fixturePath = __DIR__ . '/../fixtures/icon.png'; + + return new UploadedFile( + $fixturePath, + 'icon.png', + 'image/png', + null, + true, + ); + } }