This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/geo-service/tests/test_aoi.py
Benjamin Admin 21a844cb8a fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00

272 lines
8.8 KiB
Python

"""
Tests for AOI Packager Service
"""
import pytest
from unittest.mock import patch, MagicMock, AsyncMock
import json
import sys
sys.path.insert(0, '/app')
from services.aoi_packager import AOIPackagerService
class TestAOIPackagerService:
"""Tests for AOI Packager Service."""
@pytest.fixture
def service(self):
"""Create service instance."""
return AOIPackagerService()
def test_calculate_area_km2_small_polygon(self, service):
"""Test area calculation for small polygon."""
polygon = {
"type": "Polygon",
"coordinates": [
[
[9.19, 47.70],
[9.20, 47.70],
[9.20, 47.71],
[9.19, 47.71],
[9.19, 47.70],
]
],
}
area = service.calculate_area_km2(polygon)
# Should be approximately 1 km² (rough estimate)
assert 0.5 < area < 2.0
def test_calculate_area_km2_mainau(self, service):
"""Test area calculation for Mainau island polygon."""
polygon = {
"type": "Polygon",
"coordinates": [
[
[9.1875, 47.7055],
[9.1975, 47.7055],
[9.1975, 47.7115],
[9.1875, 47.7115],
[9.1875, 47.7055],
]
],
}
area = service.calculate_area_km2(polygon)
# Mainau template claims ~0.45 km²
assert 0.3 < area < 1.0
def test_is_within_germany_valid(self, service):
"""Test polygon within Germany."""
polygon = {
"type": "Polygon",
"coordinates": [
[
[9.19, 47.70],
[9.20, 47.70],
[9.20, 47.71],
[9.19, 47.71],
[9.19, 47.70],
]
],
}
assert service.is_within_germany(polygon) == True
def test_is_within_germany_outside(self, service):
"""Test polygon outside Germany."""
# Paris
polygon = {
"type": "Polygon",
"coordinates": [
[
[2.3, 48.8],
[2.4, 48.8],
[2.4, 48.9],
[2.3, 48.9],
[2.3, 48.8],
]
],
}
assert service.is_within_germany(polygon) == False
def test_validate_polygon_valid(self, service):
"""Test valid polygon validation."""
polygon = {
"type": "Polygon",
"coordinates": [
[
[9.19, 47.70],
[9.20, 47.70],
[9.20, 47.71],
[9.19, 47.71],
[9.19, 47.70],
]
],
}
is_valid, message = service.validate_polygon(polygon)
assert is_valid == True
assert message == "Valid"
def test_validate_polygon_not_closed(self, service):
"""Test polygon validation with unclosed ring."""
polygon = {
"type": "Polygon",
"coordinates": [
[
[9.19, 47.70],
[9.20, 47.70],
[9.20, 47.71],
[9.19, 47.71],
# Missing closing point
]
],
}
is_valid, message = service.validate_polygon(polygon)
assert is_valid == False
assert "closed" in message.lower()
def test_validate_polygon_wrong_type(self, service):
"""Test polygon validation with wrong geometry type."""
polygon = {
"type": "Point",
"coordinates": [9.19, 47.70],
}
is_valid, message = service.validate_polygon(polygon)
assert is_valid == False
assert "Polygon" in message
def test_estimate_bundle_size_low(self, service):
"""Test bundle size estimation for low quality."""
size = service.estimate_bundle_size_mb(1.0, "low")
assert size == 10.0
def test_estimate_bundle_size_medium(self, service):
"""Test bundle size estimation for medium quality."""
size = service.estimate_bundle_size_mb(1.0, "medium")
assert size == 25.0
def test_estimate_bundle_size_high(self, service):
"""Test bundle size estimation for high quality."""
size = service.estimate_bundle_size_mb(1.0, "high")
assert size == 50.0
def test_estimate_bundle_size_scales_with_area(self, service):
"""Test bundle size scales with area."""
size_1km = service.estimate_bundle_size_mb(1.0, "medium")
size_2km = service.estimate_bundle_size_mb(2.0, "medium")
assert size_2km == size_1km * 2
class TestGeoUtils:
"""Tests for geo utility functions."""
def test_lat_lon_to_tile_berlin(self):
"""Test tile conversion for Berlin."""
from utils.geo_utils import lat_lon_to_tile
# Berlin: 52.52, 13.405
x, y = lat_lon_to_tile(52.52, 13.405, 10)
# At zoom 10, Berlin should be around tile 550, 335
assert 540 < x < 560
assert 325 < y < 345
def test_tile_to_bounds(self):
"""Test tile to bounds conversion."""
from utils.geo_utils import tile_to_bounds
west, south, east, north = tile_to_bounds(10, 550, 335)
# Should return valid bounds
assert west < east
assert south < north
# Should be somewhere in Germany
assert 5 < west < 20
assert 45 < south < 60
def test_calculate_distance(self):
"""Test distance calculation."""
from utils.geo_utils import calculate_distance
# Berlin to Munich: ~504 km
dist = calculate_distance(52.52, 13.405, 48.1351, 11.582)
assert 450000 < dist < 550000 # meters
def test_get_germany_bounds(self):
"""Test Germany bounds."""
from utils.geo_utils import get_germany_bounds
west, south, east, north = get_germany_bounds()
assert west == 5.87
assert south == 47.27
assert east == 15.04
assert north == 55.06
class TestLicenseChecker:
"""Tests for license checker utility."""
def test_osm_source_allowed(self):
"""Test OSM source is allowed."""
from utils.license_checker import LicenseChecker, DataSource
assert LicenseChecker.is_source_allowed(DataSource.OPENSTREETMAP) == True
def test_copernicus_source_allowed(self):
"""Test Copernicus source is allowed."""
from utils.license_checker import LicenseChecker, DataSource
assert LicenseChecker.is_source_allowed(DataSource.COPERNICUS_DEM) == True
def test_google_source_forbidden(self):
"""Test Google source is forbidden."""
from utils.license_checker import LicenseChecker, DataSource
assert LicenseChecker.is_source_allowed(DataSource.GOOGLE) == False
def test_validate_osm_url(self):
"""Test OSM URL validation."""
from utils.license_checker import LicenseChecker
is_allowed, message = LicenseChecker.validate_url(
"https://tile.openstreetmap.org/10/550/335.png"
)
assert is_allowed == True
assert "ALLOWED" in message
def test_validate_google_url(self):
"""Test Google URL validation."""
from utils.license_checker import LicenseChecker
is_allowed, message = LicenseChecker.validate_url(
"https://maps.googleapis.com/maps/api/staticmap"
)
assert is_allowed == False
assert "FORBIDDEN" in message
def test_get_attribution_for_sources(self):
"""Test getting attribution for sources."""
from utils.license_checker import LicenseChecker, DataSource
sources = [DataSource.OPENSTREETMAP, DataSource.COPERNICUS_DEM]
attributions = LicenseChecker.get_attribution_for_sources(sources)
assert len(attributions) == 2
assert any("OpenStreetMap" in a["name"] for a in attributions)
assert any("Copernicus" in a["name"] for a in attributions)
def test_check_commercial_use_allowed(self):
"""Test commercial use check for allowed sources."""
from utils.license_checker import LicenseChecker, DataSource
sources = [DataSource.OPENSTREETMAP, DataSource.COPERNICUS_DEM]
allowed, issues = LicenseChecker.check_commercial_use(sources)
assert allowed == True
assert len(issues) == 0
def test_check_commercial_use_forbidden(self):
"""Test commercial use check with forbidden source."""
from utils.license_checker import LicenseChecker, DataSource
sources = [DataSource.OPENSTREETMAP, DataSource.GOOGLE]
allowed, issues = LicenseChecker.check_commercial_use(sources)
assert allowed == False
assert len(issues) > 0