mangaRepository = new InMemoryMangaRepository(); $this->imageStorage = new InMemoryImageStorage(); $this->handler = new ImportChapterHandler( $this->mangaRepository, $this->imageStorage ); } public function test_it_throws_exception_when_chapter_not_found(): void { // Arrange $mangaId = 'manga-123'; $manga = new Manga( new MangaId($mangaId), new MangaTitle('One Piece'), new MangaSlug('one-piece'), 'Description', 'Eiichiro Oda', 1997, ['action', 'adventure'], 'ongoing' ); $this->mangaRepository->save($manga); $cbzBinary = $this->createValidCbzBinary(); $command = new ImportChapter( mangaId: $mangaId, chapterNumber: 1.5, fileBinary: $cbzBinary ); // Assert $this->expectException(ChapterNotFoundException::class); // Act $this->handler->handle($command); } public function test_it_updates_existing_chapter_with_new_path(): void { // Arrange $mangaId = 'manga-123'; $manga = new Manga( new MangaId($mangaId), new MangaTitle('One Piece'), new MangaSlug('one-piece'), 'Description', 'Eiichiro Oda', 1997, ['action', 'adventure'], 'ongoing' ); // Create an existing chapter without pages and add through the aggregate $existingChapter = new Chapter( new ChapterId('chapter-123'), new MangaId($mangaId), 1.5, 'Chapter 1.5', 1, true, null ); $manga->addChapter($existingChapter); $this->mangaRepository->save($manga); // Import the same chapter with CBZ $cbzBinary = $this->createValidCbzBinary(); $command = new ImportChapter( mangaId: $mangaId, chapterNumber: 1.5, fileBinary: $cbzBinary ); // Act $this->handler->handle($command); // Assert $updatedChapter = $this->mangaRepository->findChapterById('chapter-123'); $this->assertNotNull($updatedChapter); $this->assertEquals('chapter-123', $updatedChapter->getId()); $this->assertEquals($mangaId, $updatedChapter->getMangaId()->getValue()); $this->assertEquals(1.5, $updatedChapter->getNumber()); $this->assertEquals('Chapter 1.5', $updatedChapter->getTitle()); $this->assertEquals(1, $updatedChapter->getVolume()); $this->assertTrue($updatedChapter->isVisible()); $this->assertTrue($updatedChapter->isAvailable()); $this->assertNotNull($updatedChapter->getPagesDirectory()); } public function test_it_throws_exception_when_manga_not_found(): void { // Arrange $cbzBinary = $this->createValidCbzBinary(); $command = new ImportChapter( mangaId: 'non-existent-manga', chapterNumber: 1.0, fileBinary: $cbzBinary ); // Assert $this->expectException(MangaNotFoundException::class); // Act $this->handler->handle($command); } public function test_it_throws_exception_when_file_is_not_valid_cbz(): void { // Arrange $mangaId = 'manga-123'; $manga = new Manga( new MangaId($mangaId), new MangaTitle('One Piece'), new MangaSlug('one-piece'), 'Description', 'Eiichiro Oda', 1997, ['action', 'adventure'], 'ongoing' ); $this->mangaRepository->save($manga); $invalidBinary = 'This is not a CBZ file'; $command = new ImportChapter( mangaId: $mangaId, chapterNumber: 1.0, fileBinary: $invalidBinary ); // Assert $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('The provided file is not a valid CBZ file'); // Act $this->handler->handle($command); } private function createValidCbzBinary(): string { $tmpFile = tempnam(sys_get_temp_dir(), 'cbz'); unlink($tmpFile); $zip = new \ZipArchive(); if ($zip->open($tmpFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) { throw new \RuntimeException('Cannot create test CBZ file'); } $zip->addFromString('image1.jpg', 'fake-image-data'); $zip->close(); $binaryContent = file_get_contents($tmpFile); unlink($tmpFile); return $binaryContent; } }