import unittest from unittest.mock import patch from src.geometry import selection_from_lat_lon from src.safety import find_forbidden_phrases from src.soil import fetch_soil def _soil_payload(clay=420, sand=300, silt=280, phh2o=72): return { "properties": { "layers": [ {"name": "clay", "depths": [{"values": {"mean": clay}}]}, {"name": "sand", "depths": [{"values": {"mean": sand}}]}, {"name": "silt", "depths": [{"values": {"mean": silt}}]}, {"name": "phh2o", "depths": [{"values": {"mean": phh2o}}]}, {"name": "bdod", "depths": [{"values": {"mean": 140}}]}, {"name": "soc", "depths": [{"values": {"mean": 18}}]}, ] } } class SoilTests(unittest.TestCase): def test_fetch_soil_interprets_clay_heavy_signal_safely(self): selection = selection_from_lat_lon(21.002, 70.245, radius_m=250) with patch("src.soil.get_json", return_value=_soil_payload()): soil, evidence = fetch_soil(selection) self.assertEqual(soil["texture_signal"], "clay-heavy topsoil signal") self.assertEqual(soil["clay_pct"], 42.0) self.assertEqual(soil["ph_h2o"], 7.2) joined = evidence[0].finding + evidence[0].design_implication + evidence[0].verification_needed self.assertIn("professional", joined) self.assertEqual(find_forbidden_phrases(joined), []) def test_fetch_soil_failure_returns_missing_data_evidence(self): selection = selection_from_lat_lon(21.002, 70.245, radius_m=250) with patch("src.soil.get_json", side_effect=TimeoutError("slow")): soil, evidence = fetch_soil(selection) self.assertEqual(soil, {}) self.assertEqual(evidence[0].confidence, "low") self.assertIn("Do not infer soil type", evidence[0].design_implication) if __name__ == "__main__": unittest.main()