@@ -869,3 +869,83 @@ def test_api2_event_ordering(journalist_app, journalist_api_token, test_files):
869869
870870 # Event "2" (sent first, processed second) finds it missing.
871871 assert resp .json ["events" ]["3419026047977394171" ][0 ] == 410
872+
873+
874+ def test_api2_source_conversation_deleted_resubmission (
875+ journalist_app ,
876+ journalist_api_token ,
877+ test_files ,
878+ ):
879+ """
880+ A rejected event (409) MUST be handled (200) if corrected and resubmitted.
881+ An accepted (i.e., corrected) event MUST be acknowledged (208) if
882+ resubmitted.
883+ """
884+ with journalist_app .test_client () as app :
885+ source = test_files ["source" ]
886+ source_uuid = source .uuid
887+
888+ # 1. Submit with the wrong version --> Conflict (409).
889+ event = Event (
890+ id = "600100" ,
891+ target = SourceTarget (source_uuid = source_uuid , version = "wrong-version" ),
892+ type = EventType .SOURCE_CONVERSATION_DELETED ,
893+ )
894+ res1 = app .post (
895+ url_for ("api2.data" ),
896+ json = {"events" : [asdict (event )]},
897+ headers = get_api_headers (journalist_api_token ),
898+ )
899+ assert res1 .status_code == 200
900+ assert res1 .json ["events" ][event .id ][0 ] == 409
901+
902+ # Confirm that nothing has been deleted.
903+ for submission in test_files ["submissions" ]:
904+ assert (
905+ Submission .query .filter (Submission .uuid == submission .uuid ).one_or_none ()
906+ is not None
907+ )
908+ for reply in test_files ["replies" ]:
909+ assert Reply .query .filter (Reply .uuid == reply .uuid ).one_or_none () is not None
910+
911+ expected_item_uuids = {item .uuid for item in test_files ["submissions" ]}
912+ expected_item_uuids .update ({item .uuid for item in test_files ["replies" ]})
913+
914+ # 2. Resubmit the same event with the correct version --> OK (200).
915+ index = app .get (
916+ url_for ("api2.index" ),
917+ headers = get_api_headers (journalist_api_token ),
918+ )
919+ assert index .status_code == 200
920+ correct_version = index .json ["sources" ][source_uuid ]
921+
922+ event .target = SourceTarget (source_uuid = source_uuid , version = correct_version )
923+ res2 = app .post (
924+ url_for ("api2.data" ),
925+ json = {"events" : [asdict (event )]},
926+ headers = get_api_headers (journalist_api_token ),
927+ )
928+ assert res2 .status_code == 200
929+ assert res2 .json ["events" ][event .id ] == [200 , None ]
930+
931+ # Confirm that items are returned as deleted.
932+ assert res2 .json ["sources" ][source_uuid ] is not None
933+ for item_uuid in expected_item_uuids :
934+ assert item_uuid in res2 .json ["items" ]
935+ assert res2 .json ["items" ][item_uuid ] is None
936+
937+ # Confirm that items have actually been deleted.
938+ for submission in test_files ["submissions" ]:
939+ assert Submission .query .filter (Submission .uuid == submission .uuid ).one_or_none () is None
940+ for reply in test_files ["replies" ]:
941+ assert Reply .query .filter (Reply .uuid == reply .uuid ).one_or_none () is None
942+ assert Source .query .filter (Source .uuid == source_uuid ).one_or_none () is not None
943+
944+ # 3. Resubmit the same event again --> Already Reported (208).
945+ res3 = app .post (
946+ url_for ("api2.data" ),
947+ json = {"events" : [asdict (event )]},
948+ headers = get_api_headers (journalist_api_token ),
949+ )
950+ assert res3 .status_code == 200
951+ assert res3 .json ["events" ][event .id ][0 ] == 208
0 commit comments