service = new IngestionService( $this->createStub(SentinelHubClient::class), $this->createStub(EntityManagerInterface::class), new NullLogger(), sys_get_temp_dir(), ); } // ── buildMultiPolygon ───────────────────────────────────────────────────── private function callBuildMultiPolygon(string $geojsonContent): ?array { $file = tempnam(sys_get_temp_dir(), 'phpunit_ingestion_') . '.geojson'; file_put_contents($file, $geojsonContent); try { $method = new \ReflectionMethod(IngestionService::class, 'buildMultiPolygon'); return $method->invoke($this->service, $file); } finally { @unlink($file); } } private static function makePolygon(int $points = 10, int $dn = 1): array { // Carré simple autour de 0,0 — répété $points fois pour avoir assez de coordonnées $coords = []; for ($i = 0; $i < $points; $i++) { $coords[] = [$i * 0.01, $i * 0.01]; } $coords[] = $coords[0]; // fermer l'anneau return [ 'type' => 'Feature', 'properties' => ['DN' => $dn], 'geometry' => [ 'type' => 'Polygon', 'coordinates' => [$coords], ], ]; } public function testReturnsNullWhenFileDoesNotExist(): void { $method = new \ReflectionMethod(IngestionService::class, 'buildMultiPolygon'); $result = $method->invoke($this->service, '/tmp/nonexistent_phpunit.geojson'); self::assertNull($result); } public function testReturnsNullForEmptyFeatureCollection(): void { $geojson = json_encode(['type' => 'FeatureCollection', 'features' => []]); self::assertNull($this->callBuildMultiPolygon($geojson)); } public function testReturnsNullForInvalidJson(): void { self::assertNull($this->callBuildMultiPolygon('not-json')); } public function testReturnsNullWhenAllFeaturesHaveWrongDN(): void { $geojson = json_encode([ 'type' => 'FeatureCollection', 'features' => [self::makePolygon(10, 0), self::makePolygon(10, 2)], ]); self::assertNull($this->callBuildMultiPolygon($geojson)); } public function testReturnsNullWhenPolygonHasTooFewPoints(): void { // MIN_RING_POINTS = 8 → 5 points doit être ignoré $geojson = json_encode([ 'type' => 'FeatureCollection', 'features' => [self::makePolygon(5, 1)], ]); self::assertNull($this->callBuildMultiPolygon($geojson)); } public function testReturnMultiPolygonForValidFeature(): void { $geojson = json_encode([ 'type' => 'FeatureCollection', 'features' => [self::makePolygon(10, 1)], ]); $result = $this->callBuildMultiPolygon($geojson); self::assertNotNull($result); self::assertSame('MultiPolygon', $result['type']); self::assertCount(1, $result['coordinates']); } public function testHandlesMultipleValidFeatures(): void { $geojson = json_encode([ 'type' => 'FeatureCollection', 'features' => [ self::makePolygon(10, 1), self::makePolygon(12, 1), self::makePolygon(5, 1), // trop petit → ignoré ], ]); $result = $this->callBuildMultiPolygon($geojson); self::assertNotNull($result); self::assertCount(2, $result['coordinates']); // 2 valides sur 3 } public function testHandlesMultiPolygonGeometryType(): void { $coords1 = array_fill(0, 11, [0.0, 0.0]); $coords1[] = $coords1[0]; $coords2 = array_fill(0, 11, [1.0, 1.0]); $coords2[] = $coords2[0]; $feature = [ 'type' => 'Feature', 'properties' => ['DN' => 1], 'geometry' => [ 'type' => 'MultiPolygon', 'coordinates' => [[$coords1], [$coords2]], ], ]; $geojson = json_encode(['type' => 'FeatureCollection', 'features' => [$feature]]); $result = $this->callBuildMultiPolygon($geojson); self::assertNotNull($result); self::assertSame('MultiPolygon', $result['type']); self::assertCount(2, $result['coordinates']); } public function testIgnoresFeaturesWithDNZeroAndKeepsOthers(): void { $geojson = json_encode([ 'type' => 'FeatureCollection', 'features' => [ self::makePolygon(10, 0), // DN=0 → ignoré self::makePolygon(10, 1), // valide ], ]); $result = $this->callBuildMultiPolygon($geojson); self::assertNotNull($result); self::assertCount(1, $result['coordinates']); } }