fix existing tests

This commit is contained in:
imperosol
2026-03-05 19:14:58 +01:00
parent 2ee0c091be
commit 654ba383b4
8 changed files with 138 additions and 151 deletions

View File

@@ -213,9 +213,9 @@ def test_user_invoice_with_multiple_items():
"""Test that annotate_total() works when invoices contain multiple items."""
user: User = subscriber_user.make()
item_recipe = Recipe(InvoiceItem, invoice=foreign_key(Recipe(Invoice, user=user)))
item_recipe.make(_quantity=3, quantity=1, product_unit_price=5)
item_recipe.make(_quantity=1, quantity=1, product_unit_price=5)
item_recipe.make(_quantity=2, quantity=1, product_unit_price=iter([5, 8]))
item_recipe.make(_quantity=3, quantity=1, unit_price=5)
item_recipe.make(_quantity=1, quantity=1, unit_price=5)
item_recipe.make(_quantity=2, quantity=1, unit_price=iter([5, 8]))
res = list(
Invoice.objects.filter(user=user)
.annotate_total()

View File

@@ -2,10 +2,11 @@ from model_bakery.recipe import Recipe, foreign_key
from club.models import Club
from core.models import User
from counter.models import Counter, Product, Refilling, Selling
from counter.models import Counter, Price, Product, Refilling, Selling
counter_recipe = Recipe(Counter)
product_recipe = Recipe(Product, club=foreign_key(Recipe(Club)))
price_recipe = Recipe(Price, product=foreign_key(product_recipe))
sale_recipe = Recipe(
Selling,
product=foreign_key(product_recipe),

View File

@@ -55,10 +55,12 @@ def test_create_actions_alongside_product():
"selling_price": 1.0,
"special_selling_price": 1.0,
"limit_age": 0,
"form-TOTAL_FORMS": "2",
"form-INITIAL_FORMS": "0",
"form-0-task": "counter.tasks.archive_product",
"form-0-trigger_at": trigger_at,
"price-TOTAL_FORMS": "0",
"price-INITIAL_FORMS": "0",
"action-TOTAL_FORMS": "1",
"action-INITIAL_FORMS": "0",
"action-0-task": "counter.tasks.archive_product",
"action-0-trigger_at": trigger_at,
},
)
assert form.is_valid()

View File

@@ -20,7 +20,6 @@ import pytest
from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.contrib.auth.models import Permission, make_password
from django.core.cache import cache
from django.http import HttpResponse
from django.shortcuts import resolve_url
from django.test import Client, TestCase
@@ -34,13 +33,12 @@ from pytest_django.asserts import assertRedirects
from club.models import Membership
from core.baker_recipes import board_user, subscriber_user, very_old_subscriber_user
from core.models import BanGroup, User
from counter.baker_recipes import product_recipe, sale_recipe
from core.models import BanGroup, Group, User
from counter.baker_recipes import price_recipe, product_recipe, sale_recipe
from counter.models import (
Counter,
Customer,
Permanency,
Product,
Refilling,
ReturnableProduct,
Selling,
@@ -204,7 +202,7 @@ class TestRefilling(TestFullClickBase):
@dataclass
class BasketItem:
id: int | None = None
price_id: int | None = None
quantity: int | None = None
def to_form(self, index: int) -> dict[str, str]:
@@ -236,38 +234,52 @@ class TestCounterClick(TestFullClickBase):
cls.banned_counter_customer.ban_groups.add(
BanGroup.objects.get(pk=settings.SITH_GROUP_BANNED_COUNTER_ID)
)
subscriber_group = Group.objects.get(id=settings.SITH_GROUP_SUBSCRIBERS_ID)
old_subscriber_group = Group.objects.get(
id=settings.SITH_GROUP_OLD_SUBSCRIBERS_ID
)
cls.gift = product_recipe.make(
selling_price="-1.5",
special_selling_price="-1.5",
cls.gift = price_recipe.make(amount=-1.5, groups=[subscriber_group])
cls.beer = price_recipe.make(
groups=[subscriber_group],
amount=1.5,
product=product_recipe.make(limit_age=18),
)
cls.beer = product_recipe.make(
limit_age=18, selling_price=1.5, special_selling_price=1
cls.beer_tap = price_recipe.make(
groups=[subscriber_group],
amount=1.5,
product=product_recipe.make(limit_age=18, tray=True),
)
cls.beer_tap = product_recipe.make(
limit_age=18, tray=True, selling_price=1.5, special_selling_price=1
cls.snack = price_recipe.make(
groups=[subscriber_group, old_subscriber_group],
amount=1.5,
product=product_recipe.make(limit_age=0),
)
cls.snack = product_recipe.make(
limit_age=0, selling_price=1.5, special_selling_price=1
)
cls.stamps = product_recipe.make(
limit_age=0, selling_price=1.5, special_selling_price=1
cls.stamps = price_recipe.make(
groups=[subscriber_group],
amount=1.5,
product=product_recipe.make(limit_age=0),
)
ReturnableProduct.objects.all().delete()
cls.cons = baker.make(Product, selling_price=1)
cls.dcons = baker.make(Product, selling_price=-1)
cls.cons = price_recipe.make(amount=1, groups=[subscriber_group])
cls.dcons = price_recipe.make(amount=-1, groups=[subscriber_group])
baker.make(
ReturnableProduct,
product=cls.cons,
returned_product=cls.dcons,
product=cls.cons.product,
returned_product=cls.dcons.product,
max_return=3,
)
cls.counter.products.add(
cls.gift, cls.beer, cls.beer_tap, cls.snack, cls.cons, cls.dcons
cls.gift.product,
cls.beer.product,
cls.beer_tap.product,
cls.snack.product,
cls.cons.product,
cls.dcons.product,
)
cls.other_counter.products.add(cls.snack)
cls.club_counter.products.add(cls.stamps)
cls.other_counter.products.add(cls.snack.product)
cls.club_counter.products.add(cls.stamps.product)
def login_in_bar(self, barmen: User | None = None):
used_barman = barmen if barmen is not None else self.barmen
@@ -285,10 +297,7 @@ class TestCounterClick(TestFullClickBase):
) -> HttpResponse:
used_counter = counter if counter is not None else self.counter
used_client = client if client is not None else self.client
data = {
"form-TOTAL_FORMS": str(len(basket)),
"form-INITIAL_FORMS": "0",
}
data = {"form-TOTAL_FORMS": str(len(basket)), "form-INITIAL_FORMS": "0"}
for index, item in enumerate(basket):
data.update(item.to_form(index))
return used_client.post(
@@ -331,32 +340,22 @@ class TestCounterClick(TestFullClickBase):
res = self.submit_basket(
self.customer, [BasketItem(self.beer.id, 2), BasketItem(self.snack.id, 1)]
)
assert res.status_code == 302
self.assertRedirects(res, self.counter.get_absolute_url())
assert self.updated_amount(self.customer) == Decimal("5.5")
# Test barmen special price
force_refill_user(self.barmen, 10)
assert (
self.submit_basket(self.barmen, [BasketItem(self.beer.id, 1)])
).status_code == 302
assert self.updated_amount(self.barmen) == Decimal(9)
def test_click_tray_price(self):
force_refill_user(self.customer, 20)
self.login_in_bar(self.barmen)
# Not applying tray price
res = self.submit_basket(self.customer, [BasketItem(self.beer_tap.id, 2)])
assert res.status_code == 302
self.assertRedirects(res, self.counter.get_absolute_url())
assert self.updated_amount(self.customer) == Decimal(17)
# Applying tray price
res = self.submit_basket(self.customer, [BasketItem(self.beer_tap.id, 7)])
assert res.status_code == 302
self.assertRedirects(res, self.counter.get_absolute_url())
assert self.updated_amount(self.customer) == Decimal(8)
def test_click_alcool_unauthorized(self):
@@ -477,7 +476,8 @@ class TestCounterClick(TestFullClickBase):
BasketItem(None, 1),
BasketItem(self.beer.id, None),
]:
assert self.submit_basket(self.customer, [item]).status_code == 200
res = self.submit_basket(self.customer, [item])
assert res.status_code == 200
assert self.updated_amount(self.customer) == Decimal(10)
def test_click_not_enough_money(self):
@@ -506,29 +506,30 @@ class TestCounterClick(TestFullClickBase):
res = self.submit_basket(
self.customer, [BasketItem(self.beer.id, 1), BasketItem(self.gift.id, 1)]
)
assert res.status_code == 302
self.assertRedirects(res, self.counter.get_absolute_url())
assert self.updated_amount(self.customer) == 0
def test_recordings(self):
force_refill_user(self.customer, self.cons.selling_price * 3)
force_refill_user(self.customer, self.cons.amount * 3)
self.login_in_bar(self.barmen)
res = self.submit_basket(self.customer, [BasketItem(self.cons.id, 3)])
assert res.status_code == 302
assert self.updated_amount(self.customer) == 0
assert list(
self.customer.customer.return_balances.values("returnable", "balance")
) == [{"returnable": self.cons.cons.id, "balance": 3}]
) == [{"returnable": self.cons.product.cons.id, "balance": 3}]
res = self.submit_basket(self.customer, [BasketItem(self.dcons.id, 3)])
assert res.status_code == 302
assert self.updated_amount(self.customer) == self.dcons.selling_price * -3
assert self.updated_amount(self.customer) == self.dcons.amount * -3
res = self.submit_basket(
self.customer, [BasketItem(self.dcons.id, self.dcons.dcons.max_return)]
self.customer,
[BasketItem(self.dcons.id, self.dcons.product.dcons.max_return)],
)
# from now on, the user amount should not change
expected_amount = self.dcons.selling_price * (-3 - self.dcons.dcons.max_return)
expected_amount = self.dcons.amount * (-3 - self.dcons.product.dcons.max_return)
assert res.status_code == 302
assert self.updated_amount(self.customer) == expected_amount
@@ -545,48 +546,58 @@ class TestCounterClick(TestFullClickBase):
def test_recordings_when_negative(self):
sale_recipe.make(
customer=self.customer.customer,
product=self.dcons,
unit_price=self.dcons.selling_price,
product=self.dcons.product,
unit_price=self.dcons.amount,
quantity=10,
)
self.customer.customer.update_returnable_balance()
self.login_in_bar(self.barmen)
res = self.submit_basket(self.customer, [BasketItem(self.dcons.id, 1)])
assert res.status_code == 200
assert self.updated_amount(self.customer) == self.dcons.selling_price * -10
assert self.updated_amount(self.customer) == self.dcons.amount * -10
res = self.submit_basket(self.customer, [BasketItem(self.cons.id, 3)])
assert res.status_code == 302
assert (
self.updated_amount(self.customer)
== self.dcons.selling_price * -10 - self.cons.selling_price * 3
== self.dcons.amount * -10 - self.cons.amount * 3
)
res = self.submit_basket(self.customer, [BasketItem(self.beer.id, 1)])
assert res.status_code == 302
assert (
self.updated_amount(self.customer)
== self.dcons.selling_price * -10
- self.cons.selling_price * 3
- self.beer.selling_price
== self.dcons.amount * -10 - self.cons.amount * 3 - self.beer.amount
)
def test_no_fetch_archived_product(self):
counter = baker.make(Counter)
group = baker.make(Group)
customer = baker.make(Customer)
product_recipe.make(archived=True, counters=[counter])
unarchived_products = product_recipe.make(
archived=False, counters=[counter], _quantity=3
group.users.add(customer.user)
price_recipe.make(
_quantity=2,
product=iter(
product_recipe.make(archived=True, counters=[counter], _quantity=2)
),
groups=[group],
)
customer_products = counter.get_products_for(customer)
assert unarchived_products == customer_products
unarchived_prices = price_recipe.make(
_quantity=2,
product=iter(
product_recipe.make(archived=False, counters=[counter], _quantity=2)
),
groups=[group],
)
customer_prices = counter.get_prices_for(customer)
assert unarchived_prices == customer_prices
class TestCounterStats(TestCase):
@classmethod
def setUpTestData(cls):
cls.users = subscriber_user.make(_quantity=4)
product = product_recipe.make(selling_price=1)
product = price_recipe.make(amount=1).product
cls.counter = baker.make(
Counter, type=["BAR"], sellers=cls.users[:4], products=[product]
)
@@ -785,9 +796,6 @@ class TestClubCounterClickAccess(TestCase):
cls.user = subscriber_user.make()
def setUp(self):
cache.clear()
def test_anonymous(self):
res = self.client.get(self.click_url)
assert res.status_code == 403

View File

@@ -341,7 +341,7 @@ def test_update_balance():
def test_update_returnable_balance():
ReturnableProduct.objects.all().delete()
customer = baker.make(Customer)
products = product_recipe.make(selling_price=0, _quantity=4, _bulk_create=True)
products = product_recipe.make(_quantity=4, _bulk_create=True)
returnables = [
baker.make(
ReturnableProduct, product=products[0], returned_product=products[1]

View File

@@ -15,9 +15,8 @@ from pytest_django.asserts import assertNumQueries, assertRedirects
from club.models import Club
from core.baker_recipes import board_user, subscriber_user
from core.models import Group, User
from counter.baker_recipes import product_recipe
from counter.forms import ProductForm
from counter.models import Product, ProductFormula, ProductType
from counter.models import Product, ProductType
@pytest.mark.django_db
@@ -81,11 +80,11 @@ def test_fetch_product_access(
def test_fetch_product_nb_queries(client: Client):
client.force_login(baker.make(User, is_superuser=True))
cache.clear()
with assertNumQueries(5):
with assertNumQueries(6):
# - 2 for authentication
# - 1 for pagination
# - 1 for the actual request
# - 1 to prefetch the related buying_groups
# - 2 to prefetch the related prices and groups
client.get(reverse("api:search_products_detailed"))
@@ -107,8 +106,10 @@ class TestCreateProduct(TestCase):
"selling_price": 1.0,
"special_selling_price": 1.0,
"limit_age": 0,
"form-TOTAL_FORMS": 0,
"form-INITIAL_FORMS": 0,
"price-TOTAL_FORMS": 0,
"price-INITIAL_FORMS": 0,
"action-TOTAL_FORMS": 0,
"action-INITIAL_FORMS": 0,
}
def test_form(self):
@@ -118,35 +119,6 @@ class TestCreateProduct(TestCase):
assert instance.club == self.club
assert instance.product_type == self.product_type
assert instance.name == "foo"
assert instance.selling_price == 1.0
def test_form_with_product_from_formula(self):
"""Test when the edited product is a result of a formula."""
self.client.force_login(self.counter_admin)
products = product_recipe.make(
selling_price=iter([1.5, 1, 1]),
special_selling_price=iter([1.4, 0.9, 0.9]),
_quantity=3,
_bulk_create=True,
)
baker.make(ProductFormula, result=products[0], products=products[1:])
data = self.data | {"selling_price": 1.7, "special_selling_price": 1.5}
form = ProductForm(data=data, instance=products[0])
assert form.is_valid()
# it shouldn't be possible to give a price higher than the formula's products
data = self.data | {"selling_price": 2.1, "special_selling_price": 1.9}
form = ProductForm(data=data, instance=products[0])
assert not form.is_valid()
assert form.errors == {
"selling_price": [
"Assurez-vous que cette valeur est inférieure ou égale à 2.00."
],
"special_selling_price": [
"Assurez-vous que cette valeur est inférieure ou égale à 1.80."
],
}
def test_view(self):
self.client.force_login(self.counter_admin)

View File

@@ -11,7 +11,12 @@ from pytest_django.asserts import assertRedirects
from core.baker_recipes import subscriber_user
from core.models import Group, User
from counter.baker_recipes import product_recipe, refill_recipe, sale_recipe
from counter.baker_recipes import (
price_recipe,
product_recipe,
refill_recipe,
sale_recipe,
)
from counter.models import (
Counter,
Customer,
@@ -147,29 +152,29 @@ class TestEboutic(TestCase):
product_type = baker.make(ProductType)
cls.snack = product_recipe.make(
selling_price=1.5, special_selling_price=1, product_type=product_type
cls.snack = price_recipe.make(
amount=1.5, product=product_recipe.make(product_type=product_type)
)
cls.beer = product_recipe.make(
limit_age=18,
selling_price=2.5,
special_selling_price=1,
product_type=product_type,
cls.beer = price_recipe.make(
product=product_recipe.make(limit_age=18, product_type=product_type),
amount=2.5,
)
cls.not_in_counter = product_recipe.make(
selling_price=3.5, product_type=product_type
cls.not_in_counter = price_recipe.make(
product=product_recipe.make(product_type=product_type), amount=3.5
)
cls.cotiz = price_recipe.make(
amount=10, product=product_recipe.make(product_type=product_type)
)
cls.cotiz = product_recipe.make(selling_price=10, product_type=product_type)
cls.group_public.products.add(cls.snack, cls.beer, cls.not_in_counter)
cls.group_cotiz.products.add(cls.cotiz)
cls.group_public.prices.add(cls.snack, cls.beer, cls.not_in_counter)
cls.group_cotiz.prices.add(cls.cotiz)
cls.subscriber.groups.add(cls.group_cotiz, cls.group_public)
cls.new_customer.groups.add(cls.group_public)
cls.new_customer_adult.groups.add(cls.group_public)
cls.eboutic = get_eboutic()
cls.eboutic.products.add(cls.cotiz, cls.beer, cls.snack)
cls.eboutic.products.add(cls.cotiz.product, cls.beer.product, cls.snack.product)
@classmethod
def set_age(cls, user: User, age: int):
@@ -253,7 +258,7 @@ class TestEboutic(TestCase):
self.submit_basket([BasketItem(self.snack.id, 2)]),
reverse("eboutic:checkout", kwargs={"basket_id": 1}),
)
assert Basket.objects.get(id=1).total == self.snack.selling_price * 2
assert Basket.objects.get(id=1).total == self.snack.amount * 2
self.client.force_login(self.new_customer_adult)
assertRedirects(
@@ -263,8 +268,7 @@ class TestEboutic(TestCase):
reverse("eboutic:checkout", kwargs={"basket_id": 2}),
)
assert (
Basket.objects.get(id=2).total
== self.snack.selling_price * 2 + self.beer.selling_price
Basket.objects.get(id=2).total == self.snack.amount * 2 + self.beer.amount
)
self.client.force_login(self.subscriber)
@@ -280,7 +284,5 @@ class TestEboutic(TestCase):
)
assert (
Basket.objects.get(id=3).total
== self.snack.selling_price * 2
+ self.beer.selling_price
+ self.cotiz.selling_price
== self.snack.amount * 2 + self.beer.amount + self.cotiz.amount
)

View File

@@ -16,7 +16,7 @@ from model_bakery import baker
from pytest_django.asserts import assertRedirects
from core.baker_recipes import old_subscriber_user, subscriber_user
from counter.baker_recipes import product_recipe
from counter.baker_recipes import price_recipe, product_recipe
from counter.models import Product, ProductType, Selling
from counter.tests.test_counter import force_refill_user
from eboutic.models import Basket, BasketItem
@@ -32,23 +32,22 @@ class TestPaymentBase(TestCase):
cls.basket = baker.make(Basket, user=cls.customer)
cls.refilling = product_recipe.make(
product_type_id=settings.SITH_COUNTER_PRODUCTTYPE_REFILLING,
selling_price=15,
prices=[price_recipe.make(amount=15)],
)
product_type = baker.make(ProductType)
cls.snack = product_recipe.make(
selling_price=1.5, special_selling_price=1, product_type=product_type
product_type=product_type, prices=[price_recipe.make(amount=1.5)]
)
cls.beer = product_recipe.make(
limit_age=18,
selling_price=2.5,
special_selling_price=1,
product_type=product_type,
prices=[price_recipe.make(amount=2.5)],
)
BasketItem.from_product(cls.snack, 1, cls.basket).save()
BasketItem.from_product(cls.beer, 2, cls.basket).save()
BasketItem.from_price(cls.snack.prices.first(), 1, cls.basket).save()
BasketItem.from_price(cls.beer.prices.first(), 2, cls.basket).save()
class TestPaymentSith(TestPaymentBase):
@@ -116,13 +115,13 @@ class TestPaymentSith(TestPaymentBase):
assert len(sellings) == 2
assert sellings[0].payment_method == Selling.PaymentMethod.SITH_ACCOUNT
assert sellings[0].quantity == 1
assert sellings[0].unit_price == self.snack.selling_price
assert sellings[0].unit_price == self.snack.prices.first().amount
assert sellings[0].counter.type == "EBOUTIC"
assert sellings[0].product == self.snack
assert sellings[1].payment_method == Selling.PaymentMethod.SITH_ACCOUNT
assert sellings[1].quantity == 2
assert sellings[1].unit_price == self.beer.selling_price
assert sellings[1].unit_price == self.beer.prices.first().amount
assert sellings[1].counter.type == "EBOUTIC"
assert sellings[1].product == self.beer
@@ -146,7 +145,7 @@ class TestPaymentSith(TestPaymentBase):
)
def test_refilling_in_basket(self):
BasketItem.from_product(self.refilling, 1, self.basket).save()
BasketItem.from_price(self.refilling.prices.first(), 1, self.basket).save()
self.client.force_login(self.customer)
force_refill_user(self.customer, self.basket.total + 1)
self.customer.customer.refresh_from_db()
@@ -191,8 +190,8 @@ class TestPaymentCard(TestPaymentBase):
def test_buy_success(self):
response = self.client.get(self.generate_bank_valid_answer(self.basket))
assert response.status_code == 200
assert response.content.decode("utf-8") == "Payment successful"
assert Basket.objects.filter(id=self.basket.id).first() is None
assert response.content.decode() == "Payment successful"
assert not Basket.objects.filter(id=self.basket.id).exists()
sellings = Selling.objects.filter(customer=self.customer.customer).order_by(
"quantity"
@@ -200,13 +199,13 @@ class TestPaymentCard(TestPaymentBase):
assert len(sellings) == 2
assert sellings[0].payment_method == Selling.PaymentMethod.CARD
assert sellings[0].quantity == 1
assert sellings[0].unit_price == self.snack.selling_price
assert sellings[0].unit_price == self.snack.prices.first().amount
assert sellings[0].counter.type == "EBOUTIC"
assert sellings[0].product == self.snack
assert sellings[1].payment_method == Selling.PaymentMethod.CARD
assert sellings[1].quantity == 2
assert sellings[1].unit_price == self.beer.selling_price
assert sellings[1].unit_price == self.beer.prices.first().amount
assert sellings[1].counter.type == "EBOUTIC"
assert sellings[1].product == self.beer
@@ -216,7 +215,9 @@ class TestPaymentCard(TestPaymentBase):
assert not customer.subscriptions.first().is_valid_now()
basket = baker.make(Basket, user=customer)
BasketItem.from_product(Product.objects.get(code="2SCOTIZ"), 1, basket).save()
BasketItem.from_price(
Product.objects.get(code="2SCOTIZ").prices.first(), 1, basket
).save()
response = self.client.get(self.generate_bank_valid_answer(basket))
assert response.status_code == 200
@@ -228,12 +229,13 @@ class TestPaymentCard(TestPaymentBase):
assert subscription.location == "EBOUTIC"
def test_buy_refilling(self):
BasketItem.from_product(self.refilling, 2, self.basket).save()
price = self.refilling.prices.first()
BasketItem.from_price(price, 2, self.basket).save()
response = self.client.get(self.generate_bank_valid_answer(self.basket))
assert response.status_code == 200
self.customer.customer.refresh_from_db()
assert self.customer.customer.amount == self.refilling.selling_price * 2
assert self.customer.customer.amount == price.amount * 2
def test_multiple_responses(self):
bank_response = self.generate_bank_valid_answer(self.basket)
@@ -253,17 +255,17 @@ class TestPaymentCard(TestPaymentBase):
self.basket.delete()
response = self.client.get(bank_response)
assert response.status_code == 500
assert (
response.text
== "Basket processing failed with error: SuspiciousOperation('Basket does not exists')"
assert response.text == (
"Basket processing failed with error: "
"SuspiciousOperation('Basket does not exists')"
)
def test_altered_basket(self):
bank_response = self.generate_bank_valid_answer(self.basket)
BasketItem.from_product(self.snack, 1, self.basket).save()
BasketItem.from_price(self.snack.prices.first(), 1, self.basket).save()
response = self.client.get(bank_response)
assert response.status_code == 500
assert (
response.text == "Basket processing failed with error: "
assert response.text == (
"Basket processing failed with error: "
"SuspiciousOperation('Basket total and amount do not match')"
)