directly integrate login assertion in requests #27
@ -12,6 +12,8 @@ from delta_barth.errors import STATUS_HANDLER
|
|||||||
from delta_barth.types import DelBarApiError, ExportResponse, ResponseType, Status
|
from delta_barth.types import DelBarApiError, ExportResponse, ResponseType, Status
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from requests import Response
|
||||||
|
|
||||||
from delta_barth.session import Session
|
from delta_barth.session import Session
|
||||||
|
|
||||||
|
|
||||||
@ -57,10 +59,10 @@ def get_sales_prognosis_data(
|
|||||||
start_date: Datetime | None = None,
|
start_date: Datetime | None = None,
|
||||||
) -> tuple[SalesPrognosisResponse, Status]:
|
) -> tuple[SalesPrognosisResponse, Status]:
|
||||||
# TODO check elimination of assertion for login, #25
|
# TODO check elimination of assertion for login, #25
|
||||||
_, status = session.assert_login()
|
# _, status = session.assert_login()
|
||||||
if status != STATUS_HANDLER.SUCCESS:
|
# if status != STATUS_HANDLER.SUCCESS:
|
||||||
response = SalesPrognosisResponse(daten=tuple())
|
# response = SalesPrognosisResponse(daten=tuple())
|
||||||
return response, status
|
# return response, status
|
||||||
|
|
||||||
ROUTE: Final[str] = "verkauf/umsatzprognosedaten"
|
ROUTE: Final[str] = "verkauf/umsatzprognosedaten"
|
||||||
URL: Final = combine_route(session.base_url, ROUTE)
|
URL: Final = combine_route(session.base_url, ROUTE)
|
||||||
@ -70,6 +72,7 @@ def get_sales_prognosis_data(
|
|||||||
BuchungsDatum=start_date,
|
BuchungsDatum=start_date,
|
||||||
)
|
)
|
||||||
empty_response = SalesPrognosisResponse(daten=tuple())
|
empty_response = SalesPrognosisResponse(daten=tuple())
|
||||||
|
resp: Response | None = None
|
||||||
try:
|
try:
|
||||||
for attempt in range(1, (MAX_LOGIN_RETRIES + 1)):
|
for attempt in range(1, (MAX_LOGIN_RETRIES + 1)):
|
||||||
resp = requests.get(
|
resp = requests.get(
|
||||||
@ -82,7 +85,6 @@ def get_sales_prognosis_data(
|
|||||||
_, status = session.relogin()
|
_, status = session.relogin()
|
||||||
if status != STATUS_HANDLER.SUCCESS and attempt == MAX_LOGIN_RETRIES:
|
if status != STATUS_HANDLER.SUCCESS and attempt == MAX_LOGIN_RETRIES:
|
||||||
return empty_response, status
|
return empty_response, status
|
||||||
|
|
||||||
except requests.exceptions.Timeout:
|
except requests.exceptions.Timeout:
|
||||||
return empty_response, STATUS_HANDLER.pipe_states.CONNECTION_TIMEOUT
|
return empty_response, STATUS_HANDLER.pipe_states.CONNECTION_TIMEOUT
|
||||||
except requests.exceptions.RequestException:
|
except requests.exceptions.RequestException:
|
||||||
@ -90,6 +92,7 @@ def get_sales_prognosis_data(
|
|||||||
|
|
||||||
response: SalesPrognosisResponse
|
response: SalesPrognosisResponse
|
||||||
status: Status
|
status: Status
|
||||||
|
assert resp is not None, "tried to use not defined response"
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
response = SalesPrognosisResponse(**resp.json())
|
response = SalesPrognosisResponse(**resp.json())
|
||||||
status = STATUS_HANDLER.SUCCESS
|
status = STATUS_HANDLER.SUCCESS
|
||||||
|
|||||||
@ -300,45 +300,3 @@ class Session:
|
|||||||
|
|
||||||
self._remove_session_token()
|
self._remove_session_token()
|
||||||
return self.login()
|
return self.login()
|
||||||
|
|
||||||
def assert_login(
|
|
||||||
self,
|
|
||||||
) -> tuple[LoginResponse, Status]:
|
|
||||||
# check if login token is still valid
|
|
||||||
# re-login if necessary
|
|
||||||
if self.session_token is None:
|
|
||||||
return self.login()
|
|
||||||
|
|
||||||
# use known endpoint which requires a valid token in its header
|
|
||||||
# evaluate the response to decide if:
|
|
||||||
# current token is still valid, token is not valid, other errors occurred
|
|
||||||
ROUTE: Final[str] = "verkauf/umsatzprognosedaten"
|
|
||||||
URL: Final = combine_route(self.base_url, ROUTE)
|
|
||||||
params: dict[str, int] = {"FirmaId": 999999}
|
|
||||||
empty_response = LoginResponse(token="")
|
|
||||||
try:
|
|
||||||
resp = requests.get(
|
|
||||||
URL,
|
|
||||||
params=params,
|
|
||||||
headers=self.headers, # type: ignore
|
|
||||||
timeout=API_CON_TIMEOUT,
|
|
||||||
)
|
|
||||||
except requests.exceptions.Timeout: # pragma: no cover
|
|
||||||
return empty_response, STATUS_HANDLER.pipe_states.CONNECTION_TIMEOUT
|
|
||||||
except requests.exceptions.RequestException: # pragma: no cover
|
|
||||||
return empty_response, STATUS_HANDLER.pipe_states.CONNECTION_ERROR
|
|
||||||
|
|
||||||
response: LoginResponse
|
|
||||||
status: Status
|
|
||||||
if resp.status_code == 200:
|
|
||||||
response = LoginResponse(token=self.session_token)
|
|
||||||
status = STATUS_HANDLER.SUCCESS
|
|
||||||
elif resp.status_code == 401:
|
|
||||||
self._remove_session_token()
|
|
||||||
response, status = self.login()
|
|
||||||
else:
|
|
||||||
response = empty_response
|
|
||||||
err = DelBarApiError(status_code=resp.status_code, **resp.json())
|
|
||||||
status = STATUS_HANDLER.api_error(err)
|
|
||||||
|
|
||||||
return response, status
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import pytest
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from delta_barth.api import requests as requests_
|
from delta_barth.api import requests as requests_
|
||||||
from delta_barth.api.common import LoginResponse
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
@pytest.mark.api_con_required
|
||||||
@ -54,12 +53,11 @@ def test_get_sales_prognosis_data_Success(session):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
@pytest.mark.api_con_required
|
||||||
def test_get_sales_prognosis_data_FailLogin(session, mock_get):
|
def test_get_sales_prognosis_data_NoAuth(session, mock_get):
|
||||||
session.login()
|
code = 401
|
||||||
code = 500
|
|
||||||
json = {
|
json = {
|
||||||
"message": "ServerError",
|
"message": "ServerError",
|
||||||
"code": "TestExternalServerError",
|
"code": "TestFailAuth",
|
||||||
"hints": "TestCase",
|
"hints": "TestCase",
|
||||||
}
|
}
|
||||||
mock_get.return_value.status_code = code
|
mock_get.return_value.status_code = code
|
||||||
@ -76,6 +74,36 @@ def test_get_sales_prognosis_data_FailLogin(session, mock_get):
|
|||||||
assert status.api_server_error.hints == json["hints"]
|
assert status.api_server_error.hints == json["hints"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_sales_prognosis_data_FailLogin(session, mock_get, mock_put):
|
||||||
|
code = 401
|
||||||
|
json = {
|
||||||
|
"message": "ServerError",
|
||||||
|
"code": "TestFailAuth",
|
||||||
|
"hints": "TestCase",
|
||||||
|
}
|
||||||
|
mock_get.return_value.status_code = code
|
||||||
|
mock_get.return_value.json.return_value = json
|
||||||
|
|
||||||
|
code_put = 500
|
||||||
|
json_put = {
|
||||||
|
"message": "ServerError",
|
||||||
|
"code": "TestUnknownError",
|
||||||
|
"hints": "TestCase",
|
||||||
|
}
|
||||||
|
mock_put.return_value.status_code = code_put
|
||||||
|
mock_put.return_value.json.return_value = json_put
|
||||||
|
|
||||||
|
resp, status = requests_.get_sales_prognosis_data(session, None, None)
|
||||||
|
assert resp is not None
|
||||||
|
assert len(resp.daten) == 0
|
||||||
|
assert status.code == 400
|
||||||
|
assert status.api_server_error is not None
|
||||||
|
assert status.api_server_error.status_code == code_put
|
||||||
|
assert status.api_server_error.message == json_put["message"]
|
||||||
|
assert status.api_server_error.code == json_put["code"]
|
||||||
|
assert status.api_server_error.hints == json_put["hints"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
@pytest.mark.api_con_required
|
||||||
def test_get_sales_prognosis_data_FailApiServer(session, mock_get):
|
def test_get_sales_prognosis_data_FailApiServer(session, mock_get):
|
||||||
code = 405
|
code = 405
|
||||||
@ -101,11 +129,6 @@ def test_get_sales_prognosis_data_FailApiServer(session, mock_get):
|
|||||||
def test_get_sales_prognosis_data_FailGetTimeout(session, mock_get):
|
def test_get_sales_prognosis_data_FailGetTimeout(session, mock_get):
|
||||||
mock_get.side_effect = requests.exceptions.Timeout("Test timeout")
|
mock_get.side_effect = requests.exceptions.Timeout("Test timeout")
|
||||||
|
|
||||||
def assert_login():
|
|
||||||
return LoginResponse(token=""), requests_.STATUS_HANDLER.SUCCESS
|
|
||||||
|
|
||||||
session.assert_login = assert_login
|
|
||||||
|
|
||||||
resp, status = requests_.get_sales_prognosis_data(session, None, None)
|
resp, status = requests_.get_sales_prognosis_data(session, None, None)
|
||||||
assert resp is not None
|
assert resp is not None
|
||||||
assert len(resp.daten) == 0
|
assert len(resp.daten) == 0
|
||||||
@ -115,11 +138,6 @@ def test_get_sales_prognosis_data_FailGetTimeout(session, mock_get):
|
|||||||
def test_get_sales_prognosis_data_FailGetRequestException(session, mock_get):
|
def test_get_sales_prognosis_data_FailGetRequestException(session, mock_get):
|
||||||
mock_get.side_effect = requests.exceptions.RequestException("Test not timeout")
|
mock_get.side_effect = requests.exceptions.RequestException("Test not timeout")
|
||||||
|
|
||||||
def assert_login():
|
|
||||||
return LoginResponse(token=""), requests_.STATUS_HANDLER.SUCCESS
|
|
||||||
|
|
||||||
session.assert_login = assert_login
|
|
||||||
|
|
||||||
resp, status = requests_.get_sales_prognosis_data(session, None, None)
|
resp, status = requests_.get_sales_prognosis_data(session, None, None)
|
||||||
assert resp is not None
|
assert resp is not None
|
||||||
assert len(resp.daten) == 0
|
assert len(resp.daten) == 0
|
||||||
|
|||||||
@ -314,11 +314,11 @@ def test_login_logout_FailApiServer(session, mock_put):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
@pytest.mark.api_con_required
|
||||||
def test_assert_login_SuccessLoggedOut(session):
|
def test_relogin_SuccessLoggedOut(session):
|
||||||
assert session.session_token is None
|
assert session.session_token is None
|
||||||
assert session._creds is not None
|
assert session._creds is not None
|
||||||
# test logged out state
|
# test logged out state
|
||||||
resp, status = session.assert_login()
|
resp, status = session.relogin()
|
||||||
assert resp is not None
|
assert resp is not None
|
||||||
assert status.code == 0
|
assert status.code == 0
|
||||||
assert session.session_token is not None
|
assert session.session_token is not None
|
||||||
@ -327,74 +327,17 @@ def test_assert_login_SuccessLoggedOut(session):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
@pytest.mark.api_con_required
|
||||||
def test_assert_login_SuccessStillLoggedIn(session):
|
def test_relogin_SuccessStillLoggedIn(session):
|
||||||
assert session.session_token is None
|
assert session.session_token is None
|
||||||
assert session._creds is not None
|
assert session._creds is not None
|
||||||
resp, status = session.login()
|
resp, status = session.login()
|
||||||
resp, status = session.assert_login()
|
old_token = session.session_token
|
||||||
|
assert old_token is not None
|
||||||
|
resp, status = session.relogin()
|
||||||
assert resp is not None
|
assert resp is not None
|
||||||
assert status.code == 0
|
assert status.code == 0
|
||||||
assert session.session_token is not None
|
assert session.session_token is not None
|
||||||
|
assert session.session_token != old_token
|
||||||
|
|
||||||
resp, status = session.logout()
|
resp, status = session.logout()
|
||||||
assert status.code == 0
|
assert status.code == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
|
||||||
def test_assert_login_ReloginNoValidAuth(session, mock_get):
|
|
||||||
code = 401
|
|
||||||
json = {
|
|
||||||
"message": "AuthentificationError",
|
|
||||||
"code": "TestAssertLoginAfter",
|
|
||||||
"hints": "TestCase",
|
|
||||||
}
|
|
||||||
mock_get.return_value.status_code = code
|
|
||||||
mock_get.return_value.json.return_value = json
|
|
||||||
|
|
||||||
resp, status = session.login()
|
|
||||||
|
|
||||||
resp, status = session.assert_login()
|
|
||||||
assert resp is not None
|
|
||||||
assert status.code == 0
|
|
||||||
assert session.session_token is not None
|
|
||||||
resp, status = session.logout()
|
|
||||||
assert status.code == 0
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
|
||||||
def test_assert_login_ReloginWrongToken(session):
|
|
||||||
# triggers code 401
|
|
||||||
assert session.session_token is None
|
|
||||||
assert session._creds is not None
|
|
||||||
_, status = session.login()
|
|
||||||
assert status.code == 0
|
|
||||||
session._session_token = "WRONGTOKEN"
|
|
||||||
resp, status = session.assert_login()
|
|
||||||
assert resp is not None
|
|
||||||
assert status.code == 0
|
|
||||||
assert session.session_token is not None
|
|
||||||
resp, status = session.logout()
|
|
||||||
assert status.code == 0
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.api_con_required
|
|
||||||
def test_assert_login_FailApiServer(session, mock_get):
|
|
||||||
code = 500
|
|
||||||
json = {
|
|
||||||
"message": "ServerError",
|
|
||||||
"code": "TestExternalServerError",
|
|
||||||
"hints": "TestCase",
|
|
||||||
}
|
|
||||||
mock_get.return_value.status_code = code
|
|
||||||
mock_get.return_value.json.return_value = json
|
|
||||||
|
|
||||||
resp, status = session.login()
|
|
||||||
|
|
||||||
resp, status = session.assert_login()
|
|
||||||
assert resp is not None
|
|
||||||
assert not resp.token
|
|
||||||
assert status.code == 400
|
|
||||||
assert status.api_server_error is not None
|
|
||||||
assert status.api_server_error.status_code == code
|
|
||||||
assert status.api_server_error.message == json["message"]
|
|
||||||
assert status.api_server_error.code == json["code"]
|
|
||||||
assert status.api_server_error.hints == json["hints"]
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user