scraper = new InMemoryScraperAdapter(); $this->scrapingJobRepository = new InMemoryScrapingJobRepository(); $this->chapterRepository = new InMemoryChapterRepository(); $this->chapterRepository->save(new Chapter( id: '1', mangaId: '1', chapterNumber: '2', volumeNumber: 1, cbzPath: null, )); $this->eventBus = new InMemoryEventBus(); $this->handler = new ScrapeChapterHandler( $this->scraper, $this->scrapingJobRepository, $this->chapterRepository, $this->eventBus ); } public function testHandleSuccessfully(): void { $command = new ScrapeChapter( mangaId: '1', chapterNumber: '2', sourceId: '3', ); $this->handler->handle($command); $scrapingJobs = $this->scrapingJobRepository->getJobs(); $this->assertCount(1, $scrapingJobs); $job = $scrapingJobs[0]; $dispatchedMessages = $this->eventBus->getDispatchedMessages(); $this->assertCount(2, $dispatchedMessages); $this->assertInstanceOf(ChapterScrapingStarted::class, $dispatchedMessages[0]); $this->assertInstanceOf(ChapterScraped::class, $dispatchedMessages[1]); $this->assertEquals($job->getId(), $dispatchedMessages[0]->getJobId()); $chapter = $this->chapterRepository->getByMangaIdAndChapterNumber('1', '2'); $this->assertNotNull($chapter->cbzPath); } public function testHandleThrowsException(): void { $command = new ScrapeChapter( mangaId: '1', chapterNumber: '2', sourceId: '3', ); $exception = new \Exception('Scraping failed'); $this->scraper->simulateError($exception); $this->handler->handle($command); $dispatchedMessages = $this->eventBus->getDispatchedMessages(); $this->assertCount(2, $dispatchedMessages); $this->assertInstanceOf(ChapterScrapingStarted::class, $dispatchedMessages[0]); $this->assertInstanceOf(ChapterScrapingFailed::class, $dispatchedMessages[1]); $this->assertEquals('1', $dispatchedMessages[1]->getMangaId()); $this->assertEquals('2', $dispatchedMessages[1]->getChapterNumber()); $this->assertEquals('Scraping failed', $dispatchedMessages[1]->getReason()); $jobs = $this->scrapingJobRepository->getJobs(); $this->assertCount(1, $jobs); $this->assertEquals(ScrapingStatus::FAILED, $jobs[0]->status); $this->assertEquals('Scraping failed', $jobs[0]->failureReason); } public function tearDown(): void { $this->scrapingJobRepository->clear(); $this->chapterRepository->clear(); } }