fix(qbittorrent): stop mislabeling gateway/URL errors as auth failures
The credential tester always reported "Authentication failed — qBittorrent rejected the credentials" for the qBittorrent service, even when credentials were correct. test_connection classified any RuntimeError whose message contained "login failed" as an auth failure — and the gateway-timeout error (502/503/504 from the reverse proxy) and the wrong-URL diagnostic both started with "qBittorrent login failed:", so a proxy timeout was reported as a credentials rejection. That sent users down the wrong path (re-entering correct passwords to fix a 504). - QbittorrentClient._login: gateway and URL/routing errors no longer contain "login failed"; only a genuine "Fails." body carries the "invalid username or password" signal. - integrations/qbittorrent.test_connection: key the auth message off "invalid username or password" specifically; all other login errors flow through translate_connection_error so the real reason (proxy timeout, wrong URL, empty body) is surfaced. After this, a failing test reports the actual cause (e.g. "qBittorrent is unreachable: reverse proxy returned HTTP 504 ...") instead of accusing the credentials. New regression test asserts a gateway error is NOT reported as "Authentication failed". 386/386 backend tests pass; ruff clean.
This commit is contained in:
@@ -76,12 +76,28 @@ class TestQbittorrentTestConnection:
|
||||
|
||||
def test_login_failed_translates_to_auth_message(self) -> None:
|
||||
mock_client = MagicMock()
|
||||
mock_client.maindata.side_effect = RuntimeError("qBittorrent login failed: Fails.")
|
||||
# Mirrors the real _login auth-failure message for a "Fails." body.
|
||||
mock_client.maindata.side_effect = RuntimeError(
|
||||
"qBittorrent login failed (HTTP 200): invalid username or password"
|
||||
)
|
||||
with patch("media_library_viewer_api.integrations.qbittorrent.QbittorrentClient", return_value=mock_client):
|
||||
result = qbit_test({"base_url": "http://qb:8080"}, {"username": "u", "password": "p"}, MagicMock())
|
||||
assert result.ok is False
|
||||
assert "Authentication failed" in result.detail
|
||||
|
||||
def test_gateway_error_does_not_masquerade_as_auth_failure(self) -> None:
|
||||
mock_client = MagicMock()
|
||||
# A 504 from the reverse proxy must NOT be reported as "Authentication
|
||||
# failed" — that misled users into re-entering correct credentials.
|
||||
mock_client.maindata.side_effect = RuntimeError(
|
||||
"qBittorrent is unreachable: reverse proxy returned HTTP 504 for http://qb:8080/api/v2/auth/login."
|
||||
)
|
||||
with patch("media_library_viewer_api.integrations.qbittorrent.QbittorrentClient", return_value=mock_client):
|
||||
result = qbit_test({"base_url": "http://qb:8080"}, {"username": "u", "password": "p"}, MagicMock())
|
||||
assert result.ok is False
|
||||
assert "Authentication failed" not in result.detail
|
||||
assert "504" in result.detail
|
||||
|
||||
def test_connection_error_translates(self) -> None:
|
||||
mock_client = MagicMock()
|
||||
mock_client.maindata.side_effect = requests.ConnectionError("Connection refused")
|
||||
|
||||
Reference in New Issue
Block a user