Files
site/WESP_REL/tests/test_lab_ui_contract.py
2026-07-17 12:57:18 +03:00

142 lines
6.1 KiB
Python

"""UI-контракт модуля lab: скрипты, API paths, K-hub."""
from __future__ import annotations
import unittest
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
ZOOTECH_PAGES_WITH_LAB_PANEL = (
"static/reports.html",
"static/components.html",
"static/feed_dispensers.html",
"static/consumption.html",
)
class LabUiContractTests(unittest.TestCase):
def _read(self, rel: str) -> str:
return (PROJECT_ROOT / rel).read_text(encoding="utf-8")
def test_zootech_pages_include_lab_master_panel(self) -> None:
for page in ZOOTECH_PAGES_WITH_LAB_PANEL:
with self.subTest(page=page):
html = self._read(page)
self.assertIn("lab-master-panel.js", html)
self.assertIn("lab-animal-profiles-modal.js", html)
def test_recipes_page_without_lab_integration(self) -> None:
"""Рецепты — отдельно от /lab; зоотехника только на lab.html."""
html = self._read("static/recipes.html")
self.assertNotIn("lab-recipes-overlay.js", html)
self.assertNotIn("lab-recipes-plan-overlay.js", html)
self.assertNotIn("lab-master-panel.js", html)
def test_components_page_lab_nutrients_ui(self) -> None:
html = self._read("static/components.html")
self.assertIn("lab-components-nutrients.js", html)
self.assertIn("labNutrientsCreateMount", html)
self.assertIn("labAgrostarDrop", html)
self.assertIn("component-add-agrostar__head", html)
self.assertIn("lab-agrostar-import.js", html)
self.assertIn("component-add-save-btn", html)
self.assertIn("componentAddSaveBtnTop", html)
self.assertNotIn('id="protein"', html)
self.assertNotIn('id="energy"', html)
self.assertIn("component-form-row--primary", html)
js = self._read("static/js/pages/lab-components-nutrients.js")
self.assertIn("renderCardInfoHtml", js)
self.assertIn("NUTRIENT_ROWS", js)
self.assertIn("LAB_INPUT_ROWS", js)
self.assertIn("EXTRA_LAB_ROWS", js)
self.assertIn("lab-nutrients-row--extra", js)
self.assertIn("externalNo", html)
self.assertNotIn("toggle-nutrients", js)
self.assertNotIn(".includes(target)", js)
self.assertNotIn("FUTTERPLUS", js)
self.assertNotIn('"СВ"', js.split("LAB_INPUT_ROWS")[1].split("];")[0])
def test_lab_sandbox_page(self) -> None:
html = self._read("static/lab.html")
js = self._read("static/js/pages/lab-sandbox.js")
prime_js = self._read("static/js/pages/lab-heisenberg-prime.js")
self.assertIn("lab-sandbox.js", html)
self.assertIn("lab-heisenberg-prime.js", html)
self.assertIn("labSandboxRecipe", html)
self.assertIn("/api/lab/rations/", js)
self.assertIn("/api/lab/recipes", js)
self.assertIn("recalculate", js)
self.assertIn("WespLabHeisenbergPrime", prime_js)
self.assertIn("function error", prime_js)
self.assertIn("lab-heisenberg-prime-active", self._read("static/css/wesp-lab-sandbox.css"))
lab_css = self._read("static/css/wesp-lab-sandbox.css")
self.assertIn("body.zootech-app-body.lab-sandbox-page", lab_css)
self.assertIn("lab-heisenberg-bg.jpg", lab_css)
def test_lab_formulate_page(self) -> None:
html = self._read("static/lab.html")
js = self._read("static/js/pages/lab-formulate.js")
self.assertIn("lab-formulate.js", html)
self.assertIn("labFormulateRun", html)
self.assertIn("labFormulateSteps", html)
self.assertIn("labFormulatePanes", html)
self.assertIn("/api/lab/formulate", js)
self.assertIn("/api/lab/norms-preview", js)
self.assertIn("labFormulateNormsMethod", html)
self.assertIn("groupSelections", js)
self.assertIn("/api/lab/formulate/components", js)
self.assertIn("labFormulateRun", js)
def test_components_main_feed_field(self) -> None:
js = self._read("static/js/pages/lab-components-nutrients.js")
self.assertIn("Осн.Корм", js)
self.assertIn("Осн. корм", js)
def test_lab_master_panel_api_paths(self) -> None:
js = self._read("static/js/pages/lab-master-panel.js")
for path in (
"/api/lab/rations/",
"/api/lab/recipes",
"/api/lab/animal-profiles",
"/api/components",
"lab-recalculate",
"lab-save",
"lab-add-line",
"lab-print-ration",
):
self.assertIn(path, js)
def test_lab_recipes_overlay_api_paths(self) -> None:
js = self._read("static/js/pages/lab-recipes-overlay.js")
self.assertIn("/api/lab/rations/", js)
self.assertIn("apply-from-master", js)
self.assertIn("sync-to-master", js)
self.assertIn("open-lab-k-hub", js)
self.assertIn("rationType", js)
self.assertIn("labRecipeQuality", js)
def test_lab_plan_overlay_daily_plan_api(self) -> None:
js = self._read("static/js/pages/lab-recipes-plan-overlay.js")
self.assertIn("/api/daily-plan/skips/ingredients", js)
self.assertIn("/api/daily-plan/replacements/ingredients", js)
self.assertIn("recipe-plan-skip-ingredient", js)
def test_k_hub_uses_daily_plan_not_lab_master(self) -> None:
center = self._read("static/js/wesp-zootech-notification-center.js")
self.assertIn("WespDailyPlanPanel", center)
self.assertNotIn("WespLabMasterPanel", center)
self.assertNotIn("k-hub-open-animal-profiles", center)
def test_lab_profiles_page_exists(self) -> None:
html = self._read("static/lab-profiles.html")
self.assertIn("lab-profiles.js", html)
js = self._read("static/js/pages/lab-profiles.js")
self.assertIn("/api/lab/animal-profiles", js)
self.assertIn("labProfilesDelete", html)
self.assertIn('method: "DELETE"', js)
self.assertIn("labProfilesSourceFilter", html)
self.assertIn("labProfilesNormsSummary", html)
self.assertIn("/api/lab/norms-preview", js)
self.assertIn("buildNormSourceMap", js)