[ ['title' => 'Pirates', 'year' => 2005], ['title' => 'The Masseuse', 'year' => 1990], ['title' => 'Debbie Does Dallas', 'year' => 1978], ], 'adm' => [ ['title' => 'Pirates', 'year' => 2005], ['title' => 'The Masseuse', 'year' => 1990], ], 'aebn' => [ ['title' => 'Pirates', 'year' => 2005], ['title' => 'The Masseuse', 'year' => 1990], ], 'hotmovies' => [ ['title' => 'Pirates', 'year' => 2005], ['title' => 'The Masseuse', 'year' => 1990], ], 'popporn' => [ ['title' => 'Pirates', 'year' => 2005], ['title' => 'The Masseuse', 'year' => 1990], ], ]; /** * @test * * @group ade */ public function ade_can_search_and_find_movies(): void { $scraper = new ADE; foreach ($this->testMovies['ade'] as $movie) { $result = $scraper->processSite($movie['title']); $this->assertTrue( $result, "ADE failed to find movie: {$movie['title']} ({$movie['year']})" ); if ($result) { $data = $scraper->getAll(); $this->assertNotEmpty($data, 'ADE returned empty data'); $this->assertArrayHasKey('title', $data, 'ADE missing title'); $this->assertArrayHasKey('directurl', $data, 'ADE missing directurl'); echo "\n✓ ADE found: {$data['title']}\n"; echo " URL: {$data['directurl']}\n"; } } } /** * @test * * @group ade */ public function ade_extracts_complete_movie_data(): void { $scraper = new ADE; $result = $scraper->processSite('Pirates'); if (! $result) { $this->markTestSkipped('ADE could not find test movie "Pirates"'); } $data = $scraper->getAll(); // Required fields $this->assertArrayHasKey('title', $data, 'Missing title'); $this->assertArrayHasKey('directurl', $data, 'Missing directurl'); // Optional but expected fields $expectedFields = ['synopsis', 'cast', 'genres', 'boxcover']; $missingFields = []; foreach ($expectedFields as $field) { if (! isset($data[$field]) || empty($data[$field])) { $missingFields[] = $field; } } if (! empty($missingFields)) { echo "\n⚠ ADE missing or empty fields: ".implode(', ', $missingFields)."\n"; } // Log extracted data for inspection $this->logScrapedData('ADE', 'Pirates', $data); } /** * @test * * @group adm */ public function adm_can_search_and_find_movies(): void { $scraper = new ADM; foreach ($this->testMovies['adm'] as $movie) { $result = $scraper->processSite($movie['title']); $this->assertTrue( $result, "ADM failed to find movie: {$movie['title']} ({$movie['year']})" ); if ($result) { $data = $scraper->getAll(); $this->assertNotEmpty($data, 'ADM returned empty data'); $this->assertArrayHasKey('title', $data, 'ADM missing title'); $this->assertArrayHasKey('directurl', $data, 'ADM missing directurl'); echo "\n✓ ADM found: {$data['title']}\n"; echo " URL: {$data['directurl']}\n"; } } } /** * @test * * @group adm */ public function adm_extracts_complete_movie_data(): void { $scraper = new ADM; $result = $scraper->processSite('Pirates'); if (! $result) { $this->markTestSkipped('ADM could not find test movie "Pirates"'); } $data = $scraper->getAll(); // Required fields $this->assertArrayHasKey('title', $data, 'Missing title'); $this->assertArrayHasKey('directurl', $data, 'Missing directurl'); // Optional but expected fields $expectedFields = ['synopsis', 'cast', 'genres', 'boxcover', 'director']; $missingFields = []; foreach ($expectedFields as $field) { if (! isset($data[$field]) || empty($data[$field])) { $missingFields[] = $field; } } if (! empty($missingFields)) { echo "\n⚠ ADM missing or empty fields: ".implode(', ', $missingFields)."\n"; } // Log extracted data for inspection $this->logScrapedData('ADM', 'Pirates', $data); } /** * @test * * @group aebn */ public function aebn_can_search_and_find_movies(): void { $scraper = new AEBN; foreach ($this->testMovies['aebn'] as $movie) { $result = $scraper->processSite($movie['title']); $this->assertTrue( $result, "AEBN failed to find movie: {$movie['title']} ({$movie['year']})" ); if ($result) { $data = $scraper->getAll(); $this->assertNotEmpty($data, 'AEBN returned empty data'); $this->assertArrayHasKey('title', $data, 'AEBN missing title'); $this->assertArrayHasKey('directurl', $data, 'AEBN missing directurl'); echo "\n✓ AEBN found: {$data['title']}\n"; echo " URL: {$data['directurl']}\n"; } } } /** * @test * * @group aebn */ public function aebn_extracts_complete_movie_data(): void { $scraper = new AEBN; $result = $scraper->processSite('Pirates'); if (! $result) { $this->markTestSkipped('AEBN could not find test movie "Pirates"'); } $data = $scraper->getAll(); // Required fields $this->assertArrayHasKey('title', $data, 'Missing title'); $this->assertArrayHasKey('directurl', $data, 'Missing directurl'); // Optional but expected fields $expectedFields = ['synopsis', 'cast', 'genres', 'boxcover', 'director']; $missingFields = []; foreach ($expectedFields as $field) { if (! isset($data[$field]) || empty($data[$field])) { $missingFields[] = $field; } } if (! empty($missingFields)) { echo "\n⚠ AEBN missing or empty fields: ".implode(', ', $missingFields)."\n"; } // Log extracted data for inspection $this->logScrapedData('AEBN', 'Pirates', $data); } /** * @test * * @group hotmovies */ public function hotmovies_can_search_and_find_movies(): void { $scraper = new Hotmovies; foreach ($this->testMovies['hotmovies'] as $movie) { $result = $scraper->processSite($movie['title']); $this->assertTrue( $result, "Hotmovies failed to find movie: {$movie['title']} ({$movie['year']})" ); if ($result) { $data = $scraper->getAll(); $this->assertNotEmpty($data, 'Hotmovies returned empty data'); $this->assertArrayHasKey('title', $data, 'Hotmovies missing title'); $this->assertArrayHasKey('directurl', $data, 'Hotmovies missing directurl'); echo "\n✓ Hotmovies found: {$data['title']}\n"; echo " URL: {$data['directurl']}\n"; } } } /** * @test * * @group hotmovies */ public function hotmovies_extracts_complete_movie_data(): void { $scraper = new Hotmovies; $result = $scraper->processSite('Pirates'); if (! $result) { $this->markTestSkipped('Hotmovies could not find test movie "Pirates"'); } $data = $scraper->getAll(); // Required fields $this->assertArrayHasKey('title', $data, 'Missing title'); $this->assertArrayHasKey('directurl', $data, 'Missing directurl'); // Optional but expected fields $expectedFields = ['synopsis', 'cast', 'genres', 'boxcover', 'director']; $missingFields = []; foreach ($expectedFields as $field) { if (! isset($data[$field]) || empty($data[$field])) { $missingFields[] = $field; } } if (! empty($missingFields)) { echo "\n⚠ Hotmovies missing or empty fields: ".implode(', ', $missingFields)."\n"; } // Log extracted data for inspection $this->logScrapedData('Hotmovies', 'Pirates', $data); } /** * @test * * @group popporn */ public function popporn_can_search_and_find_movies(): void { $scraper = new Popporn; foreach ($this->testMovies['popporn'] as $movie) { $result = $scraper->processSite($movie['title']); $this->assertTrue( $result, "Popporn failed to find movie: {$movie['title']} ({$movie['year']})" ); if ($result) { $data = $scraper->getAll(); $this->assertNotEmpty($data, 'Popporn returned empty data'); $this->assertArrayHasKey('title', $data, 'Popporn missing title'); $this->assertArrayHasKey('directurl', $data, 'Popporn missing directurl'); echo "\n✓ Popporn found: {$data['title']}\n"; echo " URL: {$data['directurl']}\n"; } } } /** * @test * * @group popporn */ public function popporn_extracts_complete_movie_data(): void { $scraper = new Popporn; $result = $scraper->processSite('Pirates'); if (! $result) { $this->markTestSkipped('Popporn could not find test movie "Pirates"'); } $data = $scraper->getAll(); // Required fields $this->assertArrayHasKey('title', $data, 'Missing title'); $this->assertArrayHasKey('directurl', $data, 'Missing directurl'); // Optional but expected fields $expectedFields = ['synopsis', 'cast', 'genres', 'boxcover', 'director']; $missingFields = []; foreach ($expectedFields as $field) { if (! isset($data[$field]) || empty($data[$field])) { $missingFields[] = $field; } } if (! empty($missingFields)) { echo "\n⚠ Popporn missing or empty fields: ".implode(', ', $missingFields)."\n"; } // Log extracted data for inspection $this->logScrapedData('Popporn', 'Pirates', $data); } /** * @test * * @group similarity */ public function all_scrapers_have_configurable_similarity_threshold(): void { $scrapers = [ 'ADE' => new ADE, 'ADM' => new ADM, 'AEBN' => new AEBN, 'Hotmovies' => new Hotmovies, 'Popporn' => new Popporn, ]; foreach ($scrapers as $name => $scraper) { $reflection = new \ReflectionClass($scraper); $this->assertTrue( $reflection->hasProperty('minimumSimilarity'), "{$name} missing minimumSimilarity property" ); $property = $reflection->getProperty('minimumSimilarity'); $property->setAccessible(true); $value = $property->getValue($scraper); $this->assertIsFloat($value, "{$name} minimumSimilarity should be float"); $this->assertEquals(90.0, $value, "{$name} default threshold should be 90.0"); echo "\n✓ {$name}: minimumSimilarity = {$value}\n"; } } /** * Helper method to log scraped data for manual inspection */ private function logScrapedData(string $scraper, string $movie, array $data): void { $logFile = storage_path('logs/scraper_test_'.date('Y-m-d').'.log'); $logDir = dirname($logFile); if (! is_dir($logDir)) { mkdir($logDir, 0755, true); } $logEntry = sprintf( "[%s] %s - %s\n%s\n\n", date('Y-m-d H:i:s'), $scraper, $movie, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ); file_put_contents($logFile, $logEntry, FILE_APPEND); echo "\n📝 Logged scraped data to: {$logFile}\n"; } }