tangled
alpha
login
or
join now
urschrei.eurosky.social
/
pyzotero
0
fork
atom
Pyzotero: a Python client for the Zotero API
pyzotero.readthedocs.io
zotero
0
fork
atom
overview
issues
pulls
pipelines
More upload and attachment tests
urschrei.eurosky.social
1 year ago
54f2acca
a18874de
+298
1 changed file
expand all
collapse all
unified
split
tests
test_zotero.py
+298
tests/test_zotero.py
···
859
859
860
860
self.assertTrue(resp)
861
861
862
862
+
@httpretty.activate
863
863
+
def testFileUpload(self):
864
864
+
"""Tests file upload process with attachments"""
865
865
+
zot = z.Zotero("myuserID", "user", "myuserkey")
866
866
+
867
867
+
# Create a temporary file for testing
868
868
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
869
869
+
with open(temp_file_path, "w") as f:
870
870
+
f.write("Test file content for upload")
871
871
+
872
872
+
# Mock Step 0: Create preliminary item registration
873
873
+
prelim_response = {
874
874
+
"success": {
875
875
+
"0": "ITEMKEY123"
876
876
+
}
877
877
+
}
878
878
+
HTTPretty.register_uri(
879
879
+
HTTPretty.POST,
880
880
+
"https://api.zotero.org/users/myuserID/items",
881
881
+
content_type="application/json",
882
882
+
body=json.dumps(prelim_response),
883
883
+
status=200,
884
884
+
)
885
885
+
886
886
+
# Create the upload payload
887
887
+
payload = [{"filename": "test_upload_file.txt", "title": "Test File", "linkMode": "imported_file"}]
888
888
+
889
889
+
# Create mock auth data to be returned by _get_auth
890
890
+
mock_auth_data = {
891
891
+
"url": "https://uploads.zotero.org/",
892
892
+
"params": {
893
893
+
"key": "abcdef1234567890",
894
894
+
"prefix": "prefix",
895
895
+
"suffix": "suffix"
896
896
+
},
897
897
+
"uploadKey": "upload_key_123"
898
898
+
}
899
899
+
900
900
+
# Patch the necessary methods to avoid HTTP calls and file system checks
901
901
+
with patch.object(z.Zupload, '_verify', return_value=None), \
902
902
+
patch.object(z.Zupload, '_get_auth', return_value=mock_auth_data), \
903
903
+
patch.object(z.Zupload, '_upload_file', return_value=None):
904
904
+
# Create the upload object and initiate upload
905
905
+
upload = z.Zupload(zot, payload, basedir=os.path.join(self.cwd, "api_responses"))
906
906
+
result = upload.upload()
907
907
+
908
908
+
# Verify the result structure
909
909
+
self.assertIn("success", result)
910
910
+
self.assertIn("failure", result)
911
911
+
self.assertIn("unchanged", result)
912
912
+
self.assertEqual(len(result["success"]), 1)
913
913
+
self.assertEqual(result["success"][0]["key"], "ITEMKEY123")
914
914
+
915
915
+
# Clean up
916
916
+
os.remove(temp_file_path)
917
917
+
918
918
+
@httpretty.activate
919
919
+
def testFileUploadExists(self):
920
920
+
"""Tests file upload process when the file already exists on the server"""
921
921
+
zot = z.Zotero("myuserID", "user", "myuserkey")
922
922
+
923
923
+
# Create a temporary file for testing
924
924
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
925
925
+
with open(temp_file_path, "w") as f:
926
926
+
f.write("Test file content for upload")
927
927
+
928
928
+
# Mock Step 0: Create preliminary item registration
929
929
+
prelim_response = {
930
930
+
"success": {
931
931
+
"0": "ITEMKEY123"
932
932
+
}
933
933
+
}
934
934
+
HTTPretty.register_uri(
935
935
+
HTTPretty.POST,
936
936
+
"https://api.zotero.org/users/myuserID/items",
937
937
+
content_type="application/json",
938
938
+
body=json.dumps(prelim_response),
939
939
+
status=200,
940
940
+
)
941
941
+
942
942
+
# Create the upload payload
943
943
+
payload = [{"filename": "test_upload_file.txt", "title": "Test File", "linkMode": "imported_file"}]
944
944
+
945
945
+
# Create mock auth data to be returned by _get_auth with exists=True
946
946
+
mock_auth_data = {
947
947
+
"exists": True
948
948
+
}
949
949
+
950
950
+
# Patch the necessary methods to avoid HTTP calls and file system checks
951
951
+
with patch.object(z.Zupload, '_verify', return_value=None), \
952
952
+
patch.object(z.Zupload, '_get_auth', return_value=mock_auth_data):
953
953
+
# Create the upload object and initiate upload
954
954
+
upload = z.Zupload(zot, payload, basedir=os.path.join(self.cwd, "api_responses"))
955
955
+
result = upload.upload()
956
956
+
957
957
+
# Verify the result structure
958
958
+
self.assertIn("success", result)
959
959
+
self.assertIn("failure", result)
960
960
+
self.assertIn("unchanged", result)
961
961
+
self.assertEqual(len(result["unchanged"]), 1)
962
962
+
self.assertEqual(result["unchanged"][0]["key"], "ITEMKEY123")
963
963
+
964
964
+
# Clean up
965
965
+
os.remove(temp_file_path)
966
966
+
967
967
+
@httpretty.activate
968
968
+
def testFileUploadWithParentItem(self):
969
969
+
"""Tests file upload process with a parent item ID"""
970
970
+
zot = z.Zotero("myuserID", "user", "myuserkey")
971
971
+
972
972
+
# Create a temporary file for testing
973
973
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
974
974
+
with open(temp_file_path, "w") as f:
975
975
+
f.write("Test file content for upload")
976
976
+
977
977
+
# Mock Step 0: Create preliminary item registration
978
978
+
prelim_response = {
979
979
+
"success": {
980
980
+
"0": "ITEMKEY123"
981
981
+
}
982
982
+
}
983
983
+
HTTPretty.register_uri(
984
984
+
HTTPretty.POST,
985
985
+
"https://api.zotero.org/users/myuserID/items",
986
986
+
content_type="application/json",
987
987
+
body=json.dumps(prelim_response),
988
988
+
status=200,
989
989
+
)
990
990
+
991
991
+
# Create the upload payload
992
992
+
payload = [{"filename": "test_upload_file.txt", "title": "Test File", "linkMode": "imported_file"}]
993
993
+
994
994
+
# Test with parent ID
995
995
+
parent_id = "PARENTITEM123"
996
996
+
997
997
+
# Create mock auth data to be returned by _get_auth
998
998
+
mock_auth_data = {
999
999
+
"url": "https://uploads.zotero.org/",
1000
1000
+
"params": {
1001
1001
+
"key": "abcdef1234567890",
1002
1002
+
"prefix": "prefix",
1003
1003
+
"suffix": "suffix"
1004
1004
+
},
1005
1005
+
"uploadKey": "upload_key_123"
1006
1006
+
}
1007
1007
+
1008
1008
+
# Mock Step 1: Get upload authorization
1009
1009
+
HTTPretty.register_uri(
1010
1010
+
HTTPretty.POST,
1011
1011
+
"https://api.zotero.org/users/myuserID/items/ITEMKEY123/file",
1012
1012
+
content_type="application/json",
1013
1013
+
body=json.dumps(mock_auth_data),
1014
1014
+
status=200,
1015
1015
+
)
1016
1016
+
1017
1017
+
# Patch the necessary methods to avoid file system checks and skip the actual upload
1018
1018
+
with patch.object(z.Zupload, '_verify', return_value=None), \
1019
1019
+
patch.object(z.Zupload, '_upload_file', return_value=None):
1020
1020
+
# Create the upload object with a parent ID and initiate upload
1021
1021
+
upload = z.Zupload(zot, payload, parentid=parent_id, basedir=os.path.join(self.cwd, "api_responses"))
1022
1022
+
result = upload.upload()
1023
1023
+
1024
1024
+
# Verify the result structure
1025
1025
+
self.assertIn("success", result)
1026
1026
+
self.assertEqual(len(result["success"]), 1)
1027
1027
+
1028
1028
+
# Check that the parentItem was added to the payload
1029
1029
+
# Get the latest request to the items endpoint
1030
1030
+
requests = httpretty.latest_requests()
1031
1031
+
item_request = None
1032
1032
+
for req in requests:
1033
1033
+
if req.url.endswith("/items"):
1034
1034
+
item_request = req
1035
1035
+
break
1036
1036
+
1037
1037
+
self.assertIsNotNone(item_request, "No request found to the items endpoint")
1038
1038
+
request_body = json.loads(item_request.body.decode('utf-8'))
1039
1039
+
self.assertEqual(request_body[0]["parentItem"], parent_id)
1040
1040
+
1041
1041
+
# Clean up
1042
1042
+
os.remove(temp_file_path)
1043
1043
+
1044
1044
+
@httpretty.activate
1045
1045
+
def testFileUploadFailure(self):
1046
1046
+
"""Tests file upload process when auth step fails"""
1047
1047
+
zot = z.Zotero("myuserID", "user", "myuserkey")
1048
1048
+
1049
1049
+
# Create a temporary file for testing
1050
1050
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
1051
1051
+
with open(temp_file_path, "w") as f:
1052
1052
+
f.write("Test file content for upload")
1053
1053
+
1054
1054
+
# Mock Step 0: Create preliminary item registration
1055
1055
+
prelim_response = {
1056
1056
+
"success": {
1057
1057
+
"0": "ITEMKEY123"
1058
1058
+
}
1059
1059
+
}
1060
1060
+
HTTPretty.register_uri(
1061
1061
+
HTTPretty.POST,
1062
1062
+
"https://api.zotero.org/users/myuserID/items",
1063
1063
+
content_type="application/json",
1064
1064
+
body=json.dumps(prelim_response),
1065
1065
+
status=200,
1066
1066
+
)
1067
1067
+
1068
1068
+
# Mock Step 1: Authorization fails with 403
1069
1069
+
HTTPretty.register_uri(
1070
1070
+
HTTPretty.POST,
1071
1071
+
"https://api.zotero.org/users/myuserID/items/ITEMKEY123/file",
1072
1072
+
status=403,
1073
1073
+
)
1074
1074
+
1075
1075
+
# Create the upload payload
1076
1076
+
payload = [{"filename": "test_upload_file.txt", "title": "Test File", "linkMode": "imported_file"}]
1077
1077
+
1078
1078
+
# Patch just the _verify method to avoid file system checks, but allow the real HTTP calls
1079
1079
+
with patch.object(z.Zupload, '_verify', return_value=None):
1080
1080
+
# Create the upload object and test for exception
1081
1081
+
upload = z.Zupload(zot, payload, basedir=os.path.join(self.cwd, "api_responses"))
1082
1082
+
1083
1083
+
# This should raise an error due to 403 status
1084
1084
+
with self.assertRaises(z.ze.UserNotAuthorisedError):
1085
1085
+
upload.upload()
1086
1086
+
1087
1087
+
# Clean up
1088
1088
+
os.remove(temp_file_path)
1089
1089
+
1090
1090
+
@httpretty.activate
1091
1091
+
def testFileUploadWithPreexistingKeys(self):
1092
1092
+
"""Tests file upload process when the payload already contains keys"""
1093
1093
+
zot = z.Zotero("myuserID", "user", "myuserkey")
1094
1094
+
1095
1095
+
# Create a temporary file for testing
1096
1096
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
1097
1097
+
with open(temp_file_path, "w") as f:
1098
1098
+
f.write("Test file content for upload")
1099
1099
+
1100
1100
+
# Create the upload payload with preexisting key
1101
1101
+
payload = [{"key": "PREEXISTING123", "filename": "test_upload_file.txt", "title": "Test File", "linkMode": "imported_file"}]
1102
1102
+
1103
1103
+
# Create mock auth data to be returned by _get_auth
1104
1104
+
mock_auth_data = {
1105
1105
+
"url": "https://uploads.zotero.org/",
1106
1106
+
"params": {
1107
1107
+
"key": "abcdef1234567890",
1108
1108
+
"prefix": "prefix",
1109
1109
+
"suffix": "suffix"
1110
1110
+
},
1111
1111
+
"uploadKey": "upload_key_123"
1112
1112
+
}
1113
1113
+
1114
1114
+
# Patch the necessary methods to avoid HTTP calls and file system checks
1115
1115
+
with patch.object(z.Zupload, '_verify', return_value=None), \
1116
1116
+
patch.object(z.Zupload, '_get_auth', return_value=mock_auth_data), \
1117
1117
+
patch.object(z.Zupload, '_upload_file', return_value=None):
1118
1118
+
# Create the upload object and initiate upload
1119
1119
+
upload = z.Zupload(zot, payload, basedir=os.path.join(self.cwd, "api_responses"))
1120
1120
+
result = upload.upload()
1121
1121
+
1122
1122
+
# Verify the result structure
1123
1123
+
self.assertIn("success", result)
1124
1124
+
self.assertEqual(len(result["success"]), 1)
1125
1125
+
self.assertEqual(result["success"][0]["key"], "PREEXISTING123")
1126
1126
+
1127
1127
+
# No need to check for endpoint calls since we're patching the methods
1128
1128
+
1129
1129
+
# Clean up
1130
1130
+
os.remove(temp_file_path)
1131
1131
+
1132
1132
+
@httpretty.activate
1133
1133
+
def testFileUploadInvalidPayload(self):
1134
1134
+
"""Tests file upload process with invalid payload mixing items with and without keys"""
1135
1135
+
zot = z.Zotero("myuserID", "user", "myuserkey")
1136
1136
+
1137
1137
+
# Create a temporary file for testing
1138
1138
+
temp_file_path = os.path.join(self.cwd, "api_responses", "test_upload_file.txt")
1139
1139
+
with open(temp_file_path, "w") as f:
1140
1140
+
f.write("Test file content for upload")
1141
1141
+
1142
1142
+
# Create the invalid upload payload (mixing items with and without keys)
1143
1143
+
payload = [
1144
1144
+
{"key": "PREEXISTING123", "filename": "test_upload_file.txt"},
1145
1145
+
{"filename": "test_upload_file.txt"} # No key
1146
1146
+
]
1147
1147
+
1148
1148
+
# Patch the _verify method to avoid file system checks
1149
1149
+
with patch.object(z.Zupload, '_verify', return_value=None):
1150
1150
+
# Create the upload object and test for exception
1151
1151
+
upload = z.Zupload(zot, payload, basedir=os.path.join(self.cwd, "api_responses"))
1152
1152
+
1153
1153
+
# This should raise an UnsupportedParamsError
1154
1154
+
with self.assertRaises(z.ze.UnsupportedParamsError):
1155
1155
+
upload.upload()
1156
1156
+
1157
1157
+
# Clean up
1158
1158
+
os.remove(temp_file_path)
1159
1159
+
862
1160
def tearDown(self):
863
1161
"""Tear stuff down"""
864
1162
HTTPretty.disable()