feat: ajout de la fonctionnalité de test de configuration de scraper, incluant la mise à jour de l'API pour tester les configurations en temps réel, la gestion des erreurs détaillées et l'intégration des tests unitaires pour valider le bon fonctionnement de cette nouvelle fonctionnalité.
This commit is contained in:
parent
ee2a9b3750
commit
cbb62989d4
198
tests/Feature/Scraping/TestScraperConfigurationTest.php
Normal file
198
tests/Feature/Scraping/TestScraperConfigurationTest.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Feature\Scraping;
|
||||
|
||||
use App\Tests\Feature\AbstractApiTestCase;
|
||||
|
||||
class TestScraperConfigurationTest extends AbstractApiTestCase
|
||||
{
|
||||
public function testTestScraperConfigurationSuccess(): void
|
||||
{
|
||||
// Given - Configuration valide avec une URL de test accessible
|
||||
$payload = [
|
||||
'baseUrl' => 'https://example.com',
|
||||
'chapterUrlFormat' => 'https://example.com/manga/{slug}/chapter/{chapter}',
|
||||
'scrapingType' => 'html',
|
||||
'testUrl' => 'https://httpbin.org/html',
|
||||
'mangaSlug' => 'test-manga',
|
||||
'chapterNumber' => 1.0,
|
||||
'imageSelector' => 'img',
|
||||
'nextPageSelector' => null,
|
||||
'chapterSelector' => null,
|
||||
];
|
||||
|
||||
// When
|
||||
$response = static::createClient()->request('POST', '/api/scraping/test-configuration', [
|
||||
'json' => $payload,
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
]);
|
||||
|
||||
// Then
|
||||
$this->assertResponseStatusCodeSame(200);
|
||||
$responseData = $response->toArray();
|
||||
|
||||
$this->assertArrayHasKey('success', $responseData);
|
||||
$this->assertArrayHasKey('imageUrls', $responseData);
|
||||
$this->assertArrayHasKey('totalImages', $responseData);
|
||||
$this->assertArrayHasKey('testedUrl', $responseData);
|
||||
$this->assertArrayHasKey('scrapingType', $responseData);
|
||||
$this->assertArrayHasKey('errors', $responseData);
|
||||
|
||||
$this->assertEquals('https://httpbin.org/html', $responseData['testedUrl']);
|
||||
$this->assertEquals('html', $responseData['scrapingType']);
|
||||
}
|
||||
|
||||
public function testTestScraperConfigurationWithInvalidUrl(): void
|
||||
{
|
||||
// Given - Configuration avec une URL invalide
|
||||
$payload = [
|
||||
'baseUrl' => 'https://example.com',
|
||||
'chapterUrlFormat' => 'https://example.com/manga/{slug}/chapter/{chapter}',
|
||||
'scrapingType' => 'html',
|
||||
'testUrl' => 'https://invalid-url-that-does-not-exist-12345.com',
|
||||
'mangaSlug' => 'test-manga',
|
||||
'chapterNumber' => 1.0,
|
||||
'imageSelector' => 'img',
|
||||
'nextPageSelector' => null,
|
||||
'chapterSelector' => null,
|
||||
];
|
||||
|
||||
// When
|
||||
$response = static::createClient()->request('POST', '/api/scraping/test-configuration', [
|
||||
'json' => $payload,
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
]);
|
||||
|
||||
// Then
|
||||
$this->assertResponseStatusCodeSame(200);
|
||||
$responseData = $response->toArray();
|
||||
|
||||
$this->assertFalse($responseData['success']);
|
||||
$this->assertEquals(0, $responseData['totalImages']);
|
||||
$this->assertEmpty($responseData['imageUrls']);
|
||||
$this->assertNotEmpty($responseData['errors']);
|
||||
|
||||
// Vérifier qu'on a une erreur détaillée
|
||||
$this->assertIsArray($responseData['errors']);
|
||||
$this->assertGreaterThan(0, count($responseData['errors']));
|
||||
}
|
||||
|
||||
public function testTestScraperConfigurationWithInvalidSelector(): void
|
||||
{
|
||||
// Given - Configuration avec un sélecteur CSS qui ne trouvera rien
|
||||
$payload = [
|
||||
'baseUrl' => 'https://example.com',
|
||||
'chapterUrlFormat' => 'https://example.com/manga/{slug}/chapter/{chapter}',
|
||||
'scrapingType' => 'html',
|
||||
'testUrl' => 'https://httpbin.org/html',
|
||||
'mangaSlug' => 'test-manga',
|
||||
'chapterNumber' => 1.0,
|
||||
'imageSelector' => '.non-existent-class-selector-12345',
|
||||
'nextPageSelector' => null,
|
||||
'chapterSelector' => null,
|
||||
];
|
||||
|
||||
// When
|
||||
$response = static::createClient()->request('POST', '/api/scraping/test-configuration', [
|
||||
'json' => $payload,
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
]);
|
||||
|
||||
// Then
|
||||
$this->assertResponseStatusCodeSame(200);
|
||||
$responseData = $response->toArray();
|
||||
|
||||
// Le sélecteur invalide peut ne pas retourner d'images, ou juste retourner un tableau vide
|
||||
// C'est un comportement acceptable, le test vérifie juste que ça ne plante pas
|
||||
$this->assertArrayHasKey('success', $responseData);
|
||||
$this->assertArrayHasKey('imageUrls', $responseData);
|
||||
$this->assertArrayHasKey('totalImages', $responseData);
|
||||
$this->assertArrayHasKey('errors', $responseData);
|
||||
}
|
||||
|
||||
public function testTestScraperConfigurationWithInvalidValidation(): void
|
||||
{
|
||||
// Given - Payload avec des données invalides
|
||||
$payload = [
|
||||
'baseUrl' => 'invalid-url',
|
||||
'chapterUrlFormat' => '',
|
||||
'scrapingType' => 'invalid-type',
|
||||
'testUrl' => 'not-a-url',
|
||||
'mangaSlug' => '',
|
||||
'chapterNumber' => -1,
|
||||
'imageSelector' => str_repeat('x', 501), // Trop long
|
||||
];
|
||||
|
||||
// When
|
||||
$response = static::createClient()->request('POST', '/api/scraping/test-configuration', [
|
||||
'json' => $payload,
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
]);
|
||||
|
||||
// Then
|
||||
$this->assertResponseStatusCodeSame(422);
|
||||
$this->assertJsonContains([
|
||||
'violations' => [
|
||||
[
|
||||
'propertyPath' => 'baseUrl',
|
||||
'message' => 'L\'URL de base doit être une URL valide',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'chapterUrlFormat',
|
||||
'message' => 'Le format d\'URL de chapitre est obligatoire',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'scrapingType',
|
||||
'message' => 'Le type de scraping doit être html ou javascript',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'testUrl',
|
||||
'message' => 'L\'URL de test doit être une URL valide',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'mangaSlug',
|
||||
'message' => 'Le slug du manga est obligatoire',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'chapterNumber',
|
||||
'message' => 'Le numéro de chapitre doit être positif',
|
||||
],
|
||||
[
|
||||
'propertyPath' => 'imageSelector',
|
||||
'message' => 'Le sélecteur d\'image est trop long',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testTestScraperConfigurationWithUnsupportedScrapingType(): void
|
||||
{
|
||||
// Given - Type de scraping non supporté
|
||||
$payload = [
|
||||
'baseUrl' => 'https://example.com',
|
||||
'chapterUrlFormat' => 'https://example.com/manga/{slug}/chapter/{chapter}',
|
||||
'scrapingType' => 'unsupported-type', // Type vraiment non supporté
|
||||
'testUrl' => 'https://httpbin.org/html',
|
||||
'mangaSlug' => 'test-manga',
|
||||
'chapterNumber' => 1.0,
|
||||
'imageSelector' => 'img',
|
||||
];
|
||||
|
||||
// When
|
||||
$response = static::createClient()->request('POST', '/api/scraping/test-configuration', [
|
||||
'json' => $payload,
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
]);
|
||||
|
||||
// Then
|
||||
$this->assertResponseStatusCodeSame(422); // Validation error
|
||||
$this->assertJsonContains([
|
||||
'violations' => [
|
||||
[
|
||||
'propertyPath' => 'scrapingType',
|
||||
'message' => 'Le type de scraping doit être html ou javascript',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user