assertInstanceOf(VrtArticleParser::class, $parser); $this->assertInstanceOf(ArticleParserInterface::class, $parser); } public function test_get_parser_returns_belga_parser_for_belga_urls(): void { $belgaUrl = 'https://www.belganewsagency.eu/nl/nieuws/binnenland/test-article'; $parser = ArticleParserFactory::getParser($belgaUrl); $this->assertInstanceOf(BelgaArticleParser::class, $parser); $this->assertInstanceOf(ArticleParserInterface::class, $parser); } public function test_get_parser_throws_exception_for_unsupported_url(): void { $unsupportedUrl = 'https://www.example.com/article'; $this->expectException(Exception::class); $this->expectExceptionMessage("No parser found for URL: {$unsupportedUrl}"); ArticleParserFactory::getParser($unsupportedUrl); } public function test_get_supported_sources_returns_array_of_source_names(): void { $sources = ArticleParserFactory::getSupportedSources(); $this->assertIsArray($sources); $this->assertCount(2, $sources); $this->assertContains('VRT News', $sources); $this->assertContains('Belga News Agency', $sources); } public function test_get_supported_sources_returns_sources_in_correct_order(): void { $sources = ArticleParserFactory::getSupportedSources(); // Based on the factory's parser registration order $this->assertEquals('VRT News', $sources[0]); $this->assertEquals('Belga News Agency', $sources[1]); } public function test_register_parser_adds_new_parser_to_list(): void { // Create a mock parser class $mockParserClass = new class implements ArticleParserInterface { public function canParse(string $url): bool { return str_contains($url, 'test-parser.com'); } public function extractData(string $html): array { return ['title' => 'Test Title']; } public function getSourceName(): string { return 'TestParser'; } }; $mockParserClassName = get_class($mockParserClass); // Register the mock parser ArticleParserFactory::registerParser($mockParserClassName); // Verify it's now included in supported sources $sources = ArticleParserFactory::getSupportedSources(); $this->assertContains('TestParser', $sources); $this->assertCount(3, $sources); // Original 2 + 1 new // Verify it can be used to parse URLs $testUrl = 'https://test-parser.com/article'; $parser = ArticleParserFactory::getParser($testUrl); $this->assertInstanceOf($mockParserClassName, $parser); } public function test_register_parser_prevents_duplicate_registration(): void { // Get initial source count $initialSources = ArticleParserFactory::getSupportedSources(); $initialCount = count($initialSources); // Try to register an existing parser ArticleParserFactory::registerParser(VrtArticleParser::class); // Verify count hasn't changed $newSources = ArticleParserFactory::getSupportedSources(); $this->assertCount($initialCount, $newSources); $this->assertEquals($initialSources, $newSources); } public function test_get_parser_uses_first_matching_parser(): void { // Create two mock parsers that can parse the same URL $mockParser1 = new class implements ArticleParserInterface { public function canParse(string $url): bool { return str_contains($url, 'shared-domain.com'); } public function extractData(string $html): array { return ['parser' => 'first']; } public function getSourceName(): string { return 'FirstParser'; } }; $mockParser2 = new class implements ArticleParserInterface { public function canParse(string $url): bool { return str_contains($url, 'shared-domain.com'); } public function extractData(string $html): array { return ['parser' => 'second']; } public function getSourceName(): string { return 'SecondParser'; } }; $mockParser1Class = get_class($mockParser1); $mockParser2Class = get_class($mockParser2); // Register both parsers ArticleParserFactory::registerParser($mockParser1Class); ArticleParserFactory::registerParser($mockParser2Class); // The first registered parser should be returned $testUrl = 'https://shared-domain.com/article'; $parser = ArticleParserFactory::getParser($testUrl); // Should return the first parser since it was registered first $this->assertInstanceOf($mockParser1Class, $parser); } public function test_factory_maintains_parser_registration_across_calls(): void { // Create a mock parser $mockParser = new class implements ArticleParserInterface { public function canParse(string $url): bool { return str_contains($url, 'persistent-test.com'); } public function extractData(string $html): array { return ['title' => 'Persistent Test']; } public function getSourceName(): string { return 'PersistentTestParser'; } }; $mockParserClass = get_class($mockParser); // Register the parser ArticleParserFactory::registerParser($mockParserClass); // Make multiple calls to verify persistence $parser1 = ArticleParserFactory::getParser('https://persistent-test.com/article1'); $parser2 = ArticleParserFactory::getParser('https://persistent-test.com/article2'); $this->assertInstanceOf($mockParserClass, $parser1); $this->assertInstanceOf($mockParserClass, $parser2); // Verify both instances are of the same class but different objects $this->assertEquals(get_class($parser1), get_class($parser2)); } public function test_get_parser_creates_new_instance_each_time(): void { $vrtUrl = 'https://www.vrt.be/vrtnws/nl/test/'; $parser1 = ArticleParserFactory::getParser($vrtUrl); $parser2 = ArticleParserFactory::getParser($vrtUrl); // Should be same class but different instances $this->assertEquals(get_class($parser1), get_class($parser2)); $this->assertNotSame($parser1, $parser2); } public function test_get_supported_sources_creates_new_instances_for_each_call(): void { // This test ensures that getSupportedSources doesn't cause issues // by creating new instances each time it's called $sources1 = ArticleParserFactory::getSupportedSources(); $sources2 = ArticleParserFactory::getSupportedSources(); $this->assertEquals($sources1, $sources2); $this->assertCount(count($sources1), $sources2); } }