@@ -238,3 +238,167 @@ func TestValidTransitions(t *testing.T) {
238238 })
239239 }
240240}
241+
242+ func TestQBittorrentAddTorrentAcceptsJSONSuccess (t * testing.T ) {
243+ mux := http .NewServeMux ()
244+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
245+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
246+ w .WriteHeader (http .StatusOK )
247+ _ , _ = w .Write ([]byte ("Ok." ))
248+ })
249+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
250+ if _ , err := r .Cookie ("QBT_SID" ); err != nil {
251+ t .Fatalf ("expected auth cookie on add request: %v" , err )
252+ }
253+ w .Header ().Set ("Content-Type" , "application/json" )
254+ w .WriteHeader (http .StatusOK )
255+ _ , _ = w .Write ([]byte (`{"added_torrent_ids":["e2f71d638953c009f17594d6982c6de68b06d985"],"failure_count":0,"pending_count":0,"success_count":1}` ))
256+ })
257+
258+ srv := httptest .NewServer (mux )
259+ defer srv .Close ()
260+
261+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
262+
263+ if err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" ); err != nil {
264+ t .Fatalf ("AddTorrent returned error: %v" , err )
265+ }
266+ }
267+
268+ func TestQBittorrentAddTorrentAcceptsOkBody (t * testing.T ) {
269+ mux := http .NewServeMux ()
270+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
271+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
272+ w .WriteHeader (http .StatusOK )
273+ _ , _ = w .Write ([]byte ("Ok." ))
274+ })
275+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
276+ w .WriteHeader (http .StatusOK )
277+ _ , _ = w .Write ([]byte ("Ok." ))
278+ })
279+
280+ srv := httptest .NewServer (mux )
281+ defer srv .Close ()
282+
283+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
284+
285+ if err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" ); err != nil {
286+ t .Fatalf ("AddTorrent returned error: %v" , err )
287+ }
288+ }
289+
290+ func TestQBittorrentAddTorrentRejectsHTTPError (t * testing.T ) {
291+ mux := http .NewServeMux ()
292+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
293+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
294+ w .WriteHeader (http .StatusOK )
295+ _ , _ = w .Write ([]byte ("Ok." ))
296+ })
297+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
298+ w .WriteHeader (http .StatusBadRequest )
299+ _ , _ = w .Write ([]byte ("bad request" ))
300+ })
301+
302+ srv := httptest .NewServer (mux )
303+ defer srv .Close ()
304+
305+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
306+
307+ err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" )
308+ if err == nil {
309+ t .Fatal ("expected error" )
310+ }
311+ if got := err .Error (); ! strings .Contains (got , "add torrent HTTP 400: bad request" ) {
312+ t .Fatalf ("error = %q, want HTTP 400 response" , got )
313+ }
314+ }
315+
316+ func TestQBittorrentAddTorrentRejectsJSONFailure (t * testing.T ) {
317+ mux := http .NewServeMux ()
318+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
319+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
320+ w .WriteHeader (http .StatusOK )
321+ _ , _ = w .Write ([]byte ("Ok." ))
322+ })
323+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
324+ w .Header ().Set ("Content-Type" , "application/json" )
325+ w .WriteHeader (http .StatusOK )
326+ _ , _ = w .Write ([]byte (`{"added_torrent_ids":[],"failure_count":1,"pending_count":0,"success_count":0,"error":"invalid torrent"}` ))
327+ })
328+
329+ srv := httptest .NewServer (mux )
330+ defer srv .Close ()
331+
332+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
333+
334+ err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" )
335+ if err == nil {
336+ t .Fatal ("expected error" )
337+ }
338+ if got := err .Error (); ! strings .Contains (got , "invalid torrent" ) {
339+ t .Fatalf ("error = %q, want invalid torrent" , got )
340+ }
341+ }
342+
343+ func TestQBittorrentAddTorrentAcceptsJSONPending (t * testing.T ) {
344+ mux := http .NewServeMux ()
345+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
346+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
347+ w .WriteHeader (http .StatusOK )
348+ _ , _ = w .Write ([]byte ("Ok." ))
349+ })
350+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
351+ w .Header ().Set ("Content-Type" , "application/json" )
352+ w .WriteHeader (http .StatusOK )
353+ _ , _ = w .Write ([]byte (`{"added_torrent_ids":[],"failure_count":0,"pending_count":1,"success_count":0}` ))
354+ })
355+
356+ srv := httptest .NewServer (mux )
357+ defer srv .Close ()
358+
359+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
360+
361+ if err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" ); err != nil {
362+ t .Fatalf ("AddTorrent returned error: %v" , err )
363+ }
364+ }
365+
366+ func TestQBittorrentAddTorrentRejectsJSONPartialFailure (t * testing.T ) {
367+ mux := http .NewServeMux ()
368+ mux .HandleFunc ("/api/v2/auth/login" , func (w http.ResponseWriter , r * http.Request ) {
369+ http .SetCookie (w , & http.Cookie {Name : "QBT_SID" , Value : "abc123" , Path : "/" })
370+ w .WriteHeader (http .StatusOK )
371+ _ , _ = w .Write ([]byte ("Ok." ))
372+ })
373+ mux .HandleFunc ("/api/v2/torrents/add" , func (w http.ResponseWriter , r * http.Request ) {
374+ w .Header ().Set ("Content-Type" , "application/json" )
375+ w .WriteHeader (http .StatusOK )
376+ _ , _ = w .Write ([]byte (`{"added_torrent_ids":["e2f71d638953c009f17594d6982c6de68b06d985"],"failure_count":1,"pending_count":0,"success_count":1}` ))
377+ })
378+
379+ srv := httptest .NewServer (mux )
380+ defer srv .Close ()
381+
382+ q := newAddTorrentTestQBClient (srv .URL , srv .Client ())
383+
384+ err := q .AddTorrent ("https://example.com/file.torrent" , "Test Book" , "" , "" )
385+ if err == nil {
386+ t .Fatal ("expected error" )
387+ }
388+ if got := err .Error (); ! strings .Contains (got , "success_count=1 failure_count=1 pending_count=0" ) {
389+ t .Fatalf ("error = %q, want partial failure counts" , got )
390+ }
391+ }
392+
393+ func newAddTorrentTestQBClient (serverURL string , client * http.Client ) * QBittorrentClient {
394+ cfg := & config.Config {
395+ QBUrl : serverURL ,
396+ QBUser : "admin" ,
397+ QBPass : "secret" ,
398+ QBSavePath : "/downloads" ,
399+ QBCategory : "librarr" ,
400+ }
401+ q := NewQBittorrentClient (cfg )
402+ q .client = client
403+ return q
404+ }
0 commit comments