mirror of
https://github.com/sstent/foodplanner.git
synced 2025-12-06 08:01:47 +00:00
201 lines
6.8 KiB
Python
201 lines
6.8 KiB
Python
"""
|
|
Tests for Foods CRUD operations
|
|
"""
|
|
import pytest
|
|
from datetime import date
|
|
import json
|
|
|
|
|
|
class TestFoodsRoutes:
|
|
"""Test food-related routes"""
|
|
|
|
def test_get_foods_page(self, client):
|
|
"""Test GET /foods page"""
|
|
response = client.get("/foods")
|
|
assert response.status_code == 200
|
|
assert b"Foods" in response.content or b"foods" in response.content
|
|
|
|
def test_add_food(self, client):
|
|
"""Test POST /foods/add"""
|
|
response = client.post("/foods/add", data={
|
|
"name": "New Test Food",
|
|
"serving_size": "100",
|
|
"serving_unit": "g",
|
|
"calories": 150.0,
|
|
"protein": 8.0,
|
|
"carbs": 15.0,
|
|
"fat": 3.0,
|
|
"fiber": 2.0,
|
|
"sugar": 1.0,
|
|
"sodium": 75.0,
|
|
"calcium": 30.0,
|
|
"source": "manual",
|
|
"brand": "Test Brand"
|
|
})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
def test_add_food_duplicate_name(self, client, sample_food):
|
|
"""Test adding food with duplicate name"""
|
|
response = client.post("/foods/add", data={
|
|
"name": sample_food.name,
|
|
"serving_size": "100",
|
|
"serving_unit": "g",
|
|
"calories": 150.0,
|
|
"protein": 8.0,
|
|
"carbs": 15.0,
|
|
"fat": 3.0,
|
|
"fiber": 2.0,
|
|
"sugar": 1.0,
|
|
"sodium": 75.0,
|
|
"calcium": 30.0,
|
|
"source": "manual",
|
|
"brand": "Test Brand"
|
|
})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "error"
|
|
|
|
def test_edit_food(self, client, sample_food):
|
|
"""Test POST /foods/edit"""
|
|
response = client.post("/foods/edit", data={
|
|
"food_id": sample_food.id,
|
|
"name": "Updated Food Name",
|
|
"serving_size": "150",
|
|
"serving_unit": "g",
|
|
"calories": 250.0,
|
|
"protein": 12.0,
|
|
"carbs": 25.0,
|
|
"fat": 6.0,
|
|
"fiber": 3.0,
|
|
"sugar": 4.0,
|
|
"sodium": 120.0,
|
|
"calcium": 60.0,
|
|
"source": "manual",
|
|
"brand": "Updated Brand"
|
|
})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
def test_edit_nonexistent_food(self, client):
|
|
"""Test editing non-existent food"""
|
|
response = client.post("/foods/edit", data={
|
|
"food_id": 99999,
|
|
"name": "Updated Food Name",
|
|
"serving_size": "150",
|
|
"serving_unit": "g",
|
|
"calories": 250.0,
|
|
"protein": 12.0,
|
|
"carbs": 25.0,
|
|
"fat": 6.0,
|
|
"fiber": 3.0,
|
|
"sugar": 4.0,
|
|
"sodium": 120.0,
|
|
"calcium": 60.0,
|
|
"source": "manual",
|
|
"brand": "Updated Brand"
|
|
})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "error"
|
|
|
|
def test_delete_foods(self, client, sample_foods):
|
|
"""Test POST /foods/delete"""
|
|
food_ids = [food.id for food in sample_foods[:2]]
|
|
response = client.post("/foods/delete",
|
|
json={"food_ids": food_ids})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
def test_search_openfoodfacts(self, client):
|
|
"""Test GET /foods/search_openfoodfacts"""
|
|
# This test requires OpenFoodFacts SDK to be installed
|
|
response = client.get("/foods/search_openfoodfacts?query=apple&limit=5")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
# Should either succeed or fail gracefully if module not installed
|
|
assert "status" in data
|
|
|
|
|
|
class TestFoodsBulkUpload:
|
|
"""Test bulk food upload functionality"""
|
|
|
|
def test_bulk_upload_foods_csv(self, client, tmp_path):
|
|
"""Test POST /foods/upload with CSV"""
|
|
# Create test CSV file
|
|
csv_content = """ID,Brand,Serving (g),Calories,Protein (g),Carbohydrate (g),Fat (g),Fiber (g),Sugar (g),Sodium (mg),Calcium (mg)
|
|
Apple,Generic,100,52,0.3,14,0.2,2.4,10,1,6
|
|
Banana,Generic,100,89,1.1,23,0.3,2.6,12,1,5"""
|
|
|
|
csv_file = tmp_path / "test_foods.csv"
|
|
csv_file.write_text(csv_content)
|
|
|
|
with open(csv_file, 'rb') as f:
|
|
response = client.post("/foods/upload",
|
|
files={"file": ("test_foods.csv", f, "text/csv")})
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "created" in data or "updated" in data
|
|
|
|
def test_bulk_upload_invalid_csv(self, client, tmp_path):
|
|
"""Test bulk upload with invalid CSV"""
|
|
csv_content = """Invalid,CSV,Format
|
|
1,2,3"""
|
|
|
|
csv_file = tmp_path / "invalid.csv"
|
|
csv_file.write_text(csv_content)
|
|
|
|
with open(csv_file, 'rb') as f:
|
|
response = client.post("/foods/upload",
|
|
files={"file": ("invalid.csv", f, "text/csv")})
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
# Should handle errors gracefully
|
|
assert "status" in data or "errors" in data
|
|
|
|
|
|
class TestOpenFoodFacts:
|
|
"""Test OpenFoodFacts integration"""
|
|
|
|
def test_add_openfoodfacts_food(self, client):
|
|
"""Test POST /foods/add_openfoodfacts"""
|
|
response = client.post("/foods/add_openfoodfacts", data={
|
|
"name": "OpenFoodFacts Test Food",
|
|
"serving_size": "100",
|
|
"serving_unit": "g",
|
|
"calories": 180.0,
|
|
"protein": 7.0,
|
|
"carbs": 18.0,
|
|
"fat": 4.0,
|
|
"fiber": 2.5,
|
|
"sugar": 3.5,
|
|
"sodium": 90.0,
|
|
"calcium": 40.0,
|
|
"openfoodfacts_id": "12345678",
|
|
"brand": "OFF Brand",
|
|
"categories": "test,food"
|
|
})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
def test_get_openfoodfacts_product(self, client):
|
|
"""Test GET /foods/get_openfoodfacts_product/{barcode}"""
|
|
# Test with a well-known barcode (Nutella)
|
|
response = client.get("/foods/get_openfoodfacts_product/3017620422003")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "status" in data
|
|
|
|
def test_openfoodfacts_by_category(self, client):
|
|
"""Test GET /foods/openfoodfacts_by_category"""
|
|
response = client.get("/foods/openfoodfacts_by_category?category=beverages&limit=5")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "status" in data
|