Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transactionUpdate/transactionCreate with empty metadata #15888

Merged
merged 2 commits into from May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -136,8 +136,10 @@ def validate_external_url(cls, external_url: Optional[str], error_code: str):

@classmethod
def validate_metadata_keys( # type: ignore[override]
cls, metadata_list: List[dict], field_name, error_code
cls, metadata_list: Optional[List[dict]], field_name, error_code
):
if not metadata_list:
return
if metadata_contains_empty_key(metadata_list):
raise ValidationError(
{
Expand Down
118 changes: 118 additions & 0 deletions saleor/graphql/payment/tests/mutations/test_transaction_create.py
Expand Up @@ -195,6 +195,63 @@ def test_transaction_create_for_order_by_app(
assert transaction.external_url == external_url


def test_transaction_create_for_order_by_app_metadata_null_value(
order_with_lines, permission_manage_payments, app_api_client
):
# given
name = "Credit Card"
psp_reference = "PSP reference - 123"
available_actions = [
TransactionActionEnum.CHARGE.name,
TransactionActionEnum.CHARGE.name,
]
authorized_value = Decimal("10")
external_url = f"http://{TEST_SERVER_DOMAIN}/external-url"

variables = {
"id": graphene.Node.to_global_id("Order", order_with_lines.pk),
"transaction": {
"name": name,
"pspReference": psp_reference,
"availableActions": available_actions,
"amountAuthorized": {
"amount": authorized_value,
"currency": "USD",
},
"metadata": None,
"privateMetadata": None,
"externalUrl": external_url,
},
}

# when
response = app_api_client.post_graphql(
MUTATION_TRANSACTION_CREATE, variables, permissions=[permission_manage_payments]
)

# then
available_actions = list(set(available_actions))

transaction = order_with_lines.payment_transactions.first()
content = get_graphql_content(response)
data = content["data"]["transactionCreate"]["transaction"]
assert data["actions"] == available_actions
assert data["pspReference"] == psp_reference
assert data["authorizedAmount"]["amount"] == authorized_value
assert data["externalUrl"] == external_url
assert data["createdBy"]["id"] == to_global_id_or_none(app_api_client.app)

assert available_actions == list(map(str.upper, transaction.available_actions))
assert psp_reference == transaction.psp_reference
assert authorized_value == transaction.authorized_value
assert transaction.metadata == {}
assert transaction.private_metadata == {}
assert transaction.app_identifier == app_api_client.app.identifier
assert transaction.app == app_api_client.app
assert transaction.user is None
assert transaction.external_url == external_url


def test_transaction_create_for_order_updates_order_total_authorized_by_app(
order_with_lines, permission_manage_payments, app_api_client
):
Expand Down Expand Up @@ -351,6 +408,67 @@ def test_transaction_create_for_checkout_by_app(
assert transaction.user is None


def test_transaction_create_for_checkout_by_app_metadata_null_value(
checkout_with_items, permission_manage_payments, app_api_client
):
# given
name = "Credit Card"
psp_reference = "PSP reference - 123"
available_actions = [
TransactionActionEnum.CHARGE.name,
TransactionActionEnum.CHARGE.name,
]
authorized_value = Decimal("10")
external_url = f"http://{TEST_SERVER_DOMAIN}/external-url"

variables = {
"id": graphene.Node.to_global_id("Checkout", checkout_with_items.pk),
"transaction": {
"name": name,
"pspReference": psp_reference,
"availableActions": available_actions,
"amountAuthorized": {
"amount": authorized_value,
"currency": "USD",
},
"metadata": None,
"privateMetadata": None,
"externalUrl": external_url,
},
}

# when
response = app_api_client.post_graphql(
MUTATION_TRANSACTION_CREATE, variables, permissions=[permission_manage_payments]
)

# then
checkout_with_items.refresh_from_db()
assert checkout_with_items.charge_status == CheckoutChargeStatus.NONE
assert checkout_with_items.authorize_status == CheckoutAuthorizeStatus.PARTIAL

available_actions = list(set(available_actions))

transaction = checkout_with_items.payment_transactions.first()
content = get_graphql_content(response)
data = content["data"]["transactionCreate"]["transaction"]
assert data["actions"] == available_actions
assert data["pspReference"] == psp_reference
assert data["authorizedAmount"]["amount"] == authorized_value
assert data["externalUrl"] == external_url
assert data["createdBy"]["id"] == to_global_id_or_none(app_api_client.app)

assert available_actions == list(map(str.upper, transaction.available_actions))
assert psp_reference == transaction.psp_reference
assert authorized_value == transaction.authorized_value
assert transaction.metadata == {}
assert transaction.private_metadata == {}
assert transaction.external_url == external_url
assert transaction.app_identifier == app_api_client.app.identifier
assert transaction.app == app_api_client.app
assert transaction.user is None


@pytest.mark.parametrize(
"amount_field_name, amount_db_field",
[
Expand Down
52 changes: 52 additions & 0 deletions saleor/graphql/payment/tests/mutations/test_transaction_update.py
Expand Up @@ -241,6 +241,31 @@ def test_transaction_update_metadata_by_app(
assert transaction_item_created_by_app.metadata == {meta_key: meta_value}


def test_transaction_update_metadata_by_app_null_value(
transaction_item_created_by_app, permission_manage_payments, app_api_client
):
# given
transaction = transaction_item_created_by_app

variables = {
"id": graphene.Node.to_global_id("TransactionItem", transaction.token),
"transaction": {
"metadata": None,
},
}

# when
response = app_api_client.post_graphql(
MUTATION_TRANSACTION_UPDATE, variables, permissions=[permission_manage_payments]
)

# then
transaction.refresh_from_db()
content = get_graphql_content(response)
data = content["data"]["transactionUpdate"]["transaction"]
assert len(data["metadata"]) == 0


def test_transaction_update_metadata_incorrect_key_by_app(
transaction_item_created_by_app, permission_manage_payments, app_api_client
):
Expand Down Expand Up @@ -300,6 +325,33 @@ def test_transaction_update_private_metadata_by_app(
assert transaction_item_created_by_app.private_metadata == {meta_key: meta_value}


def test_transaction_update_private_metadata_by_app_null_value(
transaction_item_created_by_app, permission_manage_payments, app_api_client
):
# given
transaction = transaction_item_created_by_app
transaction.private_metadata = {"key": "value"}
transaction.save(update_fields=["private_metadata"])

variables = {
"id": graphene.Node.to_global_id("TransactionItem", transaction.token),
"transaction": {
"privateMetadata": None,
},
}

# when
response = app_api_client.post_graphql(
MUTATION_TRANSACTION_UPDATE, variables, permissions=[permission_manage_payments]
)

# then
transaction.refresh_from_db()
content = get_graphql_content(response)
data = content["data"]["transactionUpdate"]["transaction"]
assert len(data["privateMetadata"]) == 1


def test_transaction_update_private_metadata_incorrect_key_by_app(
transaction_item_created_by_app, permission_manage_payments, app_api_client
):
Expand Down