feat: add vetstation role tests (BP01 Dashboard navigation)
Создана структура тестов для роли 'Ветеринарная станция' по той же
архитектуре что и 01_vetdept.
tests/02_vetstation/
conftest.py — fixtures_dir, shared_state
fixtures/images/.gitkeep — папка для фото артефактов
fixtures/docs/.gitkeep — папка для документов
BP01_dashboard/
test_bp01_dashboard.py — class TestBP01Dashboard (7 шагов)
BP01 покрывает:
s01 — Открыть главную страницу (Статистика)
s02 — Проверить заголовок организации
s03 — Проверить блок статистики регистрации животных
s04 — Проверить таблицу последних зарегистрированных особей
s05 — Перейти в раздел Животные
s06 — Перейти в раздел Владельцы животных (URL с regex: /owners?type=individual)
s07 — Перейти в раздел Единый реестр
Удалён старый CodeGen-тест 002_login_test.py
This commit is contained in:
@ -1,13 +0,0 @@
|
||||
import re
|
||||
from playwright.sync_api import Page, expect
|
||||
|
||||
|
||||
def test_example(page: Page) -> None:
|
||||
page.goto("https://vet.goznak.ru/auth")
|
||||
page.get_by_role("textbox", name="Email").click()
|
||||
page.get_by_role("textbox", name="Email").click()
|
||||
page.get_by_role("textbox", name="Email").fill("gz_vetstation@vet.goznak.ru")
|
||||
page.get_by_role("textbox", name="Введите пароль").click()
|
||||
page.get_by_role("textbox", name="Введите пароль").fill("A6wrpzpD5T")
|
||||
page.get_by_role("button", name="Войти в аккаунт").click()
|
||||
expect(page.locator("#app")).to_match_aria_snapshot("- text: Ветеринарная станция \"ГОЗНАК\" - Демо\n- combobox: /\\d+\\.\\d+\\.\\d+ - \\d+\\.\\d+\\.\\d+/\n- button \"Создать отчет\":\n - img\n - text: \"\"\n- text: Статистика регистрации домашних животных\n- img\n- text: 0 всего особей Всего особей\n- paragraph: \"0\"\n- list:\n - listitem:\n - img\n - text: \"0\"\n - img\n - text: \"0\"\n- text: Из них с биометрией\n- paragraph: \"0\"\n- list:\n - listitem:\n - img\n - text: \"0\"\n - img\n - text: \"0\"\n- text: Динамика регистраций в ветстанции\n- img\n- text: Последние зарегистрированные особи\n- button \"Перейти к списку\"\n- table:\n - rowgroup:\n - row \"ID особи Дата № регистрации Тип маркировки № маркировки Кличка Тип владелеца\":\n - columnheader \"ID особи\"\n - columnheader \"Дата\"\n - columnheader \"№ регистрации\"\n - columnheader \"Тип маркировки\"\n - columnheader \"№ маркировки\"\n - columnheader \"Кличка\"\n - columnheader \"Тип владелеца\"\n - columnheader\n - rowgroup:\n - row /homeless \\d+ \\d+\\.\\d+\\.\\d+ \\d+ С \\d+ \\d+ \\d+ Нет информации о маркировке Без номера Кличко Юридическое лицо/:\n - cell /homeless \\d+/:\n - img \"homeless\"\n - img\n - img\n - text: \"\"\n - cell /\\d+\\.\\d+\\.\\d+/\n - cell /\\d+ С \\d+ \\d+ \\d+/\n - cell \"Нет информации о маркировке\"\n - cell \"Без номера\"\n - cell \"Кличко\"\n - cell \"Юридическое лицо\"\n - cell:\n - button:\n - img\n - row /homeless \\d+ \\d+\\.\\d+\\.\\d+ \\d+ К \\d+ \\d+ \\d+ Нет информации о маркировке Без номера Звезда Юридическое лицо/:\n - cell /homeless \\d+/:\n - img \"homeless\"\n - img\n - img\n - text: \"\"\n - cell /\\d+\\.\\d+\\.\\d+/\n - cell /\\d+ К \\d+ \\d+ \\d+/\n - cell \"Нет информации о маркировке\"\n - cell \"Без номера\"\n - cell \"Звезда\"\n - cell \"Юридическое лицо\"\n - cell:\n - button:\n - img\n - row /homeless \\d+ \\d+\\.\\d+\\.\\d+ \\d+ К \\d+ \\d+ \\d+ Клеймо К-\\d+ Симба Физическое лицо/:\n - cell /homeless \\d+/:\n - img \"homeless\"\n - img\n - img\n - text: \"\"\n - cell /\\d+\\.\\d+\\.\\d+/\n - cell /\\d+ К \\d+ \\d+ \\d+/\n - cell \"Клеймо\"\n - cell /К-\\d+/\n - cell \"Симба\"\n - cell \"Физическое лицо\"\n - cell:\n - button:\n - img\n - row /homeless \\d+ \\d+\\.\\d+\\.\\d+ \\d+ С \\d+ \\d+ \\d+ Микрочип Ч-\\d+ Жорик Юридическое лицо/:\n - cell /homeless \\d+/:\n - img \"homeless\"\n - img\n - img\n - text: \"\"\n - cell /\\d+\\.\\d+\\.\\d+/\n - cell /\\d+ С \\d+ \\d+ \\d+/\n - cell \"Микрочип\"\n - cell /Ч-\\d+/\n - cell \"Жорик\"\n - cell \"Юридическое лицо\"\n - cell:\n - button:\n - img\n - row /homeless \\d+ \\d+\\.\\d+\\.\\d+ \\d+ С \\d+ \\d+ \\d+ Нет информации о маркировке Без номера Дружок Физическое лицо/:\n - cell /homeless \\d+/:\n - img \"homeless\"\n - img\n - img\n - text: \"\"\n - cell /\\d+\\.\\d+\\.\\d+/\n - cell /\\d+ С \\d+ \\d+ \\d+/\n - cell \"Нет информации о маркировке\"\n - cell \"Без номера\"\n - cell \"Дружок\"\n - cell \"Физическое лицо\"\n - cell:\n - button:\n - img")
|
||||
1
tests/02_vetstation/BP01_dashboard/__init__.py
Normal file
1
tests/02_vetstation/BP01_dashboard/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# BP01: Навигация по разделам ЛК ветеринарной станции
|
||||
85
tests/02_vetstation/BP01_dashboard/test_bp01_dashboard.py
Normal file
85
tests/02_vetstation/BP01_dashboard/test_bp01_dashboard.py
Normal file
@ -0,0 +1,85 @@
|
||||
import os
|
||||
# pyrefly: ignore [missing-import]
|
||||
import pytest
|
||||
# pyrefly: ignore [missing-import]
|
||||
from playwright.sync_api import Page, expect
|
||||
|
||||
BASE_URL = os.getenv("BASE_URL", "https://vet.goznak.ru")
|
||||
|
||||
|
||||
@pytest.mark.vetstation
|
||||
@pytest.mark.usefixtures("browser_page")
|
||||
class TestBP01Dashboard:
|
||||
"""
|
||||
BP01: Навигация по разделам личного кабинета ветеринарной станции
|
||||
|
||||
Проверяет что пользователь с ролью 'Ветеринарная станция' может:
|
||||
- Открыть главную страницу (Статистика/Dashboard)
|
||||
- Видеть заголовок своей организации
|
||||
- Видеть блок статистики регистрации животных
|
||||
- Видеть таблицу последних зарегистрированных особей
|
||||
- Перейти в раздел Животные
|
||||
- Перейти в раздел Владельцы животных
|
||||
- Перейти в раздел Единый реестр
|
||||
"""
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s01")
|
||||
def test_s01_open_dashboard(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 1: Открыть главную страницу (Статистика)"""
|
||||
browser_page.goto(BASE_URL + "/dashboard")
|
||||
expect(browser_page).to_have_url(BASE_URL + "/dashboard")
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s02", depends=["VSBP01::s01"])
|
||||
def test_s02_check_org_header(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 2: Проверить заголовок организации"""
|
||||
expect(browser_page.locator("#app")).to_contain_text(
|
||||
"Ветеринарная станция"
|
||||
)
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s03", depends=["VSBP01::s02"])
|
||||
def test_s03_check_stats_block(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 3: Проверить блок статистики регистрации животных"""
|
||||
expect(
|
||||
browser_page.get_by_text("Статистика регистрации домашних животных")
|
||||
).to_be_visible(timeout=10000)
|
||||
expect(
|
||||
browser_page.get_by_text("Всего особей").first
|
||||
).to_be_visible(timeout=10000)
|
||||
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s04", depends=["VSBP01::s03"])
|
||||
def test_s04_check_animals_table(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 4: Проверить таблицу последних зарегистрированных особей"""
|
||||
expect(
|
||||
browser_page.get_by_text("Последние зарегистрированные особи")
|
||||
).to_be_visible(timeout=10000)
|
||||
# Проверяем наличие колонок таблицы
|
||||
expect(browser_page.get_by_role("columnheader", name="Кличка")).to_be_visible()
|
||||
expect(browser_page.get_by_role("columnheader", name="Дата")).to_be_visible()
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s05", depends=["VSBP01::s04"])
|
||||
def test_s05_go_to_animals(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 5: Перейти в раздел Животные"""
|
||||
browser_page.get_by_role("link", name="Животные").click()
|
||||
expect(browser_page).to_have_url(BASE_URL + "/animals", timeout=10000)
|
||||
expect(browser_page.locator("#app")).to_be_visible(timeout=10000)
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s06", depends=["VSBP01::s05"])
|
||||
def test_s06_go_to_owners(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 6: Перейти в раздел Владельцы животных"""
|
||||
import re
|
||||
browser_page.get_by_role("link", name="Владельцы животных").click()
|
||||
# Страница открывается с query-параметром (?type=individual), поэтому regex
|
||||
expect(browser_page).to_have_url(
|
||||
re.compile(r".*/owners.*"), timeout=10000
|
||||
)
|
||||
expect(browser_page.locator("#app")).to_be_visible(timeout=10000)
|
||||
|
||||
|
||||
|
||||
@pytest.mark.dependency(name="VSBP01::s07", depends=["VSBP01::s06"])
|
||||
def test_s07_go_to_registry(self, browser_page: Page, bp_state: dict):
|
||||
"""Шаг 7: Перейти в раздел Единый реестр"""
|
||||
browser_page.get_by_role("link", name="Единый реестр").click()
|
||||
expect(browser_page).to_have_url(BASE_URL + "/registry", timeout=10000)
|
||||
expect(browser_page.locator("#app")).to_be_visible(timeout=10000)
|
||||
47
tests/02_vetstation/conftest.py
Normal file
47
tests/02_vetstation/conftest.py
Normal file
@ -0,0 +1,47 @@
|
||||
# pyrefly: ignore [missing-import]
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Пути к статическим артефактам роли (фото, документы, файлы)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def fixtures_dir() -> Path:
|
||||
"""
|
||||
Путь к папке со статическими артефактами роли vetstation.
|
||||
Структура папки:
|
||||
fixtures/
|
||||
├── images/ ← фотографии животных, документы-сканы
|
||||
└── docs/ ← PDF, сертификаты и прочие документы
|
||||
"""
|
||||
return Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Готовые фикстуры для конкретных артефактов
|
||||
# Добавляй новые по мере появления новых файлов в папке fixtures/
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# @pytest.fixture(scope="session")
|
||||
# def animal_photo(fixtures_dir) -> Path:
|
||||
# """Фото животного для теста регистрации."""
|
||||
# return fixtures_dir / "images" / "animal_photo.jpg"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Контейнер для передачи данных между разными БП одной роли (scope=session)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def shared_state() -> dict:
|
||||
"""
|
||||
Словарь для передачи данных между разными бизнес-процессами
|
||||
в рамках одной тестовой сессии для роли vetstation.
|
||||
|
||||
Пример:
|
||||
# В BP02 создаём животное → BP03 проверяет его в реестре
|
||||
shared_state["animal_id"] = "96416"
|
||||
"""
|
||||
return {}
|
||||
1
tests/02_vetstation/fixtures/docs/.gitkeep
Normal file
1
tests/02_vetstation/fixtures/docs/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
# PDF, сертификаты, ветпаспорта для роли vetstation
|
||||
1
tests/02_vetstation/fixtures/images/.gitkeep
Normal file
1
tests/02_vetstation/fixtures/images/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
# Фотографии животных и документы-сканы для роли vetstation
|
||||
1
tests/testdata/generators.py
vendored
1
tests/testdata/generators.py
vendored
@ -61,6 +61,7 @@
|
||||
import random
|
||||
import string
|
||||
from datetime import date, timedelta
|
||||
# pyrefly: ignore [missing-import]
|
||||
from faker import Faker
|
||||
|
||||
# Единственный экземпляр Faker на весь модуль — не создавай новые в функциях
|
||||
|
||||
Reference in New Issue
Block a user