setRepo = new FakeSetRepository(); $this->elementRepo = new FakeElementRepository(); $this->createElement = new CreateElement( $this->elementRepo, $this->setRepo, ); } private function createSet(string $name): DomainSet { return $this->setRepo->create(new CreateSetDto( name: $name, description: "$name description", iconImageUrl: '/assets/test-set-icon.svg', )); } public function testCreatesRootElement(): void { $set = $this->createSet('Daily learning'); $element = $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: '/assets/pdfs/root.pdf', youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s', parentElementId: null, )); $this->assertInstanceOf(Element::class, $element); $this->assertSame('Root', $element->getTitle()); $this->assertSame('Root description', $element->getDescription()); $this->assertSame('

Root rich text

', $element->getRichText()); $this->assertSame('/assets/pdfs/root.pdf', $element->getPdfPath()); $this->assertSame( 'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s', $element->getYoutubeUrl(), ); $this->assertSame($set->getId(), $element->getSet()->getId()); $this->assertNull($element->getParentElement()); } public function testCreatesChildElement(): void { $set = $this->createSet('Daily learning'); $rootElement = $this->createElement->execute( new CreateElementRequest( setId: $set->getId(), title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, ) ); $childElement = $this->createElement->execute( new CreateElementRequest( setId: $set->getId(), title: 'Child', description: 'Child description', richText: '

Child rich text

', pdfPath: '/assets/pdfs/child.pdf', youtubeUrl: 'https://youtu.be/yHx-r4p6hHU', parentElementId: $rootElement->getId(), ) ); $this->assertSame('Child', $childElement->getTitle()); $this->assertSame( 'Child description', $childElement->getDescription(), ); $this->assertSame( '

Child rich text

', $childElement->getRichText(), ); $this->assertSame( '/assets/pdfs/child.pdf', $childElement->getPdfPath(), ); $this->assertSame( 'https://youtu.be/yHx-r4p6hHU', $childElement->getYoutubeUrl(), ); $this->assertSame( $rootElement->getId(), $childElement->getParentElement()->getId(), ); } public function testCreatesElementWithBlankContentWhenMissing(): void { $set = $this->createSet('Daily learning'); $element = $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', description: null, richText: null, pdfPath: null, youtubeUrl: null, parentElementId: null, )); $this->assertSame('', $element->getDescription()); $this->assertSame('', $element->getRichText()); $this->assertNull($element->getPdfPath()); $this->assertNull($element->getYoutubeUrl()); } public function testCreatesElementWithNullPdfPathWhenBlank(): void { $set = $this->createSet('Daily learning'); $element = $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: '', youtubeUrl: null, parentElementId: null, )); $this->assertNull($element->getPdfPath()); } public function testCreatesElementWithNullYoutubeUrlWhenBlank(): void { $set = $this->createSet('Daily learning'); $element = $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: '', parentElementId: null, )); $this->assertNull($element->getYoutubeUrl()); } public function testThrowsWhenSetIdMissing(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('setId is required'); $this->createElement->execute(new CreateElementRequest( setId: null, title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, )); } public function testThrowsWhenTitleMissing(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('title is required'); $this->createElement->execute(new CreateElementRequest( setId: 1, title: null, description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, )); } public function testThrowsWhenSetDoesNotExist(): void { $this->expectException(DomainException::class); $this->expectExceptionMessage('Set with id: 99 doesnt exist'); $this->createElement->execute(new CreateElementRequest( setId: 99, title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, )); } public function testThrowsWhenParentElementDoesNotExist(): void { $set = $this->createSet('Daily learning'); $this->expectException(DomainException::class); $this->expectExceptionMessage( 'Element with id: 99 doesnt exist' ); $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Child', description: 'Child description', richText: '

Child rich text

', pdfPath: null, youtubeUrl: null, parentElementId: 99, )); } public function testThrowsWhenRootElementAlreadyExists(): void { $set = $this->createSet('Daily learning'); $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', description: 'Root description', richText: '

Root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, )); $this->expectException(DomainException::class); $this->expectExceptionMessage( 'A root element already exists for this set' ); $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Another root', description: 'Another root description', richText: '

Another root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, )); } public function testThrowsWhenParentBelongsToAnotherSet(): void { $parentSet = $this->createSet('Parent set'); $childSet = $this->createSet('Child set'); $parentElement = $this->createElement->execute( new CreateElementRequest( setId: $parentSet->getId(), title: 'Parent root', description: 'Parent root description', richText: '

Parent root rich text

', pdfPath: null, youtubeUrl: null, parentElementId: null, ) ); $this->expectException(DomainException::class); $this->expectExceptionMessage( 'Parent element must belong to the same set' ); $this->createElement->execute(new CreateElementRequest( setId: $childSet->getId(), title: 'Invalid child', description: 'Invalid child description', richText: '

Invalid child rich text

', pdfPath: null, youtubeUrl: null, parentElementId: $parentElement->getId(), )); } }