Sith/eboutic/tests.py

244 lines
10 KiB
Python
Raw Permalink Normal View History

2023-04-06 11:08:42 +00:00
# -*- coding:utf-8 -*-
#
2023-04-06 11:08:42 +00:00
# Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr
# All contributors are listed in the CONTRIBUTORS file.
#
2023-04-06 11:08:42 +00:00
# This file is part of the website of the UTBM Student Association (AE UTBM),
# https://ae.utbm.fr.
#
2023-04-06 11:08:42 +00:00
# You can find the whole source code at https://github.com/ae-utbm/sith3
#
2023-04-06 11:08:42 +00:00
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3)
# SEE : https://raw.githubusercontent.com/ae-utbm/sith3/master/LICENSE
# OR WITHIN THE LOCAL FILE "LICENSE"
#
2023-04-06 11:08:42 +00:00
# PREVIOUSLY LICENSED UNDER THE MIT LICENSE,
# SEE : https://raw.githubusercontent.com/ae-utbm/sith3/master/LICENSE.old
# OR WITHIN THE LOCAL FILE "LICENSE.old"
#
2017-05-01 17:39:13 +00:00
import base64
2022-09-25 19:29:42 +00:00
import json
2017-05-01 17:39:13 +00:00
import urllib
2022-09-25 19:29:42 +00:00
from django.conf import settings
from django.db.models import Max
from django.test import TestCase
from django.urls import reverse
2024-06-24 11:07:36 +00:00
from OpenSSL import crypto
2017-05-01 17:39:13 +00:00
from core.models import User
2024-06-24 11:07:36 +00:00
from counter.models import Counter, Customer, Product, Selling
2022-09-25 19:29:42 +00:00
from eboutic.models import Basket
2017-06-12 07:50:08 +00:00
2017-05-01 17:39:13 +00:00
class EbouticTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.barbar = Product.objects.get(code="BARB")
cls.refill = Product.objects.get(code="15REFILL")
cls.cotis = Product.objects.get(code="1SCOTIZ")
cls.eboutic = Counter.objects.get(name="Eboutic")
cls.skia = User.objects.get(username="skia")
cls.subscriber = User.objects.get(username="subscriber")
cls.old_subscriber = User.objects.get(username="old_subscriber")
cls.public = User.objects.get(username="public")
2017-05-01 17:39:13 +00:00
def get_busy_basket(self, user) -> Basket:
2022-09-25 19:29:42 +00:00
"""
Create and return a basket with 3 barbar and 1 cotis in it.
Edit the client session to store the basket id in it
"""
session = self.client.session
basket = Basket.objects.create(user=user)
session["basket_id"] = basket.id
session.save()
basket.add_product(self.barbar, 3)
basket.add_product(self.cotis)
return basket
def generate_bank_valid_answer(self) -> str:
basket = Basket.from_session(self.client.session)
basket_id = basket.id
amount = int(basket.get_total() * 100)
query = f"Amount={amount}&BasketID={basket_id}&Auto=42&Error=00000"
2017-05-01 17:39:13 +00:00
with open("./eboutic/tests/private_key.pem") as f:
PRIVKEY = f.read()
with open("./eboutic/tests/public_key.pem") as f:
settings.SITH_EBOUTIC_PUB_KEY = f.read()
privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, PRIVKEY)
2022-08-03 19:48:37 +00:00
sig = crypto.sign(privkey, query.encode("utf-8"), "sha1")
2017-05-01 17:39:13 +00:00
b64sig = base64.b64encode(sig).decode("ascii")
2018-10-04 19:29:19 +00:00
url = reverse("eboutic:etransation_autoanswer") + "?%s&Sig=%s" % (
query,
urllib.parse.quote_plus(b64sig),
)
return url
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_buy_with_sith_account(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
self.subscriber.customer.amount = 100 # give money before test
self.subscriber.customer.save()
basket = self.get_busy_basket(self.subscriber)
amount = basket.get_total()
response = self.client.post(reverse("eboutic:pay_with_sith"))
self.assertRedirects(response, "/eboutic/pay/success/")
new_balance = Customer.objects.get(user=self.subscriber).amount
assert float(new_balance) == 100 - amount
expected = 'basket_items=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/eboutic'
assert expected == self.client.cookies["basket_items"].OutputString()
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_buy_with_sith_account_no_money(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
basket = self.get_busy_basket(self.subscriber)
initial = basket.get_total() - 1 # just not enough to complete the sale
2022-09-25 19:29:42 +00:00
self.subscriber.customer.amount = initial
self.subscriber.customer.save()
response = self.client.post(reverse("eboutic:pay_with_sith"))
self.assertRedirects(response, "/eboutic/pay/failure/")
new_balance = Customer.objects.get(user=self.subscriber).amount
assert float(new_balance) == initial
# this cookie should be removed after payment
expected = 'basket_items=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/eboutic'
assert expected == self.client.cookies["basket_items"].OutputString()
2022-09-25 19:29:42 +00:00
def test_submit_basket(self):
self.client.force_login(self.subscriber)
self.client.cookies["basket_items"] = """[
2022-09-25 19:29:42 +00:00
{"id": 2, "name": "Cotis 2 semestres", "quantity": 1, "unit_price": 28},
{"id": 4, "name": "Barbar", "quantity": 3, "unit_price": 1.7}
]"""
response = self.client.get(reverse("eboutic:command"))
assert response.status_code == 200
2022-09-25 19:29:42 +00:00
self.assertInHTML(
"<tr><td>Cotis 2 semestres</td><td>1</td><td>28.00 €</td></tr>",
response.content.decode(),
)
self.assertInHTML(
"<tr><td>Barbar</td><td>3</td><td>1.70 €</td></tr>",
response.content.decode(),
)
assert "basket_id" in self.client.session
2022-09-25 19:29:42 +00:00
basket = Basket.objects.get(id=self.client.session["basket_id"])
assert basket.items.count() == 2
2022-09-25 19:29:42 +00:00
barbar = basket.items.filter(product_name="Barbar").first()
assert barbar is not None
assert barbar.quantity == 3
2022-09-25 19:29:42 +00:00
cotis = basket.items.filter(product_name="Cotis 2 semestres").first()
assert cotis is not None
assert cotis.quantity == 1
assert basket.get_total() == 3 * 1.7 + 28
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_submit_empty_basket(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
self.client.cookies["basket_items"] = "[]"
response = self.client.get(reverse("eboutic:command"))
2022-09-25 19:29:42 +00:00
self.assertRedirects(response, "/eboutic/")
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_submit_invalid_basket(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
max_id = Product.objects.aggregate(res=Max("id"))["res"]
self.client.cookies["basket_items"] = f"""[
2022-09-25 19:29:42 +00:00
{{"id": {max_id + 1}, "name": "", "quantity": 1, "unit_price": 28}}
]"""
response = self.client.get(reverse("eboutic:command"))
cookie = self.client.cookies["basket_items"].OutputString()
assert 'basket_items=""' in cookie
assert "Path=/eboutic" in cookie
2022-09-25 19:29:42 +00:00
self.assertRedirects(response, "/eboutic/")
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_submit_basket_illegal_quantity(self):
self.client.force_login(self.subscriber)
self.client.cookies["basket_items"] = """[
2022-09-25 19:29:42 +00:00
{"id": 4, "name": "Barbar", "quantity": -1, "unit_price": 1.7}
]"""
response = self.client.get(reverse("eboutic:command"))
2022-09-25 19:29:42 +00:00
self.assertRedirects(response, "/eboutic/")
2022-09-25 19:29:42 +00:00
def test_buy_subscribe_product_with_credit_card(self):
self.client.force_login(self.old_subscriber)
2022-09-25 19:29:42 +00:00
response = self.client.get(
reverse("core:user_profile", kwargs={"user_id": self.old_subscriber.id})
)
assert "Non cotisant" in str(response.content)
self.client.cookies["basket_items"] = """[
2022-09-25 19:29:42 +00:00
{"id": 2, "name": "Cotis 2 semestres", "quantity": 1, "unit_price": 28}
]"""
response = self.client.get(reverse("eboutic:command"))
2022-09-25 19:29:42 +00:00
self.assertInHTML(
"<tr><td>Cotis 2 semestres</td><td>1</td><td>28.00 €</td></tr>",
response.content.decode(),
)
2022-09-25 19:29:42 +00:00
basket = Basket.objects.get(id=self.client.session["basket_id"])
assert basket.items.count() == 1
response = self.client.get(self.generate_bank_valid_answer())
assert response.status_code == 200
assert response.content.decode("utf-8") == "Payment successful"
2022-09-25 19:29:42 +00:00
subscriber = User.objects.get(id=self.old_subscriber.id)
assert subscriber.subscriptions.count() == 2
2022-09-25 19:29:42 +00:00
sub = subscriber.subscriptions.order_by("-subscription_end").first()
assert sub.is_valid_now()
assert sub.member == subscriber
assert sub.subscription_type == "deux-semestres"
assert sub.location == "EBOUTIC"
2017-05-01 17:39:13 +00:00
def test_buy_refill_product_with_credit_card(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
# basket contains 1 refill item worth 15€
self.client.cookies["basket_items"] = json.dumps(
[{"id": 3, "name": "Rechargement 15 €", "quantity": 1, "unit_price": 15}]
2018-10-04 19:29:19 +00:00
)
2022-09-25 19:29:42 +00:00
initial_balance = self.subscriber.customer.amount
self.client.get(reverse("eboutic:command"))
2017-05-01 17:39:13 +00:00
url = self.generate_bank_valid_answer()
response = self.client.get(url)
assert response.status_code == 200
assert response.content.decode() == "Payment successful"
2022-09-25 19:29:42 +00:00
new_balance = Customer.objects.get(user=self.subscriber).amount
assert new_balance == initial_balance + 15
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_alter_basket_after_submission(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
self.client.cookies["basket_items"] = json.dumps(
[{"id": 4, "name": "Barbar", "quantity": 1, "unit_price": 1.7}]
2018-10-04 19:29:19 +00:00
)
self.client.get(reverse("eboutic:command"))
et_answer_url = self.generate_bank_valid_answer()
2022-09-25 19:29:42 +00:00
self.client.cookies["basket_items"] = json.dumps(
[ # alter basket
{"id": 4, "name": "Barbar", "quantity": 3, "unit_price": 1.7}
]
2018-10-04 19:29:19 +00:00
)
self.client.get(reverse("eboutic:command"))
response = self.client.get(et_answer_url)
assert response.status_code == 500
assert (
"Basket processing failed with error: SuspiciousOperation('Basket total and amount do not match'"
in response.content.decode("utf-8"),
2018-10-04 19:29:19 +00:00
)
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
def test_buy_simple_product_with_credit_card(self):
self.client.force_login(self.subscriber)
2022-09-25 19:29:42 +00:00
self.client.cookies["basket_items"] = json.dumps(
[{"id": 4, "name": "Barbar", "quantity": 1, "unit_price": 1.7}]
2018-10-04 19:29:19 +00:00
)
self.client.get(reverse("eboutic:command"))
et_answer_url = self.generate_bank_valid_answer()
response = self.client.get(et_answer_url)
assert response.status_code == 200
assert response.content.decode("utf-8") == "Payment successful"
2017-05-01 17:39:13 +00:00
2022-09-25 19:29:42 +00:00
selling = (
Selling.objects.filter(customer=self.subscriber.customer)
.order_by("-date")
.first()
)
assert selling.payment_method == "CARD"
assert selling.quantity == 1
assert selling.unit_price == self.barbar.selling_price
assert selling.counter.type == "EBOUTIC"
assert selling.product == self.barbar