diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a1223ce..a613751 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,3 +34,12 @@ jobs: - name: Run pre-commit checks run: uv run pre-commit run --all-files + + - name: Run integration tests + run: uv run pytest tests/integration -v -m integration --tb=short + + - name: Generate coverage report + run: uv run pytest tests/integration --cov=scripts --cov-report=term-missing + + - name: Generate integration test coverage + run: uv run pytest tests/integration --cov=scripts --cov-report=term-missing --cov-report=html diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..c967b78 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,133 @@ +"""Pytest configuration and shared fixtures for data-pipeline tests.""" + +import atexit +import sys +import warnings + +import pytest + +# Suppress noisy async context warnings from zarr/s3fs +warnings.filterwarnings("ignore", category=ResourceWarning) +warnings.filterwarnings("ignore", message="coroutine.*was never awaited") + + +# Global stderr filter that stays active even after pytest teardown +_original_stderr = sys.stderr +_suppress_traceback = False + + +class _FilteredStderr: + def write(self, text): + global _suppress_traceback + + # Start suppressing when we see async context errors + if any( + marker in text + for marker in [ + "Exception ignored", + "Traceback (most recent call last)", + "ValueError: 0 + assert "titiler.example.com" in xyz_links[0].href + href_lower = xyz_links[0].href.lower() + assert "%2fmeasurements%2freflectance%2fr60m%3ab04" in href_lower + assert "%2fmeasurements%2freflectance%2fr60m%3ab03" in href_lower + assert "%2fmeasurements%2freflectance%2fr60m%3ab02" in href_lower + + # Verify viewer link added + viewer_links = [link for link in test_pystac_item.links if link.rel == "viewer"] + assert len(viewer_links) > 0 + + # Verify EOPF Explorer link added + explorer_links = [link for link in test_pystac_item.links if "explorer" in link.href.lower()] + assert len(explorer_links) > 0 + + +@pytest.mark.integration +def test_add_visualization_links_s1(): + """Test add_visualization_links for Sentinel-1.""" + from scripts.register import add_visualization_links + + # Create S1 item + item = Item( + id="S1A_IW_GRDH_test", + geometry=None, + bbox=None, + datetime=datetime(2025, 1, 1, 0, 0, 0, tzinfo=UTC), + properties={}, + collection="sentinel-1-grd", + ) + item.add_asset( + "vh", + Asset( + href="s3://bucket/test.zarr/measurements/VH", + media_type="application/vnd+zarr", + roles=["data"], + ), + ) + + add_visualization_links( + item=item, + raster_base="https://titiler.example.com", + collection_id="sentinel-1-grd", + ) + + # Verify XYZ link contains VH + xyz_links = [link for link in item.links if link.rel == "xyz"] + assert len(xyz_links) > 0 + assert "VH" in xyz_links[0].href or "vh" in xyz_links[0].href.lower() + + +@pytest.mark.integration +def test_s3_to_https_conversion(): + """Test S3 URL to HTTPS conversion.""" + from scripts.register import s3_to_https + + result = s3_to_https("s3://bucket/path/file.zarr", "https://s3.example.com") + + assert result.startswith("https://") + assert "bucket" in result + assert "file.zarr" in result + + +@pytest.mark.integration +def test_rewrite_asset_hrefs(test_pystac_item): + """Test asset href rewriting from old to new base.""" + from scripts.register import rewrite_asset_hrefs + + rewrite_asset_hrefs( + item=test_pystac_item, + old_base="s3://bucket", + new_base="s3://new-bucket", + s3_endpoint="https://s3.example.com", + ) + + # Verify assets were rewritten + for asset in test_pystac_item.assets.values(): + assert "new-bucket" in asset.href + assert "bucket/" not in asset.href or "new-bucket" in asset.href