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__])