svthalia/concrexit

View on GitHub
website/payments/tests/api/v1/test_viewsets_payments.py

Summary

Maintainability
A
55 mins
Test Coverage
from unittest import mock
from unittest.mock import MagicMock, Mock

from django.apps import apps
from django.test import TestCase, override_settings
from django.urls import reverse

from freezegun import freeze_time
from rest_framework.test import APIClient

from members.models import Member
from payments.exceptions import PaymentError
from payments.models import BankAccount, Payment, PaymentUser
from payments.payables import payables
from payments.tests.__mocks__ import MockModel, MockPayable


@freeze_time("2020-09-01")
@override_settings(SUSPEND_SIGNALS=True, THALIA_PAY_ENABLED_PAYMENT_METHOD=True)
class PaymentProcessViewTest(TestCase):
    """Test for the PaymentProcessView."""

    fixtures = ["members.json"]

    test_body = {
        "app_label": "mock_app",
        "model_name": "mock_model",
        "payable_pk": "mock_payable_pk",
    }

    @classmethod
    def setUpTestData(cls):
        cls.user = Member.objects.filter(last_name="Wiggers").first()
        cls.account1 = BankAccount.objects.create(
            owner=cls.user,
            initials="J1",
            last_name="Test",
            iban="NL91ABNA0417164300",
            valid_from="2019-03-01",
            signature="sig",
            mandate_no="11-2",
        )
        cls.user = PaymentUser.objects.get(pk=cls.user.pk)

    def setUp(self):
        payables.register(MockModel, MockPayable)

        self.account1.refresh_from_db()
        self.client = APIClient()
        self.client.force_login(self.user)

        self.payable = MockPayable(MockModel(payer=self.user))
        self.original_get_payable = payables.get_payable
        payables.get_payable = MagicMock()
        payables.get_payable.return_value = self.payable

        self.original_get_model = apps.get_model
        mock_get_model = mock_get_model = MagicMock()

        def side_effect(*args, **kwargs):
            if "app_label" in kwargs and kwargs["app_label"] == "mock_app":
                return mock_get_model
            return self.original_get_model(*args, **kwargs)

        apps.get_model = Mock(side_effect=side_effect)

    def tearDown(self):
        apps.get_model = self.original_get_model
        payables.get_payable = self.original_get_payable
        payables._unregister(MockModel)

    def test_not_logged_in(self):
        self.client.logout()

        response = self.client.post(reverse("api:v1:payment-list"))
        self.assertEqual(403, response.status_code)

    @override_settings(THALIA_PAY_ENABLED_PAYMENT_METHOD=False)
    def test_member_has_tpay_enabled(self):
        response = self.client.post(
            reverse("api:v1:payment-list"), self.test_body, format="json"
        )
        self.assertEqual(400, response.status_code)

    def test_different_member(self):
        self.payable.model.payer = PaymentUser()

        response = self.client.post(
            reverse("api:v1:payment-list"), self.test_body, format="json"
        )

        self.assertEqual(403, response.status_code)
        self.assertEqual(
            {"detail": "You are not allowed to process this payment."}, response.data
        )

    def test_already_paid(self):
        self.payable.model.payment = Payment(amount=8)

        response = self.client.post(
            reverse("api:v1:payment-list"), self.test_body, format="json"
        )

        self.assertEqual(409, response.status_code)
        self.assertEqual(
            {"detail": "This object has already been paid for."}, response.data
        )

    @mock.patch("payments.services.create_payment")
    @mock.patch("payments.payables.payables.get_payable")
    def test_creates_payment(self, get_payable, create_payment):
        def set_payments_side_effect(*args, **kwargs):
            self.payable.model.payment = Payment.objects.create(amount=8)

        create_payment.side_effect = set_payments_side_effect
        get_payable.return_value = self.payable

        response = self.client.post(
            reverse("api:v1:payment-list"), self.test_body, format="json"
        )

        create_payment.assert_called_with(self.payable, self.user, Payment.TPAY)

        self.assertEqual(201, response.status_code)
        self.assertEqual(
            reverse("api:v1:payment-detail", kwargs={"pk": self.payable.payment.pk}),
            response.headers["Location"],
        )

    @mock.patch("payments.services.create_payment")
    def test_payment_create_error(self, create_payment):
        create_payment.side_effect = PaymentError("Test error")

        response = self.client.post(
            reverse("api:v1:payment-list"), self.test_body, format="json"
        )

        self.assertEqual(400, response.status_code)