feat(order): Add finalize order functionality
This commit is contained in:
@@ -28,14 +28,14 @@ Base.metadata.create_all(bind=connection)
|
||||
# Bind sessions to the single connection so all sessions share the same DB
|
||||
TestSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=connection)
|
||||
|
||||
test_session = None
|
||||
|
||||
|
||||
def get_test_session():
|
||||
"""Dependency override for get_session"""
|
||||
db = TestSessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
assert test_session is not None, "test_session is not set"
|
||||
yield test_session
|
||||
test_session.flush()
|
||||
|
||||
|
||||
app.dependency_overrides[get_session] = get_test_session
|
||||
@@ -57,21 +57,11 @@ def unauthorized_client():
|
||||
def test_db():
|
||||
"""Provides a database session for direct test usage"""
|
||||
db = TestSessionLocal()
|
||||
|
||||
# Start a SAVEPOINT so test changes can be rolled back without
|
||||
# closing the shared connection. Also restart the nested transaction
|
||||
# when the session issues commits internally.
|
||||
db.begin_nested()
|
||||
|
||||
@event.listens_for(db, "after_transaction_end")
|
||||
def restart_savepoint(session, transaction):
|
||||
# If the nested transaction ended, re-open it for continued isolation
|
||||
if transaction.nested and not session.is_active:
|
||||
session.begin_nested()
|
||||
|
||||
global test_session
|
||||
test_session = db
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
# Rollback to the SAVEPOINT and close the session to clean up
|
||||
test_session = None
|
||||
db.rollback()
|
||||
db.close()
|
||||
db.close()
|
||||
|
||||
31
test/fake_data.py
Normal file
31
test/fake_data.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from faker import Faker
|
||||
from faker.providers import BaseProvider
|
||||
|
||||
fake = Faker()
|
||||
|
||||
|
||||
class MyProvider(BaseProvider):
|
||||
def product(self) -> dict:
|
||||
return {
|
||||
"name": fake.text(max_nb_chars=10),
|
||||
"price": Decimal(
|
||||
fake.pyfloat(left_digits=2, right_digits=2, positive=True)
|
||||
),
|
||||
"unit_of_measure": fake.random_element(elements=["kg", "g", "l", "piece"]),
|
||||
"vat_rate": fake.random_element(elements=[7, 19]),
|
||||
}
|
||||
|
||||
def area(self) -> dict:
|
||||
return {
|
||||
"name": fake.text(max_nb_chars=10),
|
||||
"description": fake.text(max_nb_chars=100),
|
||||
}
|
||||
|
||||
def order(self) -> dict:
|
||||
return {}
|
||||
|
||||
|
||||
# then add new provider to faker instance
|
||||
fake.add_provider(MyProvider)
|
||||
71
test/test_shop.py
Normal file
71
test/test_shop.py
Normal file
@@ -0,0 +1,71 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from fake_data import fake
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from allmende_payment_system.database import ensure_user
|
||||
from allmende_payment_system.models import (
|
||||
Account,
|
||||
Area,
|
||||
Order,
|
||||
OrderItem,
|
||||
Product,
|
||||
Transaction,
|
||||
)
|
||||
|
||||
|
||||
def create_user_with_account(test_db, username: str, balance: float | None = None):
|
||||
user_info = {"username": username, "display_name": f"Display {username}"}
|
||||
user = ensure_user(user_info, test_db)
|
||||
account = Account(name=f"Account for {username}")
|
||||
test_db.add(account)
|
||||
user.accounts.append(account)
|
||||
|
||||
if balance is not None:
|
||||
user.accounts[0].transactions.append(
|
||||
Transaction(total_amount=Decimal(balance), type="deposit")
|
||||
)
|
||||
test_db.flush()
|
||||
return user
|
||||
|
||||
|
||||
def test_add_item_to_cart(client: TestClient, test_db):
|
||||
area = Area(**fake.area())
|
||||
test_db.add(area)
|
||||
product = Product(**fake.product())
|
||||
product.area = area
|
||||
test_db.add(product)
|
||||
test_db.flush()
|
||||
form_data = {"product_id": product.id, "quantity": 2, "area_id": area.id}
|
||||
|
||||
response = client.post(
|
||||
"/shop/cart/add",
|
||||
data=form_data,
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert response.status_code == 302
|
||||
|
||||
|
||||
def test_finalize_order(client: TestClient, test_db):
|
||||
area = Area(**fake.area())
|
||||
test_db.add(area)
|
||||
product = Product(**fake.product())
|
||||
product.area = area
|
||||
test_db.add(product)
|
||||
test_db.flush()
|
||||
|
||||
user = create_user_with_account(test_db, "test", balance=100.0)
|
||||
|
||||
user.shopping_cart.items.append(
|
||||
OrderItem(product=product, quantity=2, total_amount=product.price * 2)
|
||||
)
|
||||
test_db.flush()
|
||||
|
||||
response = client.get("/shop/finalize_order", follow_redirects=False)
|
||||
assert response.status_code == 302
|
||||
|
||||
assert len(user.shopping_cart.items) == 0
|
||||
assert len(user.orders) == 2 # shopping cart + finalized order
|
||||
|
||||
assert user.accounts[0].balance == Decimal(100.0) - (product.price * 2)
|
||||
Reference in New Issue
Block a user