mangaRepository = new InMemoryMangaRepository(); $this->chapterRepository = new InMemoryChapterRepository(); $this->pathManager = new InMemoryPathManager(); $this->handler = new ImportVolumeHandler( $this->mangaRepository, $this->chapterRepository, $this->pathManager ); } public function test_it_updates_all_chapters_in_volume(): void { // Arrange $mangaId = 'manga-123'; $volumeNumber = 1; $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); // Create chapters in volume 1 for ($i = 1; $i <= 3; $i++) { $chapter = new Chapter( new ChapterId("chapter-$i"), $mangaId, (float)$i, "Chapter $i", $volumeNumber, true, null ); $this->chapterRepository->save($chapter); } $cbzBinary = $this->createValidCbzBinary(); $command = new ImportVolume( mangaId: $mangaId, volumeNumber: $volumeNumber, fileBinary: $cbzBinary ); // Act $this->handler->handle($command); // Assert $chapters = $this->chapterRepository->findByMangaIdAndVolume($mangaId, $volumeNumber); $this->assertCount(3, $chapters); foreach ($chapters as $chapter) { $this->assertTrue($chapter->isAvailable()); $this->assertStringContainsString('_vol' . $volumeNumber . '.cbz', $chapter->getCbzPath()); } } public function test_it_throws_exception_when_manga_not_found(): void { // Arrange $cbzBinary = $this->createValidCbzBinary(); $command = new ImportVolume( mangaId: 'non-existent-manga', volumeNumber: 1, 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 ImportVolume( mangaId: $mangaId, volumeNumber: 1, fileBinary: $invalidBinary ); // Assert $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('The provided file is not a valid CBZ file'); // Act $this->handler->handle($command); } public function test_it_throws_exception_when_no_chapters_in_volume(): 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 ImportVolume( mangaId: $mangaId, volumeNumber: 999, // Non-existent volume fileBinary: $cbzBinary ); // Assert $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('No chapters found'); // Act $this->handler->handle($command); } /** * Create a minimal valid CBZ (ZIP) binary for testing */ 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; } }