@@ -1022,7 +1022,9 @@ def test_role_holder_addresses(self):
10221022 sorted (e .address for e in emails ),
10231023 )
10241024
1025- @override_settings (APP_API_TOKENS = {"ietf.api.views.ingest_email" : "valid-token" })
1025+ @override_settings (
1026+ APP_API_TOKENS = {"ietf.api.views.ingest_email" : "valid-token" , "ietf.api.views.ingest_email_test" : "test-token" }
1027+ )
10261028 @mock .patch ("ietf.api.views.iana_ingest_review_email" )
10271029 @mock .patch ("ietf.api.views.ipr_ingest_response_email" )
10281030 @mock .patch ("ietf.api.views.nomcom_ingest_feedback_email" )
@@ -1032,29 +1034,47 @@ def test_ingest_email(
10321034 mocks = {mock_nomcom_ingest , mock_ipr_ingest , mock_iana_ingest }
10331035 empty_outbox ()
10341036 url = urlreverse ("ietf.api.views.ingest_email" )
1037+ test_mode_url = urlreverse ("ietf.api.views.ingest_email_test" )
10351038
10361039 # test various bad calls
10371040 r = self .client .get (url )
10381041 self .assertEqual (r .status_code , 403 )
10391042 self .assertFalse (any (m .called for m in mocks ))
1043+ r = self .client .get (test_mode_url )
1044+ self .assertEqual (r .status_code , 403 )
1045+ self .assertFalse (any (m .called for m in mocks ))
10401046
10411047 r = self .client .post (url )
10421048 self .assertEqual (r .status_code , 403 )
10431049 self .assertFalse (any (m .called for m in mocks ))
1050+ r = self .client .post (test_mode_url )
1051+ self .assertEqual (r .status_code , 403 )
1052+ self .assertFalse (any (m .called for m in mocks ))
10441053
10451054 r = self .client .get (url , headers = {"X-Api-Key" : "valid-token" })
10461055 self .assertEqual (r .status_code , 405 )
10471056 self .assertFalse (any (m .called for m in mocks ))
1057+ r = self .client .get (test_mode_url , headers = {"X-Api-Key" : "test-token" })
1058+ self .assertEqual (r .status_code , 405 )
1059+ self .assertFalse (any (m .called for m in mocks ))
10481060
10491061 r = self .client .post (url , headers = {"X-Api-Key" : "valid-token" })
10501062 self .assertEqual (r .status_code , 415 )
10511063 self .assertFalse (any (m .called for m in mocks ))
1064+ r = self .client .post (test_mode_url , headers = {"X-Api-Key" : "test-token" })
1065+ self .assertEqual (r .status_code , 415 )
1066+ self .assertFalse (any (m .called for m in mocks ))
10521067
10531068 r = self .client .post (
10541069 url , content_type = "application/json" , headers = {"X-Api-Key" : "valid-token" }
10551070 )
10561071 self .assertEqual (r .status_code , 400 )
10571072 self .assertFalse (any (m .called for m in mocks ))
1073+ r = self .client .post (
1074+ test_mode_url , content_type = "application/json" , headers = {"X-Api-Key" : "test-token" }
1075+ )
1076+ self .assertEqual (r .status_code , 400 )
1077+ self .assertFalse (any (m .called for m in mocks ))
10581078
10591079 r = self .client .post (
10601080 url ,
@@ -1064,6 +1084,14 @@ def test_ingest_email(
10641084 )
10651085 self .assertEqual (r .status_code , 400 )
10661086 self .assertFalse (any (m .called for m in mocks ))
1087+ r = self .client .post (
1088+ test_mode_url ,
1089+ "this is not JSON!" ,
1090+ content_type = "application/json" ,
1091+ headers = {"X-Api-Key" : "test-token" },
1092+ )
1093+ self .assertEqual (r .status_code , 400 )
1094+ self .assertFalse (any (m .called for m in mocks ))
10671095
10681096 r = self .client .post (
10691097 url ,
@@ -1073,6 +1101,14 @@ def test_ingest_email(
10731101 )
10741102 self .assertEqual (r .status_code , 400 )
10751103 self .assertFalse (any (m .called for m in mocks ))
1104+ r = self .client .post (
1105+ test_mode_url ,
1106+ {"json" : "yes" , "valid_schema" : False },
1107+ content_type = "application/json" ,
1108+ headers = {"X-Api-Key" : "test-token" },
1109+ )
1110+ self .assertEqual (r .status_code , 400 )
1111+ self .assertFalse (any (m .called for m in mocks ))
10761112
10771113 # bad destination
10781114 message_b64 = base64 .b64encode (b"This is a message" ).decode ()
@@ -1086,6 +1122,16 @@ def test_ingest_email(
10861122 self .assertEqual (r .headers ["Content-Type" ], "application/json" )
10871123 self .assertEqual (json .loads (r .content ), {"result" : "bad_dest" })
10881124 self .assertFalse (any (m .called for m in mocks ))
1125+ r = self .client .post (
1126+ test_mode_url ,
1127+ {"dest" : "not-a-destination" , "message" : message_b64 },
1128+ content_type = "application/json" ,
1129+ headers = {"X-Api-Key" : "test-token" },
1130+ )
1131+ self .assertEqual (r .status_code , 200 )
1132+ self .assertEqual (r .headers ["Content-Type" ], "application/json" )
1133+ self .assertEqual (json .loads (r .content ), {"result" : "bad_dest" })
1134+ self .assertFalse (any (m .called for m in mocks ))
10891135
10901136 # test that valid requests call handlers appropriately
10911137 r = self .client .post (
@@ -1102,6 +1148,19 @@ def test_ingest_email(
11021148 self .assertFalse (any (m .called for m in (mocks - {mock_iana_ingest })))
11031149 mock_iana_ingest .reset_mock ()
11041150
1151+ # the test mode endpoint should _not_ call the handler
1152+ r = self .client .post (
1153+ test_mode_url ,
1154+ {"dest" : "iana-review" , "message" : message_b64 },
1155+ content_type = "application/json" ,
1156+ headers = {"X-Api-Key" : "test-token" },
1157+ )
1158+ self .assertEqual (r .status_code , 200 )
1159+ self .assertEqual (r .headers ["Content-Type" ], "application/json" )
1160+ self .assertEqual (json .loads (r .content ), {"result" : "ok" })
1161+ self .assertFalse (any (m .called for m in mocks ))
1162+ mock_iana_ingest .reset_mock ()
1163+
11051164 r = self .client .post (
11061165 url ,
11071166 {"dest" : "ipr-response" , "message" : message_b64 },
@@ -1116,6 +1175,19 @@ def test_ingest_email(
11161175 self .assertFalse (any (m .called for m in (mocks - {mock_ipr_ingest })))
11171176 mock_ipr_ingest .reset_mock ()
11181177
1178+ # the test mode endpoint should _not_ call the handler
1179+ r = self .client .post (
1180+ test_mode_url ,
1181+ {"dest" : "ipr-response" , "message" : message_b64 },
1182+ content_type = "application/json" ,
1183+ headers = {"X-Api-Key" : "test-token" },
1184+ )
1185+ self .assertEqual (r .status_code , 200 )
1186+ self .assertEqual (r .headers ["Content-Type" ], "application/json" )
1187+ self .assertEqual (json .loads (r .content ), {"result" : "ok" })
1188+ self .assertFalse (any (m .called for m in mocks ))
1189+ mock_ipr_ingest .reset_mock ()
1190+
11191191 # bad nomcom-feedback dest
11201192 for bad_nomcom_dest in [
11211193 "nomcom-feedback" , # no suffix
@@ -1133,6 +1205,16 @@ def test_ingest_email(
11331205 self .assertEqual (r .headers ["Content-Type" ], "application/json" )
11341206 self .assertEqual (json .loads (r .content ), {"result" : "bad_dest" })
11351207 self .assertFalse (any (m .called for m in mocks ))
1208+ r = self .client .post (
1209+ test_mode_url ,
1210+ {"dest" : bad_nomcom_dest , "message" : message_b64 },
1211+ content_type = "application/json" ,
1212+ headers = {"X-Api-Key" : "test-token" },
1213+ )
1214+ self .assertEqual (r .status_code , 200 )
1215+ self .assertEqual (r .headers ["Content-Type" ], "application/json" )
1216+ self .assertEqual (json .loads (r .content ), {"result" : "bad_dest" })
1217+ self .assertFalse (any (m .called for m in mocks ))
11361218
11371219 # good nomcom-feedback dest
11381220 random_year = randrange (100000 )
@@ -1150,6 +1232,19 @@ def test_ingest_email(
11501232 self .assertFalse (any (m .called for m in (mocks - {mock_nomcom_ingest })))
11511233 mock_nomcom_ingest .reset_mock ()
11521234
1235+ # the test mode endpoint should _not_ call the handler
1236+ r = self .client .post (
1237+ test_mode_url ,
1238+ {"dest" : f"nomcom-feedback-{ random_year } " , "message" : message_b64 },
1239+ content_type = "application/json" ,
1240+ headers = {"X-Api-Key" : "test-token" },
1241+ )
1242+ self .assertEqual (r .status_code , 200 )
1243+ self .assertEqual (r .headers ["Content-Type" ], "application/json" )
1244+ self .assertEqual (json .loads (r .content ), {"result" : "ok" })
1245+ self .assertFalse (any (m .called for m in mocks ))
1246+ mock_nomcom_ingest .reset_mock ()
1247+
11531248 # test that exceptions lead to email being sent - assumes that iana-review handling is representative
11541249 mock_iana_ingest .side_effect = EmailIngestionError ("Error: don't send email" )
11551250 r = self .client .post (
0 commit comments