create(new CreateSetDto( name: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', )); $element = $elementRepository->create(new CreateElementDto( set: $set, title: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', richText: '
A structured path for growth
', pdfPath: '/assets/pdfs/baderech.pdf', youtubeUrl: $sampleYoutubeUrl, parentElement: null, )); $firstChildElement = $elementRepository->create(new CreateElementDto( set: $set, title: 'Avodah Foundations', description: 'Foundations for steady avodah', iconImageUrl: null, richText: 'Foundations rich text
', pdfPath: '/assets/pdfs/foundations.pdf', youtubeUrl: null, parentElement: $element, )); $secondChildElement = $elementRepository->create(new CreateElementDto( set: $set, title: 'Daily Practice', description: 'Daily practices for growth', iconImageUrl: null, richText: 'Daily practice rich text
', pdfPath: null, youtubeUrl: null, parentElement: $element, )); $response = $this->getJson("/api/elements/{$element->getId()}"); $response->assertOk(); $response->assertExactJson([ 'childElements' => [ [ 'id' => $firstChildElement->getId(), 'title' => 'Avodah Foundations', 'description' => 'Foundations for steady avodah', ], [ 'id' => $secondChildElement->getId(), 'title' => 'Daily Practice', 'description' => 'Daily practices for growth', ], ], 'element' => [ 'id' => $element->getId(), 'title' => 'Baderech HaAvodah', 'description' => 'A structured path for growth', 'iconImageUrl' => '/assets/baderech-haavodah-icon.png', 'richText' => 'A structured path for growth
', 'pdfPath' => '/assets/pdfs/baderech.pdf', 'youtubeUrl' => $sampleYoutubeUrl, ], ]); } public function testReturns404WhenElementDoesNotExist(): void { $response = $this->getJson('/api/elements/999'); $response->assertNotFound(); $response->assertExactJson([ 'error' => 'Element not found', ]); } public function testUpdateRequiresAuthentication(): void { $setRepository = app(SetRepository::class); $elementRepository = app(ElementRepository::class); $set = $setRepository->create(new CreateSetDto( name: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', )); $element = $elementRepository->create(new CreateElementDto( set: $set, title: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', richText: 'A structured path for growth
', pdfPath: '/assets/pdfs/baderech.pdf', youtubeUrl: null, parentElement: null, )); $response = $this->patchJson("/api/elements/{$element->getId()}", [ 'title' => 'Updated title', 'description' => 'Updated description', 'iconImageUrl' => '/assets/updated-icon.png', 'richText' => 'Updated rich text
', 'pdfPath' => '/assets/pdfs/updated.pdf', 'youtubeUrl' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', ]); $response->assertUnauthorized(); $response->assertExactJson([ 'error' => 'unauthenticated', ]); } public function testAuthenticatedUpdateReturnsElementPayload(): void { $sampleYoutubeUrl = 'https://www.youtube.com/watch?v=' . 'dQw4w9WgXcQ'; $setRepository = app(SetRepository::class); $elementRepository = app(ElementRepository::class); $set = $setRepository->create(new CreateSetDto( name: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', )); $element = $elementRepository->create(new CreateElementDto( set: $set, title: 'Baderech HaAvodah', description: 'A structured path for growth', iconImageUrl: '/assets/baderech-haavodah-icon.png', richText: 'A structured path for growth
', pdfPath: '/assets/pdfs/baderech.pdf', youtubeUrl: null, parentElement: null, )); $this->createSession('valid-token'); $response = $this->withCredentials() ->withUnencryptedCookie('auth_token', 'valid-token') ->patchJson("/api/elements/{$element->getId()}", [ 'title' => 'Updated title', 'description' => 'Updated description', 'iconImageUrl' => '/assets/updated-icon.png', 'richText' => 'Updated rich text
', 'pdfPath' => '/assets/pdfs/updated.pdf', 'youtubeUrl' => $sampleYoutubeUrl, ]); $response->assertOk(); $response->assertExactJson([ 'element' => [ 'id' => $element->getId(), 'title' => 'Updated title', 'description' => 'Updated description', 'iconImageUrl' => '/assets/updated-icon.png', 'richText' => 'Updated rich text
', 'pdfPath' => '/assets/pdfs/updated.pdf', 'youtubeUrl' => $sampleYoutubeUrl, ], ]); $updatedElement = $elementRepository->find($element->getId()); $this->assertSame('Updated title', $updatedElement->getTitle()); $this->assertSame( 'Updated rich text
', $updatedElement->getRichText(), ); } 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'), ), )); } }