import unittest from src.evidence import make_evidence from src.models import ReportBundle, SiteSelection from src.report import build_board_markdown, build_markdown_report from src.safety import find_forbidden_phrases class ReportTests(unittest.TestCase): def test_report_contains_mandatory_safety_notes(self): selection = SiteSelection( id="S1", selection_type="pin_radius", coordinate_mode="wgs84", geometry_geojson=None, local_geometry=None, anchor_lat=21.0, anchor_lon=70.0, radius_m=250, area_sqm=196349.54, perimeter_m=1570.8, centroid=(21.0, 70.0), bbox=None, unit_source="meters", accuracy_label="pin-radius approximation", source_files=[], selected_boundary_id=None, limitations=["This is approximate context analysis, not exact boundary analysis."], ) evidence = [ make_evidence( category="Boundary", finding="Pin-radius selection created.", source_name="User input", source_url="", source_type="pin", resolution_or_scope="250 m radius", confidence="low", limitation="Not exact site boundary.", design_implication="Use for neighborhood context.", verification_needed="Confirm actual plot edges.", output_label="user_input", ) ] bundle = ReportBundle( board_markdown="## Board Pack\nInitial context.", evidence_rows=evidence, checklist_markdown="- Confirm actual plot edges.", diagram_paths=[], export_path=None, warnings=[], ) report = build_markdown_report("Demo Project", "Demo Site", selection, bundle) self.assertIn("Preliminary site-analysis assistant", report) self.assertIn("Verify on site", report) self.assertEqual(find_forbidden_phrases(report), []) def test_board_markdown_contains_detailed_workbook(self): selection = SiteSelection( id="S2", selection_type="drawn_polygon", coordinate_mode="wgs84", geometry_geojson=None, local_geometry=None, anchor_lat=21.002, anchor_lon=70.245, radius_m=None, area_sqm=48100.0, perimeter_m=920.0, centroid=(21.002, 70.245), bbox=None, unit_source="drawn map geometry", accuracy_label="drawn boundary approximation", source_files=[], selected_boundary_id=None, limitations=["Drawn map boundaries are approximate."], ) climate = { "forecast": { "current_temperature_c": 29.0, "current_humidity_pct": 72, "current_wind_speed_kmh": 14.0, }, "recent_historical": {"period": "recent archive sample"}, "climate_normal": {"period": "multi-year archive sample", "total_precipitation_mm": 812.4}, } osm_context = {"counts": {"roads/access": 12, "water": 1, "green": 3}} sun_summary = { "orientation_note": "Use north-south orientation checks for early massing.", "east_west_note": "Western exposure needs shading verification.", "wind_note": "Regional wind direction is modelled and needs site verification.", "limitation": "No surrounding-building shadow simulation.", } topography = { "mean_elevation_m": 11.2, "relief_m": 3.4, "approx_slope_pct": 1.2, "interpretation": "Public elevation samples suggest a gentle level change.", } soil = { "texture_signal": "clay-heavy topsoil signal", "clay_pct": 42.0, "sand_pct": 30.0, "silt_pct": 28.0, "ph_h2o": 7.2, "design_implication": "Check drainage and settlement risk with professional testing.", } board = build_board_markdown( "Resort Thesis", "Chorwad Site", selection, climate, osm_context, sun_summary, {"city": "Chorwad", "state": "Gujarat", "country": "India"}, topography=topography, soil=soil, ) self.assertIn("Detailed Site Analysis Workbook", board) self.assertIn("Reference Framework", board) self.assertIn("Urban Design Lab", board) self.assertIn("Diagram And Sheet Production Checklist", board) self.assertIn("Before, During And After Site Visit", board) self.assertIn("Public elevation signal", board) self.assertIn("Preliminary SoilGrids signal", board) self.assertNotIn("- -", board) self.assertEqual(find_forbidden_phrases(board), []) if __name__ == "__main__": unittest.main()