Skip to content

Commit

Permalink
add test_client testcases
Browse files Browse the repository at this point in the history
Signed-off-by: flashdagger <flashdagger@googlemail.com>
  • Loading branch information
flashdagger committed Oct 22, 2023
1 parent 4463af9 commit 9ecf2ec
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 13 deletions.
97 changes: 94 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,99 @@ def test_server_version(rclient):
assert version[:2] == ["6", "1"]


def test_raise_if_user_cannot_be_found(rclient):
with pytest.raises(APIException, match="Couldn't find User") as exc:
rclient.users(100).reload()
def test_raise_api_exception(rclient):
with pytest.raises(APIException, match="No route matches") as exc:
rclient.get()

assert exc.value.response.status_code == 404


def test_params_bool_is_lowercase(rclient):
from urllib.parse import parse_qs, urlsplit

response = rclient.response(
"GET", rclient.url, params={"is_true": True, "is_false": False}
)
mapping = parse_qs(urlsplit(response.url).query)
assert mapping["is_true"] == ["true"]
assert mapping["is_false"] == ["false"]


def test_logging(caplog, rclient):
import logging

with caplog.at_level(logging.DEBUG, logger="zammadoo"):
rclient.response("GET", rclient.url, params={"foo": "bar"})
rclient.response("GET", rclient.url, json={"foo": "bar"})
rclient.response("GET", rclient.url, stream=True)

assert caplog.record_tuples == [
("zammadoo", logging.INFO, "HTTP:GET https://localhost/api/v1?foo=bar"),
(
"zammadoo",
logging.DEBUG,
"HTTP:GET https://localhost/api/v1 json={'foo': 'bar'}",
),
(
"zammadoo",
logging.DEBUG,
"HTTP:GET https://localhost/api/v1 [Content-Type: application/json; charset=utf-8]",
),
]


def test_raises_http_exception(rclient):
from requests import HTTPError

from zammadoo.client import raise_or_return_json

response = rclient.response("GET", "https://httpbin.org/status/404", verify=False)
with pytest.raises(HTTPError):
raise_or_return_json(response)


def test_return_text_if_not_json(rclient):
from zammadoo.client import raise_or_return_json

response = rclient.response("GET", "https://httpbin.org/status/200", verify=False)
assert raise_or_return_json(response) == ""


def test_http_auth(recorded_session):
from zammadoo import Client

client = Client("https://httpbin.org", http_auth=("myuser", "mysecret"))
answer = client.request("GET", "basic-auth", "myuser", "mysecret", verify=False)
assert answer == {"authenticated": True, "user": "myuser"}

answer = client.request(
"GET", "hidden-basic-auth", "myuser", "mysecret", verify=False
)
assert answer == {"authenticated": True, "user": "myuser"}


def test_oauth2_token(recorded_session):
from zammadoo import Client

client = Client("https://httpbin.org", oauth2_token="AbCdEf123456")
answer = client.request("GET", "bearer", verify=False)
assert answer == {"authenticated": True, "token": "AbCdEf123456"}


def test_raise_if_not_authentication_provided():
from zammadoo import Client

with pytest.raises(TypeError, match="needs an authentication parameter"):
Client("https://localhost")


def test_impersonation_of(rclient):
users = rclient.users

with rclient.impersonation_of(1):
assert users.me().id == 1

with rclient.impersonation_of(2):
assert users.me().id == 2

assert users.me().id == 1
12 changes: 12 additions & 0 deletions tests/test_client/test_http_auth.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{"method": "GET", "headers": {"Content-Type": "application/json", "Content-Length": "49"}, "url": "https://httpbin.org/basic-auth/myuser/mysecret", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 49}
{
"authenticated": true,
"user": "myuser"
}

{"method": "GET", "headers": {"Content-Type": "application/json", "Content-Length": "49"}, "url": "https://httpbin.org/hidden-basic-auth/myuser/mysecret", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 49}
{
"authenticated": true,
"user": "myuser"
}

6 changes: 6 additions & 0 deletions tests/test_client/test_impersonation_of.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8", "Content-Length": "626"}, "url": "https://localhost/api/v1/users/me", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 626}
{"id":1,"organization_id":null,"login":"-","firstname":"-","lastname":"","email":"","image":null,"image_source":null,"vip":false,"verified":false,"active":false,"last_login":null,"source":null,"login_failed":0,"out_of_office":false,"out_of_office_start_at":null,"out_of_office_end_at":null,"out_of_office_replacement_id":null,"preferences":{"tickets_closed":0,"tickets_open":0},"updated_by_id":3,"created_by_id":1,"created_at":"2023-09-22T20:15:52.579Z","updated_at":"2023-10-14T01:31:18.352Z","role_ids":[3],"two_factor_preference_ids":[],"organization_ids":[],"authorization_ids":[],"overview_sorting_ids":[],"group_ids":{}}
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8", "Content-Length": "677"}, "url": "https://localhost/api/v1/users/me", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 677}
{"id":2,"organization_id":1,"login":"nicole.braun@zammad.org","firstname":"Nicole","lastname":"Braun","email":"nicole.braun@zammad.org","image":null,"image_source":null,"vip":false,"verified":false,"active":true,"last_login":null,"source":null,"login_failed":0,"out_of_office":false,"out_of_office_start_at":null,"out_of_office_end_at":null,"out_of_office_replacement_id":null,"preferences":{"tickets_closed":1,"tickets_open":3},"updated_by_id":2,"created_by_id":1,"created_at":"2023-09-22T20:15:54.486Z","updated_at":"2023-10-04T18:43:23.975Z","role_ids":[3],"two_factor_preference_ids":[],"organization_ids":[],"authorization_ids":[],"overview_sorting_ids":[],"group_ids":{}}
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8", "Content-Length": "626"}, "url": "https://localhost/api/v1/users/me", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 626}
{"id":1,"organization_id":null,"login":"-","firstname":"-","lastname":"","email":"","image":null,"image_source":null,"vip":false,"verified":false,"active":false,"last_login":null,"source":null,"login_failed":0,"out_of_office":false,"out_of_office_start_at":null,"out_of_office_end_at":null,"out_of_office_replacement_id":null,"preferences":{"tickets_closed":0,"tickets_open":0},"updated_by_id":3,"created_by_id":1,"created_at":"2023-09-22T20:15:52.579Z","updated_at":"2023-10-14T01:31:18.352Z","role_ids":[3],"two_factor_preference_ids":[],"organization_ids":[],"authorization_ids":[],"overview_sorting_ids":[],"group_ids":{}}
6 changes: 6 additions & 0 deletions tests/test_client/test_logging.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8"}, "url": "https://localhost/api/v1?foo=bar", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"No route matches [GET] /api/v1","error_human":"No route matches [GET] /api/v1"}
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8"}, "url": "https://localhost/api/v1", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"No route matches [GET] /api/v1","error_human":"No route matches [GET] /api/v1"}
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8"}, "url": "https://localhost/api/v1", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"No route matches [GET] /api/v1","error_human":"No route matches [GET] /api/v1"}
6 changes: 6 additions & 0 deletions tests/test_client/test_oauth2_token.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"method": "GET", "headers": {"Content-Type": "application/json", "Content-Length": "56"}, "url": "https://httpbin.org/bearer", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 56}
{
"authenticated": true,
"token": "AbCdEf123456"
}

2 changes: 2 additions & 0 deletions tests/test_client/test_params_bool_is_lowercase.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8"}, "url": "https://localhost/api/v1?is_true=true&is_false=false", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"No route matches [GET] /api/v1","error_human":"No route matches [GET] /api/v1"}
2 changes: 2 additions & 0 deletions tests/test_client/test_raise_api_exception.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8"}, "url": "https://localhost/api/v1", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"No route matches [GET] /api/v1","error_human":"No route matches [GET] /api/v1"}
4 changes: 2 additions & 2 deletions tests/test_client/test_raise_if_user_cannot_be_found.log
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{"method": "GET", "url": "https://localhost/api/v1/users/100", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 93}
{"error":"Couldn't find User with 'id'=100","error_human":"Couldn't find User with 'id'=100"}
{"method": "GET", "url": "https://localhost/api/v1/users/0", "status_code": 404, "encoding": "utf-8", "reason": "Not Found", "content_size": 89}
{"error":"Couldn't find User with 'id'=0","error_human":"Couldn't find User with 'id'=0"}
2 changes: 2 additions & 0 deletions tests/test_client/test_raises_http_exception.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"method": "GET", "headers": {"Content-Type": "text/html; charset=utf-8", "Content-Length": "0"}, "url": "https://httpbin.org/status/404", "status_code": 404, "encoding": "utf-8", "reason": "NOT FOUND", "content_size": 0}

2 changes: 2 additions & 0 deletions tests/test_client/test_return_text_if_not_json.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"method": "GET", "headers": {"Content-Type": "text/html; charset=utf-8", "Content-Length": "0"}, "url": "https://httpbin.org/status/200", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 0}

2 changes: 1 addition & 1 deletion tests/test_client/test_server_version.log
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{"method": "GET", "url": "https://localhost/api/v1/version", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 45}
{"method": "GET", "headers": {"Content-Type": "application/json; charset=utf-8", "Content-Length": "45"}, "url": "https://localhost/api/v1/version", "status_code": 200, "encoding": "utf-8", "reason": "OK", "content_size": 45}
{"version":"6.1.0-1696849338.59fe2e15.focal"}
5 changes: 3 additions & 2 deletions zammadoo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,9 @@ def response(
if isinstance(value, bool):
params[key] = str(value).lower()

loglevel = LOG.getEffectiveLevel()
response = self.session.request(method, url, params=params, json=json, **kwargs)
if kwargs.get("stream") and LOG.level == logging.DEBUG:
if kwargs.get("stream") and loglevel == logging.DEBUG:
headers = response.headers
mapping = dict.fromkeys(("Content-Length", "Content-Type"))
for key in mapping:
Expand All @@ -256,7 +257,7 @@ def response(
f"{key}: {value}" for key, value in mapping.items() if value
)
LOG.debug("HTTP:%s %s [%s]", method, response.url, info)
elif json and LOG.level == logging.DEBUG:
elif json and loglevel == logging.DEBUG:
LOG.debug("HTTP:%s %s json=%r", method, response.url, json)
else:
LOG.info("HTTP:%s %s", method, response.url)
Expand Down
9 changes: 4 additions & 5 deletions zammadoo/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,11 @@ def cached_info(self, rid: int, refresh=True) -> "JsonDict":
self.client.get, self.endpoint, rid
)

if not refresh:
return cache.setdefault_by_callback(item, callback)
if refresh:
response = cache[item] = callback()
return response

response = callback()
cache[item] = response
return response
return cache.setdefault_by_callback(item, callback)


class CreatableT(ResourcesT[_T_co]):
Expand Down

0 comments on commit 9ecf2ec

Please sign in to comment.