budget/tests/mocks/nordigen.py
Luís Murta 1cfc8dbe38
Create EUA and request user access permission
Move the token creation/renewal code into the NordigenClient and remove
external access. The NordigenClient now also takes the DB client in the
constructor.

While creating the unit test, noticed that the nordigen mocks for
downloaded transactions could match the simple transactions mock, thus
helping in the online download command.
Also created the nordigen.NordigenClient mock, with the used methods
mocked and raising a NotImplement when a new endpoint is requested.
2024-01-22 22:01:38 +00:00

147 lines
4.8 KiB
Python

from typing import Any, Dict, List, Optional
import nordigen
from nordigen.types.http_enums import HTTPMethod
from nordigen.types.types import RequisitionDto, TokenType
from pfbudget.extract.nordigen import NordigenCredentials
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
accounts_id = {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created": "2023-04-13T21:45:59.957Z",
"last_accessed": "2023-04-13T21:45:59.957Z",
"iban": "string",
"institution_id": "string",
"status": "DISCOVERED",
"owner_name": "string",
}
# The downloaded transactions match the simple and simple_transformed mocks
accounts_id_transactions = {
"transactions": {
"booked": [
{
"transactionId": "string",
"debtorName": "string",
"debtorAccount": {"iban": "string"},
"transactionAmount": {"currency": "string", "amount": "328.18"},
"bankTransactionCode": "string",
"bookingDate": "2023-01-14",
"valueDate": "2023-01-15",
"remittanceInformationUnstructured": "string",
},
{
"transactionId": "string",
"transactionAmount": {"currency": "string", "amount": "947.26"},
"bankTransactionCode": "string",
"bookingDate": "2023-02-14",
"valueDate": "2023-02-15",
"remittanceInformationUnstructured": "string",
},
],
"pending": [
{
"transactionAmount": {"currency": "string", "amount": "float"},
"valueDate": "2023-04-14",
"remittanceInformationUnstructured": "string",
}
],
}
}
requisitions = {
"count": 123,
"next": "https://ob.nordigen.com/api/v2/requisitions/?limit=100&offset=0",
"previous": "https://ob.nordigen.com/api/v2/requisitions/?limit=100&offset=0",
"results": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created": "2023-04-13T21:43:45.027Z",
"redirect": "string",
"status": "CR",
"institution_id": "string",
"agreement": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"reference": "string",
"accounts": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"],
"user_language": "strin",
"link": "https://ob.nordigen.com/psd2/start/3fa85f64-5717-4562-b3fc-2c963f66afa6/{$INSTITUTION_ID}",
"ssn": "string",
"account_selection": False,
"redirect_immediate": False,
}
],
}
requisitions_id = {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created": "2023-04-13T21:45:12.336Z",
"redirect": "string",
"status": "CR",
"institution_id": "string",
"agreement": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"reference": "string",
"accounts": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"],
"user_language": "strin",
"link": "https://ob.nordigen.com/psd2/start/3fa85f64-5717-4562-b3fc-2c963f66afa6/{$INSTITUTION_ID}",
"ssn": "string",
"account_selection": False,
"redirect_immediate": False,
}
credentials = NordigenCredentials("ID", "KEY")
class MockNordigenClient(nordigen.NordigenClient):
def __init__(
self,
secret_key: str = "ID",
secret_id: str = "KEY",
timeout: int = 10,
base_url: str = "https://ob.nordigen.com/api/v2",
) -> None:
super().__init__(secret_key, secret_id, timeout, base_url)
def generate_token(self) -> TokenType:
return {
"access": "access_token",
"refresh": "refresh_token",
"access_expires": 86400,
"refresh_expires": 2592000,
}
def exchange_token(self, refresh_token: str) -> TokenType:
assert len(refresh_token) > 0, "invalid refresh token"
return {
"access": "access_token",
"refresh": "refresh_token",
"access_expires": 86400,
"refresh_expires": 2592000,
}
def request(
self,
method: HTTPMethod,
endpoint: str,
data: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, Any]] = None,
) -> Any:
if endpoint == "requisitions/" + "requisition_id" + "/":
return requisitions_id
elif endpoint == "accounts/" + id + "/transactions/":
return accounts_id_transactions
else:
raise NotImplementedError(endpoint)
def initialize_session(
self,
redirect_uri: str,
institution_id: str,
reference_id: str,
max_historical_days: int = 90,
access_valid_for_days: int = 90,
access_scope: List[str] | None = None,
) -> RequisitionDto:
return RequisitionDto("http://random", "requisition_id")