Skip to content

Commit

Permalink
Feat: GET funding sources linked to concession group (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
thekaveman authored Mar 21, 2024
2 parents 330428c + 14b9e6a commit b6006aa
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 24 deletions.
6 changes: 6 additions & 0 deletions littlepay/api/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ def remove_concession_group(self, group_id) -> bool:
endpoint = self.concession_groups_endpoint(group_id)
return self._delete(endpoint)

def get_concession_group_linked_funding_sources(self, group_id) -> Generator[GroupFundingSourceResponse, None, None]:
"""Yield GroupFundingSourceResponse objects representing linked funding sources from the concession_groups endpoint."""
endpoint = self.concession_group_funding_source_endpoint(group_id)
for item in self._get_list(endpoint):
yield GroupFundingSourceResponse(**item)

def link_concession_group_funding_source(
self, group_id: str, funding_source_id: str, concession_expiry: datetime = None
) -> dict:
Expand Down
100 changes: 76 additions & 24 deletions tests/api/test_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,31 @@


@pytest.fixture
def ListResponse_GroupFundingSources():
def expected_expiry():
return datetime(2024, 3, 19, 22, 0, 0, tzinfo=timezone.utc)


@pytest.fixture
def expected_expiry_str(expected_expiry):
return expected_expiry.strftime("%Y-%m-%dT%H:%M:%SZ")


@pytest.fixture
def ListResponse_GroupFundingSources(expected_expiry_str):
items = [
dict(
id="0",
participant_id="zero_0",
concession_expiry="2024-03-19T20:00:00Z",
concession_created_at="2024-03-19T20:00:00Z",
concession_updated_at="2024-03-19T20:00:00Z",
concession_expiry=expected_expiry_str,
concession_created_at=expected_expiry_str,
concession_updated_at=expected_expiry_str,
),
dict(
id="1",
participant_id="one_1",
concession_expiry="2024-03-19T20:00:00Z",
concession_created_at="2024-03-19T20:00:00Z",
concession_updated_at="2024-03-19T20:00:00Z",
concession_expiry=expected_expiry_str,
concession_created_at=expected_expiry_str,
concession_updated_at=expected_expiry_str,
),
dict(id="2", participant_id="two_2", concession_expiry="", concession_created_at=""),
]
Expand All @@ -39,6 +49,14 @@ def mock_ClientProtocol_get_list_Groups(mocker):
return mocker.patch("littlepay.api.ClientProtocol._get_list", side_effect=lambda *args, **kwargs: (g for g in items))


@pytest.fixture
def mock_ClientProtocol_get_list_FundingSources(mocker, ListResponse_GroupFundingSources):
return mocker.patch(
"littlepay.api.ClientProtocol._get_list",
side_effect=lambda *args, **kwargs: (g for g in ListResponse_GroupFundingSources.list),
)


@pytest.fixture
def mock_ClientProtocol_post_create_concession_group(mocker):
response = dict(id="0", participant_id="zero_0")
Expand Down Expand Up @@ -90,19 +108,18 @@ def test_GroupFundingSourceResponse_empty_dates():
assert response.concession_updated_at is None


def test_GroupFundingSourceResponse_with_dates():
str_date = "2024-03-19T20:00:00Z"
expected_date = datetime(2024, 3, 19, 20, 0, 0, tzinfo=timezone.utc)

response = GroupFundingSourceResponse("id", "participant_id", str_date, str_date, str_date)
def test_GroupFundingSourceResponse_with_dates(expected_expiry, expected_expiry_str):
response = GroupFundingSourceResponse(
"id", "participant_id", expected_expiry_str, expected_expiry_str, expected_expiry_str
)

assert response.id == "id"
assert response.participant_id == "participant_id"
assert response.concession_expiry == expected_date
assert response.concession_expiry == expected_expiry
assert response.concession_expiry.tzinfo == timezone.utc
assert response.concession_created_at == expected_date
assert response.concession_created_at == expected_expiry
assert response.concession_created_at.tzinfo == timezone.utc
assert response.concession_updated_at == expected_date
assert response.concession_updated_at == expected_expiry
assert response.concession_updated_at.tzinfo == timezone.utc


Expand Down Expand Up @@ -174,6 +191,45 @@ def test_GroupsMixin_remove_concession_group(mock_ClientProtocol_delete):
assert result is True


def test_GroupsMixin_get_concession_group_linked_funding_sources(
ListResponse_GroupFundingSources, mock_ClientProtocol_get_list_FundingSources, expected_expiry, expected_expiry_str
):
client = GroupsMixin()

result = client.get_concession_group_linked_funding_sources("group-1234")
assert isinstance(result, Generator)
assert mock_ClientProtocol_get_list_FundingSources.call_count == 0

result_list = list(result)
mock_ClientProtocol_get_list_FundingSources.assert_called_once_with(
client.concession_group_funding_source_endpoint("group-1234")
)

expected_list = ListResponse_GroupFundingSources.list

assert len(result_list) == len(expected_list)
assert all([isinstance(i, GroupFundingSourceResponse) for i in result_list])

for i in range(len(result_list)):
assert result_list[i].id == expected_list[i]["id"]
assert result_list[i].participant_id == expected_list[i]["participant_id"]

if expected_list[i].get("concession_expiry") == expected_expiry_str:
assert result_list[i].concession_expiry == expected_expiry
else:
assert result_list[i].concession_expiry is None

if expected_list[i].get("concession_created_at") == expected_expiry_str:
assert result_list[i].concession_created_at == expected_expiry
else:
assert result_list[i].concession_created_at is None

if expected_list[i].get("concession_updated_at") == expected_expiry_str:
assert result_list[i].concession_updated_at == expected_expiry
else:
assert result_list[i].concession_updated_at is None


def test_GroupsMixin_link_concession_group_funding_source(mock_ClientProtocol_post_link_concession_group_funding_source):
client = GroupsMixin()
result = client.link_concession_group_funding_source("group-1234", "funding-source-1234")
Expand All @@ -185,21 +241,17 @@ def test_GroupsMixin_link_concession_group_funding_source(mock_ClientProtocol_po
assert result == {"status_code": 201}


def test_GroupsMixin_format_concession_expiry_not_datetime():
def test_GroupsMixin_format_concession_expiry_not_datetime(expected_expiry_str):
client = GroupsMixin()
with pytest.raises(TypeError, match="concession_expiry must be a Python datetime instance"):
client._format_concession_expiry("2024-03-18T01:02:03Z")
client._format_concession_expiry(expected_expiry_str)


def test_GroupsMixin_format_concession_expiry_aware_utc():
# construct a UTC datetime and the expected string formatting
concession_expiry = datetime(2024, 3, 18, 1, 2, 3, tzinfo=timezone.utc)
expected_body_expiry = "2024-03-18T01:02:03Z"

def test_GroupsMixin_format_concession_expiry_aware_utc(expected_expiry, expected_expiry_str):
client = GroupsMixin()
result = client._format_concession_expiry(concession_expiry)
result = client._format_concession_expiry(expected_expiry)

assert result == expected_body_expiry
assert result == expected_expiry_str


def test_GroupsMixin_format_concession_expiry_aware_not_utc():
Expand Down

0 comments on commit b6006aa

Please sign in to comment.