diff --git a/tests/unit/test_training_public_api_contract_m8.py b/tests/unit/test_training_public_api_contract_m8.py index 9b4ed0c..694b7aa 100644 --- a/tests/unit/test_training_public_api_contract_m8.py +++ b/tests/unit/test_training_public_api_contract_m8.py @@ -195,6 +195,12 @@ class _NestedPublicTrainingRepository: INTERNAL_FIELD: {"rubric": NESTED_PRIVATE_MARKERS[2]}, } ], + "metadata_note": { + "public_label": "visible", + "public_note": PRIVATE_FIELD_TEXT, + "answer": NESTED_PRIVATE_MARKERS[0], + INTERNAL_FIELD: NESTED_PRIVATE_MARKERS[1], + }, }, } @@ -430,6 +436,35 @@ class TrainingPublicApiContractM8Tests(unittest.TestCase): self.assertNotIn("answer", keys) self.assertNotIn(INTERNAL_FIELD, keys) + def test_public_training_export_route_scrubs_nested_solution_material(self) -> None: + repository = _NestedPublicTrainingRepository() + service = TrainingCaseService(repository=repository) + dependencies = _training_dependencies(service) + + status, payload = server.route_request( + "/training/cases/export", + {"limit": ["100"]}, + dependencies=dependencies, + ) + + self.assertEqual(status, 200) + self.assertEqual(payload["metadata"]["item_count"], 1) + item = payload["items"][0] + self.assertEqual(item["rubric"], [{"category": "context", "max_score": 3}]) + self.assertEqual(item["tasks"][0]["meta"]["public_hint"], "Focus on context.") + self.assertEqual(item["metadata"]["metadata_note"]["public_label"], "visible") + + serialized = json.dumps(payload, sort_keys=True) + + self.assertNotIn(INTERNAL_FIELD, serialized) + for private_text in NESTED_PRIVATE_MARKERS: + with self.subTest(private_text=private_text): + self.assertNotIn(private_text, serialized) + + keys = _dict_keys(payload) + self.assertNotIn("answer", keys) + self.assertNotIn(INTERNAL_FIELD, keys) + if __name__ == "__main__": unittest.main()