From 81b2ec41fa90f8db607d44051015574b3991d071 Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 12 Aug 2025 14:45:59 +0300 Subject: [PATCH] ci-tests-frontend-e2e-fix --- .gitea/workflows/main.yml | 9 -- tests/auth/conftest.py | 3 +- tests/auth/test_settings.py | 2 - tests/check_communities_table.py | 4 +- tests/conftest.py | 13 +++ tests/test_community_delete_e2e_browser.py | 107 ++++++++++++--------- tests/test_delete_button_debug.py | 10 +- tests/test_login_debug.py | 6 +- 8 files changed, 88 insertions(+), 66 deletions(-) diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml index 9b790248..a2e6c272 100644 --- a/.gitea/workflows/main.yml +++ b/.gitea/workflows/main.yml @@ -41,15 +41,6 @@ jobs: run: | npm run build - - name: Start Frontend Server - run: | - # Запускаем фронтенд сервер в фоне - npm run dev & - # Ждем запуска сервера - sleep 10 - # Проверяем что сервер запустился - curl -f http://localhost:3000 || exit 1 - - name: Setup Playwright (use pre-installed browsers) env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 diff --git a/tests/auth/conftest.py b/tests/auth/conftest.py index f647b4cc..deca76f0 100644 --- a/tests/auth/conftest.py +++ b/tests/auth/conftest.py @@ -1,5 +1,6 @@ import pytest +PORT = 8000 @pytest.fixture def oauth_settings() -> dict[str, dict[str, str]]: @@ -14,7 +15,7 @@ def oauth_settings() -> dict[str, dict[str, str]]: @pytest.fixture def frontend_url() -> str: """URL фронтенда для тестов""" - return "https://localhost:3000" + return f"https://localhost:{PORT}" @pytest.fixture(autouse=True) diff --git a/tests/auth/test_settings.py b/tests/auth/test_settings.py index 2361d224..5984dd66 100644 --- a/tests/auth/test_settings.py +++ b/tests/auth/test_settings.py @@ -1,7 +1,5 @@ """Тестовые настройки для OAuth""" -FRONTEND_URL = "https://localhost:3000" - OAUTH_CLIENTS = { "GOOGLE": {"id": "test_google_id", "key": "test_google_secret"}, "GITHUB": {"id": "test_github_id", "key": "test_github_secret"}, diff --git a/tests/check_communities_table.py b/tests/check_communities_table.py index c86f5c74..4e6f15ad 100644 --- a/tests/check_communities_table.py +++ b/tests/check_communities_table.py @@ -20,7 +20,9 @@ async def check_communities_table(): try: # В CI/CD фронтенд обслуживается бэкендом на порту 8000 - frontend_url = "http://localhost:3000" + # В локальной разработке - на порту 3000 + is_ci = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true" + frontend_url = "http://localhost:8000" if is_ci else "http://localhost:3000" print(f"🌐 Открываем админ-панель на {frontend_url}...") await page.goto(frontend_url) await page.wait_for_load_state("networkidle") diff --git a/tests/conftest.py b/tests/conftest.py index 72b1fcb0..b467de1f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,6 @@ import pytest +import os +from settings import FRONTEND_URL from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool @@ -486,3 +488,14 @@ def cleanup_test_data(db_session, user_ids=None, community_ids=None): db_session.query(CommunityAuthor).where(CommunityAuthor.community_id.in_(community_ids)).delete(synchronize_session=False) db_session.commit() + + +@pytest.fixture +def frontend_url() -> str: + """URL фронтенда для тестов""" + # В CI/CD используем порт 8000 (бэкенд), в локальной разработке - порт 3000 + is_ci = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true" + if is_ci: + return "http://localhost:8000" + else: + return FRONTEND_URL diff --git a/tests/test_community_delete_e2e_browser.py b/tests/test_community_delete_e2e_browser.py index 6262361c..410532de 100644 --- a/tests/test_community_delete_e2e_browser.py +++ b/tests/test_community_delete_e2e_browser.py @@ -94,7 +94,7 @@ class TestCommunityDeleteE2EBrowser: # Проверяем фронтенд try: - response = requests.get("http://localhost:3000", timeout=2) + response = requests.get("http://localhost:8000", timeout=2) if response.status_code == 200: print("✅ Фронтенд сервер уже запущен") frontend_running = True @@ -104,45 +104,64 @@ class TestCommunityDeleteE2EBrowser: frontend_running = False if not frontend_running: - # В CI/CD фронтенд сервер запускается в workflow - # В локальной разработке запускаем фронтенд сервер - print("🔄 Запускаем фронтенд сервер...") - try: - frontend_process = subprocess.Popen( - ["npm", "run", "dev"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ) - - # Ждем запуска фронтенда - print("⏳ Ждем запуска фронтенда...") - for i in range(15): # Ждем максимум 15 секунд - try: - response = requests.get("http://localhost:3000", timeout=2) - if response.status_code == 200: - print("✅ Фронтенд сервер запущен") - break - except: - pass - await asyncio.sleep(1) - else: - # Если фронтенд не запустился, выводим логи - print("❌ Фронтенд сервер не запустился за 15 секунд") - - # Получаем логи процесса - if frontend_process: - stdout, stderr = frontend_process.communicate() - print(f"📋 STDOUT: {stdout.decode()}") - print(f"📋 STDERR: {stderr.decode()}") - - print("⚠️ Продолжаем тест без фронтенда (только API тесты)") + # Проверяем, находимся ли мы в CI/CD окружении + is_ci = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true" + + if is_ci: + print("🔧 CI/CD окружение - фронтенд собран и обслуживается бэкендом") + # В CI/CD фронтенд уже собран и обслуживается бэкендом на порту 8000 + try: + response = requests.get("http://localhost:8000/", timeout=2) + if response.status_code == 200: + print("✅ Бэкенд готов обслуживать фронтенд") + frontend_running = True + frontend_process = None + else: + print(f"⚠️ Бэкенд вернул статус {response.status_code}") + frontend_process = None + except Exception as e: + print(f"⚠️ Не удалось проверить бэкенд: {e}") frontend_process = None + else: + # Локальная разработка - запускаем фронтенд сервер + print("🔄 Запускаем фронтенд сервер...") + try: + frontend_process = subprocess.Popen( + ["npm", "run", "dev"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ) - except Exception as e: - print(f"⚠️ Не удалось запустить фронтенд сервер: {e}") - print("🔄 Продолжаем тест без фронтенда (только API тесты)") - frontend_process = None + # Ждем запуска фронтенда + print("⏳ Ждем запуска фронтенда...") + for i in range(15): # Ждем максимум 15 секунд + try: + # В локальной разработке фронтенд работает на порту 3000 + response = requests.get("http://localhost:3000", timeout=2) + if response.status_code == 200: + print("✅ Фронтенд сервер запущен") + break + except: + pass + await asyncio.sleep(1) + else: + # Если фронтенд не запустился, выводим логи + print("❌ Фронтенд сервер не запустился за 15 секунд") + + # Получаем логи процесса + if frontend_process: + stdout, stderr = frontend_process.communicate() + print(f"📋 STDOUT: {stdout.decode()}") + print(f"📋 STDERR: {stderr.decode()}") + + print("⚠️ Продолжаем тест без фронтенда (только API тесты)") + frontend_process = None + + except Exception as e: + print(f"⚠️ Не удалось запустить фронтенд сервер: {e}") + print("🔄 Продолжаем тест без фронтенда (только API тесты)") + frontend_process = None # Запускаем браузер print("🔄 Запускаем браузер...") @@ -223,7 +242,7 @@ class TestCommunityDeleteE2EBrowser: return user - async def test_community_delete_browser_workflow(self, browser_setup, test_users): + async def test_community_delete_browser_workflow(self, browser_setup, test_users, frontend_url): """Полный E2E тест удаления сообщества через браузер""" page = browser_setup["page"] @@ -240,8 +259,6 @@ class TestCommunityDeleteE2EBrowser: try: # 1. Открываем админ-панель - # В CI/CD фронтенд обслуживается бэкендом на порту 8000 - frontend_url = "http://localhost:3000" print(f"🌐 Открываем админ-панель на {frontend_url}...") await page.goto(frontend_url) @@ -591,7 +608,7 @@ class TestCommunityDeleteE2EBrowser: raise - async def test_community_delete_without_permissions_browser(self, browser_setup, test_community_for_browser): + async def test_community_delete_without_permissions_browser(self, browser_setup, test_community_for_browser, frontend_url): """Тест попытки удаления без прав через браузер""" page = browser_setup["page"] @@ -599,7 +616,7 @@ class TestCommunityDeleteE2EBrowser: try: # 1. Открываем админ-панель print("🔄 Открываем админ-панель...") - await page.goto("http://localhost:3000/admin") + await page.goto(f"{frontend_url}/admin") await page.wait_for_load_state("networkidle") # 2. Авторизуемся как обычный пользователь (без прав admin) @@ -675,7 +692,7 @@ class TestCommunityDeleteE2EBrowser: print(f"❌ Ошибка в E2E тесте прав доступа: {e}") raise - async def test_community_delete_ui_validation(self, browser_setup, test_community_for_browser, admin_user_for_browser): + async def test_community_delete_ui_validation(self, browser_setup, test_community_for_browser, admin_user_for_browser, frontend_url): """Тест UI валидации при удалении сообщества""" page = browser_setup["page"] @@ -683,7 +700,7 @@ class TestCommunityDeleteE2EBrowser: try: # 1. Авторизуемся как админ print("🔐 Авторизуемся как админ...") - await page.goto("http://localhost:3000/admin") + await page.goto(f"{frontend_url}/admin") await page.wait_for_load_state("networkidle") import os diff --git a/tests/test_delete_button_debug.py b/tests/test_delete_button_debug.py index 9397c504..b19496cc 100644 --- a/tests/test_delete_button_debug.py +++ b/tests/test_delete_button_debug.py @@ -10,7 +10,7 @@ import os from playwright.async_api import async_playwright -async def test_delete_button(): +async def test_delete_button(frontend_url): async with async_playwright() as p: # Определяем headless режим из переменной окружения headless_mode = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true" @@ -20,8 +20,8 @@ async def test_delete_button(): page = await browser.new_page() try: - print("🌐 Открываем админ-панель...") - await page.goto("http://localhost:3000/login") + print(f"🌐 Открываем админ-панель на {frontend_url}...") + await page.goto(f"{frontend_url}/login") await page.wait_for_load_state("networkidle") print("🔐 Авторизуемся...") @@ -30,11 +30,11 @@ async def test_delete_button(): await page.click('button[type="submit"]') # Ждем авторизации - await page.wait_for_url("http://localhost:3000/admin/**", timeout=10000) + await page.wait_for_url(f"{frontend_url}/admin/**", timeout=10000) print("✅ Авторизация успешна") print("📋 Переходим на страницу сообществ...") - await page.goto("http://localhost:3000/admin/communities") + await page.goto(f"{frontend_url}/admin/communities") await page.wait_for_load_state("networkidle") print("🔍 Ищем таблицу сообществ...") diff --git a/tests/test_login_debug.py b/tests/test_login_debug.py index 85b6c4c8..789deb6b 100644 --- a/tests/test_login_debug.py +++ b/tests/test_login_debug.py @@ -10,7 +10,7 @@ import os from playwright.async_api import async_playwright -async def test_login(): +async def test_login(frontend_url): async with async_playwright() as p: # Определяем headless режим из переменной окружения headless_mode = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true" @@ -25,8 +25,8 @@ async def test_login(): page.on("console", lambda msg: print(f"📝 CONSOLE: {msg.text}")) try: - print("🌐 Открываем страницу входа...") - await page.goto("http://localhost:3000/login") + print(f"🌐 Открываем страницу входа на {frontend_url}...") + await page.goto(f"{frontend_url}/login") await page.wait_for_load_state("networkidle") print("📸 Делаем скриншот страницы входа...")