211 lines
9.4 KiB
Python
211 lines
9.4 KiB
Python
"""Инвентарь UI страницы /recipes — источник правды для контракт- и E2E-тестов."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Dict, List, Tuple
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
|
|
STATIC = PROJECT_ROOT / "static"
|
|
|
|
# Ключевые DOM id (dashboard + editor + mobile)
|
|
DOM_IDS: List[str] = [
|
|
"wespZootechNavMount",
|
|
"recipesMobileNav",
|
|
"recipesMobileNavTitle",
|
|
"recipesDashboard",
|
|
"dispensersCol",
|
|
"periodsCol",
|
|
"recipesCol",
|
|
"dispensersList",
|
|
"periodsList",
|
|
"recipesList",
|
|
"recipesCardHeaderText",
|
|
"createRecipeBtn",
|
|
"recipeEdit",
|
|
"recipeEditSkeletonPanel",
|
|
"recipeForm",
|
|
"recipeName",
|
|
"headsCount",
|
|
"mixingTime",
|
|
"tripPercent",
|
|
"ingredientsTable",
|
|
"ingredientsTableBody",
|
|
"unloadingGroupsCard",
|
|
"unloadingGroupsTableBody",
|
|
"componentSelectionCard",
|
|
"targetComponentSelect",
|
|
"ingredientMobileSheet",
|
|
"unloadingGroupMobileSheet",
|
|
"recipeHelpModal",
|
|
]
|
|
|
|
# data-action → файл(ы), где должен быть handler
|
|
DATA_ACTION_HANDLERS: Dict[str, List[str]] = {
|
|
"mobile-dashboard-back": ["static/js/pages/recipes-page.js"],
|
|
"open-recipe-help": ["static/js/pages/recipes-page.js"],
|
|
"close-recipe-help": ["static/js/pages/recipes-page.js"],
|
|
"logout": ["static/js/pages/recipes-page.js", "static/js/wesp-zootech-nav.js"],
|
|
"add-ingredient": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"toggle-unloading-link": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"add-unloading-group": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"show-recipe-edit-off": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"print-all-recipes": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"print-recipe": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"save-and-exit": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"move-group-up": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"move-group-down": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"remove-unloading-group": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"move-ingredient-up": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"move-ingredient-down": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"remove-ingredient": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"open-ingredient-sheet": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"close-ingredient-sheet": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"open-unloading-group-sheet": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"close-unloading-group-sheet": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"group-type-change": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"group-value-change": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"ingredient-change": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"dry-matter-percent-change": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"recalculate-weights": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"recalculate-total-weight": ["static/js/modules/recipes/recipe-editor.js"],
|
|
"select-dispenser": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"select-recipe": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"select-period": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"copy-recipe": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"delete-recipe": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"unskip-recipe-today": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"unskip-ingredient-parts-today": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"unskip-group-parts-today": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"paste-recipe": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"create-recipe": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"move-recipe-up": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"move-recipe-down": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"recipe-drag-handle": ["static/js/modules/recipes/dispenser-selector.js"],
|
|
"open-settings": ["static/js/modules/recipes/sync-panel.js", "static/js/wesp-zootech-nav.js"],
|
|
"close-settings": ["static/js/modules/recipes/sync-panel.js"],
|
|
"toggle-credentials-form": ["static/js/modules/recipes/sync-panel.js"],
|
|
"toggle-sync-form": ["static/js/modules/recipes/sync-panel.js"],
|
|
"change-credentials": ["static/js/modules/recipes/sync-panel.js"],
|
|
"sync-edit-client": ["static/js/modules/recipes/sync-panel.js"],
|
|
"sync-delete-client": ["static/js/modules/recipes/sync-panel.js"],
|
|
"sync-save-client": ["static/js/modules/recipes/sync-panel.js"],
|
|
"sync-cancel-edit": ["static/js/modules/recipes/sync-panel.js"],
|
|
}
|
|
|
|
# data-action → уровень теста, который должен покрывать action (e2e | api | contract)
|
|
ACTION_COVERAGE_TARGET: Dict[str, str] = {
|
|
"mobile-dashboard-back": "e2e",
|
|
"open-recipe-help": "e2e",
|
|
"close-recipe-help": "e2e",
|
|
"logout": "e2e",
|
|
"add-ingredient": "e2e",
|
|
"toggle-unloading-link": "e2e",
|
|
"add-unloading-group": "contract",
|
|
"show-recipe-edit-off": "contract",
|
|
"print-all-recipes": "e2e",
|
|
"print-recipe": "e2e",
|
|
"save-and-exit": "e2e",
|
|
"move-group-up": "api",
|
|
"move-group-down": "api",
|
|
"remove-unloading-group": "contract",
|
|
"move-ingredient-up": "api",
|
|
"move-ingredient-down": "api",
|
|
"remove-ingredient": "e2e",
|
|
"open-ingredient-sheet": "e2e",
|
|
"close-ingredient-sheet": "e2e",
|
|
"open-unloading-group-sheet": "contract",
|
|
"close-unloading-group-sheet": "contract",
|
|
"group-type-change": "e2e",
|
|
"group-value-change": "contract",
|
|
"ingredient-change": "contract",
|
|
"dry-matter-percent-change": "e2e",
|
|
"recalculate-weights": "contract",
|
|
"recalculate-total-weight": "contract",
|
|
"select-dispenser": "e2e",
|
|
"select-recipe": "e2e",
|
|
"select-period": "e2e",
|
|
"copy-recipe": "e2e",
|
|
"delete-recipe": "e2e",
|
|
"unskip-recipe-today": "api",
|
|
"unskip-ingredient-parts-today": "api",
|
|
"unskip-group-parts-today": "api",
|
|
"paste-recipe": "e2e",
|
|
"create-recipe": "e2e",
|
|
"move-recipe-up": "e2e",
|
|
"move-recipe-down": "e2e",
|
|
"recipe-drag-handle": "e2e",
|
|
"open-settings": "e2e",
|
|
"close-settings": "e2e",
|
|
"toggle-credentials-form": "e2e",
|
|
"toggle-sync-form": "e2e",
|
|
"change-credentials": "contract",
|
|
"sync-edit-client": "contract",
|
|
"sync-delete-client": "contract",
|
|
"sync-save-client": "contract",
|
|
"sync-cancel-edit": "contract",
|
|
}
|
|
|
|
# fetch URL patterns в JS страницы рецептов
|
|
API_ENDPOINTS: List[Tuple[str, List[str]]] = [
|
|
("/api/feed_dispensers", ["static/js/pages/recipes-data-controller.js"]),
|
|
("/api/feed_dispensers/", ["static/js/pages/recipes-data-controller.js", "static/js/pages/recipes-operations-controller.js"]),
|
|
("/api/periods/", ["static/js/pages/recipes-data-controller.js", "static/js/pages/recipes-operations-controller.js"]),
|
|
("/api/recipes/calculate", ["static/recipes.html"]),
|
|
("/api/recipes/", ["static/recipes.html", "static/js/pages/recipes-operations-controller.js", "static/js/pages/recipes-editor-controller.js"]),
|
|
("/api/auth/check", ["static/recipes.html", "static/js/pages/recipes-auth-settings.js"]),
|
|
("/api/auth/logout", ["static/js/pages/recipes-auth-settings.js"]),
|
|
("/api/auth/change_credentials", ["static/js/pages/recipes-auth-settings.js"]),
|
|
("/api/sync/clients", ["static/js/pages/recipes-auth-settings.js"]),
|
|
]
|
|
|
|
# CSS анимации / transition-классы
|
|
CSS_ANIMATION_MARKERS: List[Tuple[str, List[str]]] = [
|
|
("dashboard-skeleton-shimmer", ["static/css/wesp-recipes-skeleton.css"]),
|
|
("dashboard-list-skeleton--exit", ["static/css/wesp-recipes-skeleton.css"]),
|
|
("recipe-form--enter", ["static/css/wesp-recipes-editor.css", "static/recipes.html"]),
|
|
("dashboard-mobile-step-", ["static/css/wesp-recipes-mobile.css", "static/js/pages/recipes-data-controller.js"]),
|
|
]
|
|
|
|
# Скелетон-templates
|
|
SKELETON_TEMPLATE_IDS: List[str] = [
|
|
"recipe-card-skeleton-inner",
|
|
"recipe-card-skeleton-inner--mill",
|
|
"dashboard-list-skeleton-dispensers",
|
|
"dashboard-list-skeleton-periods",
|
|
]
|
|
|
|
# Mill-ветки в JS/HTML
|
|
MILL_MARKERS: List[Tuple[str, List[str]]] = [
|
|
("loadMillRecipes", ["static/js/pages/recipes-data-controller.js"]),
|
|
("getCurrentDispenserType() === \"mill\"", [
|
|
"static/js/pages/recipes-data-controller.js",
|
|
"static/js/pages/recipes-operations-controller.js",
|
|
"static/js/pages/recipes-editor-controller.js",
|
|
]),
|
|
("deleted_ingredient_ids", ["static/recipes.html"]),
|
|
("deleted_unloading_group_ids", ["static/recipes.html"]),
|
|
("target_component_id", ["static/recipes.html", "static/js/pages/recipes-editor-controller.js"]),
|
|
("unlinkFromPeriodOnly", ["static/js/pages/recipes-operations-controller.js"]),
|
|
]
|
|
|
|
# Скрипты, импортируемые из recipes.html (type=module)
|
|
RECIPES_PAGE_SCRIPTS: List[str] = [
|
|
"recipes-boot.js",
|
|
"recipes-page.js",
|
|
"recipes-data-controller.js",
|
|
"recipes-operations-controller.js",
|
|
"recipes-editor-controller.js",
|
|
"recipes-auth-settings.js",
|
|
"recipe-list-dnd.js",
|
|
"recipe-period-transfer.js",
|
|
"recipe-mobile-sheet-gestures.js",
|
|
]
|
|
|
|
# Модули, подключаемые через recipes-page.js
|
|
RECIPES_PAGE_NESTED_MODULES: List[str] = [
|
|
"recipe-editor.js",
|
|
"dispenser-selector.js",
|
|
"sync-panel.js",
|
|
]
|