point-of-sales/py-kivy/tests/test_orders.py

245 lines
7.6 KiB
Python

import pytest
import logging
from fastapi.testclient import TestClient
from hypothesis import given, strategies as st, settings
from bson import ObjectId
from pos_system.server import app
from pos_system.database import get_db
from datetime import datetime
client = TestClient(app)
logger = logging.getLogger(__name__)
def clear_db():
db = get_db()
db.orders.delete_many({})
db.items.delete_many({})
db.users.delete_many({})
@pytest.fixture(autouse=True)
def run_around_tests():
clear_db()
yield
clear_db()
def create_test_user():
user_data = {
"username": "testuser",
"email": "testuser@example.com",
"password": "testpassword",
"full_name": "Test User",
"is_active": True,
"is_superuser": False
}
response = client.post("/users/register", json=user_data)
assert response.status_code == 200, f"Failed to create user: {response.text}"
return response.json()
def login_test_user():
login_data = {
"username": "testuser",
"password": "testpassword"
}
response = client.post("/token", data=login_data)
assert response.status_code == 200
return response.json()["access_token"]
def create_test_item(token):
headers = {"Authorization": f"Bearer {token}"}
response = client.post(
"/items/",
headers=headers,
json={"name": "Test Item", "price": 10.99,
"quantity": 100, "unit": "piece"}
)
assert response.status_code == 200
return response.json()["_id"]
@pytest.fixture
def auth_headers():
create_test_user()
token = login_test_user()
return {"Authorization": f"Bearer {token}"}
def test_create_order(auth_headers):
logger.info("Testing create order")
item_id = create_test_item(auth_headers["Authorization"].split()[1])
order_data = {
"items": [{"item_id": item_id, "quantity": 2}],
"total_amount": 21.98,
"payment_method": "credit_card"
}
response = client.post("/orders/", json=order_data, headers=auth_headers)
assert response.status_code == 200
assert "_id" in response.json()
logger.info(f"Created order with ID: {response.json()['_id']}")
def test_read_orders(auth_headers):
logger.info("Testing read orders")
item_id = create_test_item(auth_headers["Authorization"].split()[1])
order_data = {
"items": [{"item_id": item_id, "quantity": 2}],
"total_amount": 21.98,
"payment_method": "credit_card"
}
client.post("/orders/", json=order_data, headers=auth_headers)
response = client.get("/orders/", headers=auth_headers)
assert response.status_code == 200
orders = response.json()
assert len(orders) == 1
assert orders[0]["total_amount"] == 21.98
logger.info(f"Retrieved {len(orders)} orders")
def test_read_order(auth_headers):
logger.info("Testing read single order")
item_id = create_test_item(auth_headers["Authorization"].split()[1])
order_data = {
"items": [{"item_id": item_id, "quantity": 2}],
"total_amount": 21.98,
"payment_method": "credit_card"
}
create_response = client.post(
"/orders/", json=order_data, headers=auth_headers)
order_id = create_response.json()["_id"]
response = client.get(f"/orders/{order_id}", headers=auth_headers)
assert response.status_code == 200
assert response.json()["total_amount"] == 21.98
logger.info(f"Retrieved order with ID: {order_id}")
def test_update_order(auth_headers):
logger.info("Testing update order")
item_id = create_test_item(auth_headers["Authorization"].split()[1])
order_data = {
"items": [{"item_id": item_id, "quantity": 2}],
"total_amount": 21.98,
"payment_method": "credit_card"
}
create_response = client.post(
"/orders/", json=order_data, headers=auth_headers)
order_id = create_response.json()["_id"]
update_data = {
"items": [{"item_id": item_id, "quantity": 3}],
"total_amount": 32.97,
"payment_method": "cash"
}
response = client.put(f"/orders/{order_id}",
json=update_data, headers=auth_headers)
assert response.status_code == 200
assert response.json()["total_amount"] == 32.97
assert response.json()["payment_method"] == "cash"
logger.info(f"Updated order with ID: {order_id}")
def test_delete_order(auth_headers):
logger.info("Testing delete order")
item_id = create_test_item(auth_headers["Authorization"].split()[1])
order_data = {
"items": [{"item_id": item_id, "quantity": 2}],
"total_amount": 21.98,
"payment_method": "credit_card"
}
create_response = client.post(
"/orders/", json=order_data, headers=auth_headers)
order_id = create_response.json()["_id"]
response = client.delete(f"/orders/{order_id}", headers=auth_headers)
assert response.status_code == 200
assert response.json()["message"] == "Order deleted successfully"
get_response = client.get(f"/orders/{order_id}", headers=auth_headers)
assert get_response.status_code == 404
logger.info(f"Deleted order with ID: {order_id}")
@given(
st.lists(
st.fixed_dictionaries({
"quantity": st.integers(min_value=1, max_value=10)
}),
min_size=1,
max_size=5
),
st.floats(min_value=0.01, max_value=1000,
allow_nan=False, allow_infinity=False),
st.sampled_from(["credit_card", "cash", "paypal"])
)
@settings(max_examples=50)
def test_create_order_property(auth_headers, items, total_amount, payment_method):
clear_db()
create_test_user()
token = login_test_user()
auth_headers = {"Authorization": f"Bearer {token}"}
item_id = create_test_item(token)
for item in items:
item["item_id"] = item_id # Use the same item_id for all items
order_data = {
"items": items,
"total_amount": total_amount,
"payment_method": payment_method
}
response = client.post("/orders/", json=order_data, headers=auth_headers)
assert response.status_code == 200
assert "_id" in response.json()
order_id = response.json()["_id"]
get_response = client.get(f"/orders/{order_id}", headers=auth_headers)
assert get_response.status_code == 200
retrieved_order = get_response.json()
assert retrieved_order["total_amount"] == total_amount
assert retrieved_order["payment_method"] == payment_method
assert len(retrieved_order["items"]) == len(items)
@given(
st.lists(
st.fixed_dictionaries({
"total_amount": st.floats(min_value=0.01, max_value=1000, allow_nan=False, allow_infinity=False),
"payment_method": st.sampled_from(["credit_card", "cash", "paypal"])
}),
min_size=1,
max_size=10
)
)
@settings(max_examples=20)
def test_read_orders_property(auth_headers, orders):
clear_db()
create_test_user()
token = login_test_user()
auth_headers = {"Authorization": f"Bearer {token}"}
item_id = create_test_item(token)
for order in orders:
order_data = {
"items": [{"item_id": item_id, "quantity": 1}],
"total_amount": order["total_amount"],
"payment_method": order["payment_method"]
}
client.post("/orders/", json=order_data, headers=auth_headers)
response = client.get("/orders/", headers=auth_headers)
assert response.status_code == 200
retrieved_orders = response.json()
assert len(retrieved_orders) == len(orders)
for retrieved_order in retrieved_orders:
assert "total_amount" in retrieved_order
assert "payment_method" in retrieved_order
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
if report.when == "call" and report.failed:
if "hypothesis" in item.keywords:
logger.error(f"Property test failed: {item.name}")
logger.error(f"Falsifying example: {call.excinfo.value}")
if __name__ == "__main__":
pytest.main([__file__])