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({}) @pytest.fixture(autouse=True) def run_around_tests(): clear_db() yield clear_db() def create_test_item(): response = client.post( "/items/", json={"name": "Test Item", "price": 10.99, "quantity": 100, "unit": "piece"} ) return response.json()["_id"] def test_create_order(): logger.info("Testing create order") item_id = create_test_item() order_data = { "user_id": str(ObjectId()), "items": [{"item_id": item_id, "quantity": 2}], "total_amount": 21.98, "payment_method": "credit_card" } response = client.post("/orders/", json=order_data) assert response.status_code == 200 assert "_id" in response.json() logger.info(f"Created order with ID: {response.json()['_id']}") def test_read_orders(): logger.info("Testing read orders") item_id = create_test_item() order_data = { "user_id": str(ObjectId()), "items": [{"item_id": item_id, "quantity": 2}], "total_amount": 21.98, "payment_method": "credit_card" } client.post("/orders/", json=order_data) response = client.get("/orders/") 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(): logger.info("Testing read single order") item_id = create_test_item() order_data = { "user_id": str(ObjectId()), "items": [{"item_id": item_id, "quantity": 2}], "total_amount": 21.98, "payment_method": "credit_card" } create_response = client.post("/orders/", json=order_data) order_id = create_response.json()["_id"] response = client.get(f"/orders/{order_id}") 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(): logger.info("Testing update order") item_id = create_test_item() order_data = { "user_id": str(ObjectId()), "items": [{"item_id": item_id, "quantity": 2}], "total_amount": 21.98, "payment_method": "credit_card" } create_response = client.post("/orders/", json=order_data) 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) 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(): logger.info("Testing delete order") item_id = create_test_item() order_data = { "user_id": str(ObjectId()), "items": [{"item_id": item_id, "quantity": 2}], "total_amount": 21.98, "payment_method": "credit_card" } create_response = client.post("/orders/", json=order_data) order_id = create_response.json()["_id"] response = client.delete(f"/orders/{order_id}") assert response.status_code == 200 assert response.json()["message"] == "Order deleted successfully" get_response = client.get(f"/orders/{order_id}") assert get_response.status_code == 404 logger.info(f"Deleted order with ID: {order_id}") @given( st.lists( st.fixed_dictionaries({ "item_id": st.text(min_size=24, max_size=24), "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(items, total_amount, payment_method): clear_db() item_id = create_test_item() for item in items: item["item_id"] = item_id # Use the same item_id for all items order_data = { "user_id": str(ObjectId()), "items": items, "total_amount": total_amount, "payment_method": payment_method } response = client.post("/orders/", json=order_data) assert response.status_code == 200 assert "_id" in response.json() order_id = response.json()["_id"] get_response = client.get(f"/orders/{order_id}") 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({ "user_id": st.text(min_size=24, max_size=24), "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(orders): clear_db() item_id = create_test_item() for order in orders: order_data = { "user_id": order["user_id"], "items": [{"item_id": item_id, "quantity": 1}], "total_amount": order["total_amount"], "payment_method": order["payment_method"] } client.post("/orders/", json=order_data) response = client.get("/orders/") assert response.status_code == 200 retrieved_orders = response.json() assert len(retrieved_orders) == len(orders) for retrieved_order in retrieved_orders: assert "user_id" in retrieved_order 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__])