diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..d84560f --- /dev/null +++ b/pytest.ini @@ -0,0 +1,10 @@ +[pytest] +addopts = --browser chromium --headed --slowmo 1000 +html_report_dir = html-report +testpaths = tests +markers = + vetdept: тесты для роли Управление ветеринарии + vetstation: тесты для роли Ветеринарная станци + prefecture: тесты для роли Администрация + contractor_admin: тесты для роли Администратор организации отлова + smoke: критически важные тесты для быстрого прогона \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fc63313 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +playwright +pytest +pytest-playwright +pytest-xdist +pytest-html==3.2.0 \ No newline at end of file diff --git a/tests/01_vetdept/001_login_test.py b/tests/01_vetdept/001_login_test.py new file mode 100644 index 0000000..eeddb47 --- /dev/null +++ b/tests/01_vetdept/001_login_test.py @@ -0,0 +1,53 @@ +import pytest +from playwright.sync_api import Page, expect + + +@pytest.mark.vetdept +def test_dashboard(role_page: Page): + print("\n[TEST] ТЕСТ: Проверка навигации по разделам портала") + print("=" * 60) + + # Шаг 1 + print("\n[1/6] Переход на главную страницу (Dashboard)...") + role_page.goto("https://vet.goznak.ru/dashboard") + print(" [OK] Страница загружена") + + # Шаг 2 + print("[2/6] Проверка URL главной страницы...") + expect(role_page).to_have_url("https://vet.goznak.ru/dashboard") + print(" [OK] URL соответствует ожидаемому") + + # Шаг 3 + print("[3/6] Проверка заголовка организации...") + expect(role_page.locator("#app")).to_contain_text("Управление Ветеринарии Гознак") + print(" [OK] Заголовок 'Управление Ветеринарии Гознак' найден") + + # Шаг 4 + print("[4/6] Переход в раздел 'Организации'...") + role_page.get_by_role("link", name="Организации").click() + print(" [OK] Клик выполнен, ожидание перехода...") + + print(" Проверка URL раздела 'Организации'...") + expect(role_page).to_have_url("https://vet.goznak.ru/organizations", timeout=10000) + print(" [OK] URL раздела верный") + + print(" Проверка заголовка страницы...") + expect(role_page.get_by_text("Подведомственные организации")).to_be_visible(timeout=10000) + print(" [OK] Заголовок 'Подведомственные организации' найден") + + # Шаг 5 + print("[5/6] Переход в раздел 'Заявки на отлов'...") + role_page.get_by_role("link", name="Заявки на отлов").click() + print(" [OK] Клик выполнен, ожидание перехода...") + + # Шаг 6 + print("[6/6] Проверка страницы 'Заявки на отлов'...") + expect(role_page).to_have_url("https://vet.goznak.ru/claims-list", timeout=10000) + print(" [OK] URL раздела верный") + + expect(role_page.get_by_text("Мои заявки")).to_be_visible(timeout=10000) + print(" [OK] Заголовок 'Мои заявки' найден") + + print("\n" + "=" * 60) + print("🎉 ВСЕ ПРОВЕРКИ ПРОЙДЕНУ УСПЕШНО!") + print("=" * 60) \ No newline at end of file diff --git a/tests/01_vetdept/__init__.py b/tests/01_vetdept/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/02_vetstation/002_login_test.py b/tests/02_vetstation/002_login_test.py new file mode 100644 index 0000000..ef3e91c --- /dev/null +++ b/tests/02_vetstation/002_login_test.py @@ -0,0 +1,13 @@ +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") diff --git a/tests/02_vetstation/__init__.py b/tests/02_vetstation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0701195 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,41 @@ +import pytest +from playwright.sync_api import Page + +# Словарь с учетными данными для разных ролей +CREDENTIALS = { + "vetdept": {"login": "gz_vetdept@vet.goznak.ru", "password": "y2pyBAn7zw"}, + "vetstation": {"login": "gz_vetstation@vet.goznak.ru", "password": "A6wrpzpD5T"}, + "prefecture": {"login": "gz_prefecture@vet.goznak.ru", "password": "sbT9shGsbe"}, +} + +@pytest.fixture(scope="function") +def role_page(page: Page, request): + """ + Фикстура, которая определяет роль теста и автоматически авторизует пользователя. + """ + # 2. Выполняем логин + role = None + + for marker in request.node.iter_markers(): + if marker.name in CREDENTIALS: + role = marker.name + break + + # 3. Если маркер не найден, честно говорим об этом (вместо молчаливого NameError) + if role is None: + pytest.fail("ОШИБКА: У теста нет маркера роли (например, @pytest.mark.vetstation)!") + + print(f"\n[АВТОЛОГИН] Выполняется вход под ролью: {role}") + + page.goto("https://vet.goznak.ru") + creds = CREDENTIALS[role] + + page.get_by_role("textbox", name="Email").fill(creds["login"]) + page.get_by_role("textbox", name="Введите пароль").fill(creds["password"]) + page.get_by_role("button", name="Войти в аккаунт").click() + + page.wait_for_selector("#app", timeout=10000) + + yield page + + page.context.clear_cookies() \ No newline at end of file