from app.core.errors import AppError from app.services.raster_service import extract_raster_metadata def test_extract_raster_metadata_returns_dependency_aware_error(monkeypatch, tmp_path) -> None: monkeypatch.setattr("app.services.raster_service._import_rasterio", lambda: (_ for _ in ()).throw(ImportError("rasterio not installed"))) file_path = tmp_path / "missing.tif" file_path.write_bytes(b"\x00\x01\x02") try: extract_raster_metadata(str(file_path)) except AppError as exc: assert exc.code == "RASTER_PROCESSING_UNAVAILABLE" else: raise AssertionError("Missing rasterio should raise AppError code RASTER_PROCESSING_UNAVAILABLE") def test_extract_raster_metadata_maps_basic_profile_fields(monkeypatch, tmp_path) -> None: file_path = tmp_path / "sample.tif" file_path.write_bytes(b"fake") class FakeDataset: width = 1024 height = 768 count = 4 driver = "GTiff" crs = "EPSG:31370" bounds = (100.0, 200.0, 500.0, 800.0) res = (0.25, 0.25) dtypes = ["uint16", "uint16", "uint16", "uint16"] nodata = -9999 class transform: @staticmethod def to_gdal(): return (0.25, 0.0, 100.0, 0.0, -0.25, 800.0, 0.0, 0.0, 1.0) def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return None class FakeRasterio: class errors: class RasterioIOError(Exception): ... def open(self, *_): return FakeDataset() class FakeErrors: RasterioIOError = FakeRasterio.errors.RasterioIOError monkeypatch.setattr("app.services.raster_service._import_rasterio", lambda: (FakeRasterio(), FakeErrors())) metadata = extract_raster_metadata(str(file_path)) assert metadata["driver"] == "GTiff" assert metadata["width"] == 1024 assert metadata["height"] == 768 assert metadata["band_count"] == 4 assert metadata["crs"] == "EPSG:31370" assert metadata["bounds"] == [100.0, 200.0, 500.0, 800.0] assert metadata["resolution"] == [0.25, 0.25] assert metadata["dtype"] == ["uint16", "uint16", "uint16", "uint16"] assert metadata["nodata"] == -9999.0