indico-plugins/payment_paypal/tests/controllers_test.py
2022-01-05 11:41:25 +01:00

106 lines
4.0 KiB
Python

# This file is part of the Indico plugins.
# Copyright (C) 2002 - 2022 CERN
#
# The Indico plugins are free software; you can redistribute
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from unittest.mock import MagicMock
import pytest
from flask import request
from indico.modules.events.payment.models.transactions import PaymentTransaction
from indico_payment_paypal.controllers import RHPaypalIPN
from indico_payment_paypal.plugin import PaypalPaymentPlugin
@pytest.mark.usefixtures('db', 'request_context')
@pytest.mark.parametrize(('formdata', 'expected'), (
({'business': 'test'}, True),
({'receiver_id': 'test'}, True),
({'receiver_email': 'test'}, True),
({'business': 'foo'}, False),
({}, False)
))
def test_ipn_verify_business(formdata, expected, dummy_event):
rh = RHPaypalIPN()
rh.registration = MagicMock()
rh.registration.registration_form.event = dummy_event
PaypalPaymentPlugin.event_settings.set(dummy_event, 'business', 'TeST')
request.form = formdata
with PaypalPaymentPlugin.instance.plugin_context():
assert rh._verify_business() == expected
@pytest.mark.usefixtures('request_context')
@pytest.mark.parametrize(('amount', 'currency', 'expected'), (
('13.37', 'EUR', True),
('13.37', 'CHF', False),
('10.00', 'CHF', False),
('10.00', 'CHF', False),
))
def test_ipn_verify_amount(mocker, amount, currency, expected):
nai = mocker.patch('indico_payment_paypal.controllers.notify_amount_inconsistency')
rh = RHPaypalIPN()
rh.event = MagicMock(id=1)
rh.registration = MagicMock()
rh.registration.price = 13.37
rh.registration.currency = currency
request.form = {'mc_gross': amount, 'mc_currency': 'EUR'}
with PaypalPaymentPlugin.instance.plugin_context():
assert rh._verify_amount() == expected
assert nai.called == (not expected)
@pytest.mark.usefixtures('request_context')
@pytest.mark.parametrize(('txn_id', 'payment_status', 'expected'), (
('12345', 'Completed', True),
('12345', 'Pending', False),
('123456', 'Completed', False),
('123456', 'Pending', False),
))
def test_ipn_is_transaction_duplicated(txn_id, payment_status, expected):
request.form = {'payment_status': 'Completed', 'txn_id': '12345'}
rh = RHPaypalIPN()
rh.registration = MagicMock()
rh.registration.transaction = None
assert not rh._is_transaction_duplicated()
transaction = PaymentTransaction(provider='paypal', data={'payment_status': payment_status, 'txn_id': txn_id})
rh.registration.transaction = transaction
assert rh._is_transaction_duplicated() == expected
@pytest.mark.usefixtures('db', 'request_context')
@pytest.mark.parametrize('fail', (
'verify',
'dup_txn',
'fail',
'refund',
'negative',
'status',
None,
))
def test_ipn_process(mocker, fail):
rt = mocker.patch('indico_payment_paypal.controllers.register_transaction')
post = mocker.patch('indico_payment_paypal.controllers.requests.post')
mocker.patch('indico_payment_paypal.controllers.notify_amount_inconsistency')
post.return_value.text = 'INVALID' if fail == 'verify' else 'VERIFIED'
rh = RHPaypalIPN()
rh._verify_business = MagicMock()
rh._is_transaction_duplicated = lambda: fail == 'dup_txn'
rh.event = MagicMock(id=1)
rh.registration = MagicMock()
rh.registration.getTotal.return_value = 10.00
payment_status = {'fail': 'Failed', 'refund': 'Refunded', 'status': 'Foobar'}.get(fail, 'Completed')
amount = '-10.00' if fail == 'negative' else '10.00'
request.view_args = {'event_id': rh.event.id}
request.args = {'registrantId': '1'}
request.form = {'payment_status': payment_status, 'txn_id': '12345', 'mc_gross': amount,
'mc_currency': 'EUR', 'business': 'foo@bar.com'}
with PaypalPaymentPlugin.instance.plugin_context():
rh._process()
assert post.called
assert rt.called == (fail is None)