@@ -0,0 +1,127 @@
|
||||
"""POST /api/recipes/calculate — HTTP-контракт и нормализация ключей."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from app import create_app, db
|
||||
from app.models import Component
|
||||
from config import TestingConfig
|
||||
|
||||
|
||||
class RecipesCalculateApiConfig(TestingConfig):
|
||||
_TMP_DIR = tempfile.mkdtemp(prefix="wesp-calc-api-")
|
||||
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP_DIR, 'calc_test.db')}"
|
||||
SQLALCHEMY_BINDS = {"reports": f"sqlite:///{os.path.join(_TMP_DIR, 'reports_test.db')}"}
|
||||
AUTH_LOGIN = "calc-api-admin"
|
||||
AUTH_PASSWORD = "calc-api-secret"
|
||||
|
||||
|
||||
SCENARIO_CALCULATE_FROM_DRY_MATTER = "CALCULATE_FROM_DRY_MATTER"
|
||||
|
||||
|
||||
class RecipesCalculateApiTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.app = create_app(RecipesCalculateApiConfig)
|
||||
self.client = self.app.test_client()
|
||||
self.ctx = self.app.app_context()
|
||||
self.ctx.push()
|
||||
db.create_all()
|
||||
self.client.post(
|
||||
"/api/auth/login",
|
||||
json={"login": "calc-api-admin", "password": "calc-api-secret"},
|
||||
)
|
||||
self.comp_id = "calc-comp-1"
|
||||
db.session.add(
|
||||
Component(
|
||||
id=self.comp_id,
|
||||
name="Зерно",
|
||||
type="grain",
|
||||
dry_matter=80.0,
|
||||
protein=0.0,
|
||||
energy=0.0,
|
||||
price=0.0,
|
||||
)
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
self.ctx.pop()
|
||||
|
||||
def test_calculate_requires_auth(self) -> None:
|
||||
anon = self.app.test_client()
|
||||
resp = anon.post("/api/recipes/calculate", json={"headsCount": 1})
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
|
||||
def test_calculate_empty_body_400(self) -> None:
|
||||
resp = self.client.post("/api/recipes/calculate")
|
||||
self.assertIn(resp.status_code, (400, 415))
|
||||
|
||||
def test_calculate_camelCase_weight_mode(self) -> None:
|
||||
resp = self.client.post(
|
||||
"/api/recipes/calculate",
|
||||
json={
|
||||
"headsCount": 10,
|
||||
"tripPercent": 100,
|
||||
"ingredients": [
|
||||
{"weightPerHead": 2.0, "dryMatter": 50.0, "componentId": self.comp_id},
|
||||
],
|
||||
"unloadingGroups": [{"distributionType": "percent", "value": 100}],
|
||||
},
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200, resp.get_data(as_text=True))
|
||||
data = resp.get_json()
|
||||
self.assertEqual(data["totals"]["totalTripWeight"], 20.0)
|
||||
self.assertEqual(data["ingredients"][0]["weightPerHead"], "2.00")
|
||||
|
||||
def test_calculate_snake_case_and_component_dm_lookup(self) -> None:
|
||||
resp = self.client.post(
|
||||
"/api/recipes/calculate",
|
||||
json={
|
||||
"heads_count": 5,
|
||||
"trip_percent": 100,
|
||||
"ingredients": [
|
||||
{"weight_per_head": 1.0, "dry_matter": 0, "component_id": self.comp_id},
|
||||
],
|
||||
},
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
ing = resp.get_json()["ingredients"][0]
|
||||
self.assertEqual(ing["dryMatterPerHead"], 0.8)
|
||||
|
||||
def test_calculate_from_dry_matter_flag(self) -> None:
|
||||
resp = self.client.post(
|
||||
"/api/recipes/calculate",
|
||||
json={
|
||||
"headsCount": 10,
|
||||
"tripPercent": 100,
|
||||
"calculateFromDryMatter": True,
|
||||
"ingredients": [
|
||||
{"dryMatterPerHead": 1.0, "dryMatter": 50.0},
|
||||
],
|
||||
},
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.get_json()["ingredients"][0]["weightPerHead"], "2.00")
|
||||
|
||||
def test_calculate_heads_unloading_groups(self) -> None:
|
||||
resp = self.client.post(
|
||||
"/api/recipes/calculate",
|
||||
json={
|
||||
"headsCount": 100,
|
||||
"tripPercent": 100,
|
||||
"ingredients": [{"weightPerHead": 10.0, "dryMatter": 50.0}],
|
||||
"unloading_groups": [{"distribution_type": "heads", "value": 25}],
|
||||
},
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
groups = resp.get_json()["unloadingGroups"]
|
||||
self.assertEqual(groups[0]["calculatedWeight"], 250)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user