Skip to content

Commit

Permalink
fix: prevent error when addons is null (#2722)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewelwell committed Sep 1, 2023
1 parent 45844d2 commit 003d782
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 11 deletions.
5 changes: 2 additions & 3 deletions api/organisations/chargebee/chargebee.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ def _convert_chargebee_subscription_to_dictionary(
) -> dict:
chargebee_subscription_dict = vars(chargebee_subscription)
# convert the addons into a list of dictionaries since vars don't do it recursively
chargebee_subscription_dict["addons"] = [
vars(addon) for addon in chargebee_subscription.addons
]
addons = chargebee_subscription.addons or []
chargebee_subscription_dict["addons"] = [vars(addon) for addon in addons]

return chargebee_subscription_dict
63 changes: 59 additions & 4 deletions api/tests/unit/organisations/chargebee/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import typing

import pytest
from pytest_mock import MockerFixture
from tests.unit.organisations.chargebee.test_unit_chargebee_chargebee import (
Expand All @@ -7,6 +9,14 @@

from organisations.chargebee.metadata import ChargebeeObjMetadata

ChargebeeCacheMocker = typing.Callable[
[
typing.Optional[dict[str, ChargebeeObjMetadata]],
typing.Optional[dict[str, ChargebeeObjMetadata]],
],
None,
]


@pytest.fixture
def chargebee_object_metadata():
Expand All @@ -17,6 +27,36 @@ def chargebee_object_metadata():
def mock_subscription_response(
mocker: MockerFixture,
chargebee_object_metadata: ChargebeeObjMetadata,
chargebee_cache_mocker: ChargebeeCacheMocker,
) -> MockChargeBeeSubscriptionResponse:
# Given
plan_id = "plan-id"
subscription_id = "subscription-id"
customer_email = "test@example.com"

# Let's create a (mocked) subscription object
mock_subscription_response = MockChargeBeeSubscriptionResponse(
subscription_id=subscription_id,
plan_id=plan_id,
customer_email=customer_email,
addons=None,
)
mocked_chargebee = mocker.patch("organisations.chargebee.chargebee.chargebee")

# tie that subscription object to the mocked chargebee object
mocked_chargebee.Subscription.retrieve.return_value = mock_subscription_response

# now, let's mock chargebee cache object
chargebee_cache_mocker({plan_id: chargebee_object_metadata}, None)

return mock_subscription_response


@pytest.fixture
def mock_subscription_response_with_addons(
mocker: MockerFixture,
chargebee_object_metadata: ChargebeeObjMetadata,
chargebee_cache_mocker: ChargebeeCacheMocker,
) -> MockChargeBeeSubscriptionResponse:
# Given
plan_id = "plan-id"
Expand All @@ -37,10 +77,25 @@ def mock_subscription_response(
mocked_chargebee.Subscription.retrieve.return_value = mock_subscription_response

# now, let's mock chargebee cache object
mocked_chargebee_cache = mocker.patch(
"organisations.chargebee.chargebee.ChargebeeCache", autospec=True
chargebee_cache_mocker(
{plan_id: chargebee_object_metadata}, {addon_id: chargebee_object_metadata}
)
mocked_chargebee_cache.return_value.plans = {plan_id: chargebee_object_metadata}
mocked_chargebee_cache.return_value.addons = {addon_id: chargebee_object_metadata}

return mock_subscription_response


@pytest.fixture()
def chargebee_cache_mocker(
mocker: MockerFixture,
) -> ChargebeeCacheMocker:
def mock_chargebee_cache(
plans_data: dict[str, ChargebeeObjMetadata] = None,
addons_data: dict[str, ChargebeeObjMetadata] = None,
) -> None:
mocked_chargebee_cache = mocker.patch(
"organisations.chargebee.chargebee.ChargebeeCache", autospec=True
)
mocked_chargebee_cache.return_value.plans = plans_data or {}
mocked_chargebee_cache.return_value.addons = addons_data or {}

return mock_chargebee_cache
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ def test_get_hosted_page_url_for_subscription_upgrade(self):


def test_extract_subscription_metadata(
mock_subscription_response, chargebee_object_metadata: ChargebeeObjMetadata
mock_subscription_response_with_addons: MockChargeBeeSubscriptionResponse,
chargebee_object_metadata: ChargebeeObjMetadata,
):
# Given
status = "status"
Expand Down Expand Up @@ -300,7 +301,8 @@ def test_extract_subscription_metadata(


def test_extract_subscription_metadata_when_addon_list_is_empty(
mock_subscription_response, chargebee_object_metadata: ChargebeeObjMetadata
mock_subscription_response_with_addons: MockChargeBeeSubscriptionResponse,
chargebee_object_metadata: ChargebeeObjMetadata,
):
# Given
status = "status"
Expand Down Expand Up @@ -329,16 +331,19 @@ def test_extract_subscription_metadata_when_addon_list_is_empty(


def test_get_subscription_metadata_from_id(
mock_subscription_response, chargebee_object_metadata: ChargebeeObjMetadata
mock_subscription_response_with_addons: MockChargeBeeSubscriptionResponse,
chargebee_object_metadata: ChargebeeObjMetadata,
):
# Given
customer_email = "test@example.com"
subscription_id = mock_subscription_response.subscription.id
subscription_id = mock_subscription_response_with_addons.subscription.id

# When
subscription_metadata = get_subscription_metadata_from_id(subscription_id)

# Then
# Values here are multiplied by 2 because the both the plan and the addon included in
# the mock_subscription_response_with_addons fixture contain the same values.
assert subscription_metadata.seats == chargebee_object_metadata.seats * 2
assert subscription_metadata.api_calls == chargebee_object_metadata.api_calls * 2
assert subscription_metadata.projects == chargebee_object_metadata.projects * 2
Expand Down Expand Up @@ -425,6 +430,23 @@ def test_get_subscription_metadata_from_id_returns_none_for_invalid_subscription
assert subscription_metadata is None


def test_get_subscription_metadata_from_id_returns_valid_metadata_if_addons_is_none(
mock_subscription_response: MockChargeBeeSubscriptionResponse,
chargebee_object_metadata: ChargebeeObjMetadata,
) -> None:
# Given
mock_subscription_response.addons = None
subscription_id = mock_subscription_response.subscription.id

# When
subscription_metadata = get_subscription_metadata_from_id(subscription_id)

# Then
assert subscription_metadata.seats == chargebee_object_metadata.seats
assert subscription_metadata.api_calls == chargebee_object_metadata.api_calls
assert subscription_metadata.projects == chargebee_object_metadata.projects


def test_add_single_seat_with_existing_addon(mocker):
# Given
plan_id = "plan-id"
Expand Down

1 comment on commit 003d782

@vercel
Copy link

@vercel vercel bot commented on 003d782 Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./docs

docs-git-main-flagsmith.vercel.app
docs-flagsmith.vercel.app
docs.flagsmith.com
docs.bullet-train.io

Please sign in to comment.