Pyzotero: a Python client for the Zotero API pyzotero.readthedocs.io
zotero

Add attachment tests

+196
+196
tests/test_zotero.py
··· 1192 1192 1193 1193 # Clean up 1194 1194 os.remove(temp_file_path) 1195 + 1196 + @httpretty.activate 1197 + def testAttachmentSimple(self): 1198 + """Test attachment_simple method with a single file""" 1199 + zot = z.Zotero("myuserID", "user", "myuserkey") 1200 + 1201 + # Create a temporary test file 1202 + temp_file_path = os.path.join(self.cwd, "api_responses", "test_attachment.txt") 1203 + with open(temp_file_path, "w") as f: 1204 + f.write("Test attachment content") 1205 + 1206 + # Mock the item template response 1207 + HTTPretty.register_uri( 1208 + HTTPretty.GET, 1209 + "https://api.zotero.org/items/new?itemType=attachment&linkMode=imported_file", 1210 + content_type="application/json", 1211 + body=json.dumps({"itemType": "attachment", "linkMode": "imported_file"}) 1212 + ) 1213 + 1214 + # Mock the item creation response 1215 + HTTPretty.register_uri( 1216 + HTTPretty.POST, 1217 + "https://api.zotero.org/users/myuserID/items", 1218 + content_type="application/json", 1219 + body=json.dumps({"success": {"0": "ITEMKEY123"}}) 1220 + ) 1221 + 1222 + # Patch the necessary methods to avoid HTTP calls and file system checks 1223 + with patch.object(z.Zupload, "_verify", return_value=None), \ 1224 + patch.object(z.Zupload, "_get_auth", return_value={ 1225 + "url": "https://uploads.zotero.org/", 1226 + "params": {"key": "abcdef1234567890"}, 1227 + "uploadKey": "upload_key_123" 1228 + }), \ 1229 + patch.object(z.Zupload, "_upload_file", return_value=None): 1230 + 1231 + # Test attachment_simple with a single file 1232 + result = zot.attachment_simple([temp_file_path]) 1233 + 1234 + # Verify the result structure 1235 + self.assertIn("success", result) 1236 + self.assertEqual(len(result["success"]), 1) 1237 + 1238 + # Verify that the correct attachment template was used 1239 + request = httpretty.last_request() 1240 + payload = json.loads(request.body.decode("utf-8")) 1241 + self.assertEqual(payload[0]["title"], "test_attachment.txt") 1242 + self.assertEqual(payload[0]["filename"], temp_file_path) 1243 + 1244 + # Clean up 1245 + os.remove(temp_file_path) 1246 + 1247 + @httpretty.activate 1248 + def testAttachmentSimpleWithParent(self): 1249 + """Test attachment_simple method with a parent ID""" 1250 + zot = z.Zotero("myuserID", "user", "myuserkey") 1251 + 1252 + # Create a temporary test file 1253 + temp_file_path = os.path.join(self.cwd, "api_responses", "test_attachment.txt") 1254 + with open(temp_file_path, "w") as f: 1255 + f.write("Test attachment content") 1256 + 1257 + # Mock the item template response 1258 + HTTPretty.register_uri( 1259 + HTTPretty.GET, 1260 + "https://api.zotero.org/items/new?itemType=attachment&linkMode=imported_file", 1261 + content_type="application/json", 1262 + body=json.dumps({"itemType": "attachment", "linkMode": "imported_file"}) 1263 + ) 1264 + 1265 + # Patch the _attachment method to verify it's called correctly 1266 + with patch.object(z.Zotero, "_attachment") as mock_attachment: 1267 + # Set up the mock return value 1268 + mock_attachment.return_value = {"success": [{"key": "ITEMKEY123"}]} 1269 + 1270 + # Test attachment_simple with a parent ID 1271 + result = zot.attachment_simple([temp_file_path], parentid="PARENT123") 1272 + 1273 + # Verify the result structure matches the mock return value 1274 + self.assertEqual(result, {"success": [{"key": "ITEMKEY123"}]}) 1275 + 1276 + # Check that _attachment was called with the parent ID 1277 + mock_attachment.assert_called_once() 1278 + args = mock_attachment.call_args[0] 1279 + # First argument is the templates list, second is parent ID 1280 + self.assertEqual(len(args), 2) 1281 + self.assertEqual(args[1], "PARENT123") 1282 + 1283 + # Verify the template was correctly set up 1284 + templates = args[0] 1285 + self.assertEqual(len(templates), 1) 1286 + self.assertEqual(templates[0]["title"], "test_attachment.txt") 1287 + self.assertEqual(templates[0]["filename"], temp_file_path) 1288 + 1289 + # Clean up 1290 + os.remove(temp_file_path) 1291 + 1292 + @httpretty.activate 1293 + def testAttachmentBoth(self): 1294 + """Test attachment_both method with custom title and filename""" 1295 + zot = z.Zotero("myuserID", "user", "myuserkey") 1296 + 1297 + # Create a temporary test file 1298 + temp_file_path = os.path.join(self.cwd, "api_responses", "test_attachment.txt") 1299 + with open(temp_file_path, "w") as f: 1300 + f.write("Test attachment content") 1301 + 1302 + # Mock the item template response 1303 + HTTPretty.register_uri( 1304 + HTTPretty.GET, 1305 + "https://api.zotero.org/items/new?itemType=attachment&linkMode=imported_file", 1306 + content_type="application/json", 1307 + body=json.dumps({"itemType": "attachment", "linkMode": "imported_file"}) 1308 + ) 1309 + 1310 + # Mock the item creation response 1311 + HTTPretty.register_uri( 1312 + HTTPretty.POST, 1313 + "https://api.zotero.org/users/myuserID/items", 1314 + content_type="application/json", 1315 + body=json.dumps({"success": {"0": "ITEMKEY123"}}) 1316 + ) 1317 + 1318 + # Patch the necessary methods to avoid HTTP calls and file system checks 1319 + with patch.object(z.Zupload, "_verify", return_value=None), \ 1320 + patch.object(z.Zupload, "_get_auth", return_value={ 1321 + "url": "https://uploads.zotero.org/", 1322 + "params": {"key": "abcdef1234567890"}, 1323 + "uploadKey": "upload_key_123" 1324 + }), \ 1325 + patch.object(z.Zupload, "_upload_file", return_value=None): 1326 + 1327 + # Test attachment_both with custom title 1328 + custom_title = "Custom Attachment Title" 1329 + files = [(custom_title, temp_file_path)] 1330 + result = zot.attachment_both(files) 1331 + 1332 + # Verify the result structure 1333 + self.assertIn("success", result) 1334 + self.assertEqual(len(result["success"]), 1) 1335 + 1336 + # Verify that the correct attachment template was used 1337 + request = httpretty.last_request() 1338 + payload = json.loads(request.body.decode("utf-8")) 1339 + self.assertEqual(payload[0]["title"], custom_title) 1340 + self.assertEqual(payload[0]["filename"], temp_file_path) 1341 + 1342 + # Clean up 1343 + os.remove(temp_file_path) 1344 + 1345 + @httpretty.activate 1346 + def testAttachmentBothWithParent(self): 1347 + """Test attachment_both method with a parent ID""" 1348 + zot = z.Zotero("myuserID", "user", "myuserkey") 1349 + 1350 + # Create a temporary test file 1351 + temp_file_path = os.path.join(self.cwd, "api_responses", "test_attachment.txt") 1352 + with open(temp_file_path, "w") as f: 1353 + f.write("Test attachment content") 1354 + 1355 + # Mock the item template response 1356 + HTTPretty.register_uri( 1357 + HTTPretty.GET, 1358 + "https://api.zotero.org/items/new?itemType=attachment&linkMode=imported_file", 1359 + content_type="application/json", 1360 + body=json.dumps({"itemType": "attachment", "linkMode": "imported_file"}) 1361 + ) 1362 + 1363 + # Patch the _attachment method to verify it's called correctly 1364 + with patch.object(z.Zotero, "_attachment") as mock_attachment: 1365 + # Set up the mock return value 1366 + mock_attachment.return_value = {"success": [{"key": "ITEMKEY123"}]} 1367 + 1368 + # Test attachment_both with a parent ID 1369 + custom_title = "Custom Attachment Title" 1370 + files = [(custom_title, temp_file_path)] 1371 + result = zot.attachment_both(files, parentid="PARENT123") 1372 + 1373 + # Verify the result structure matches the mock return value 1374 + self.assertEqual(result, {"success": [{"key": "ITEMKEY123"}]}) 1375 + 1376 + # Check that _attachment was called with the parent ID 1377 + mock_attachment.assert_called_once() 1378 + args = mock_attachment.call_args[0] 1379 + # First argument is the templates list, second is parent ID 1380 + self.assertEqual(len(args), 2) 1381 + self.assertEqual(args[1], "PARENT123") 1382 + 1383 + # Verify the template was correctly set up 1384 + templates = args[0] 1385 + self.assertEqual(len(templates), 1) 1386 + self.assertEqual(templates[0]["title"], custom_title) 1387 + self.assertEqual(templates[0]["filename"], temp_file_path) 1388 + 1389 + # Clean up 1390 + os.remove(temp_file_path) 1195 1391 1196 1392 def tearDown(self): 1197 1393 """Tear stuff down"""