Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
@@ -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()