142 lines
6.1 KiB
Python
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)
|