#!/usr/bin/env python3 """ Тест для отладки поиска кнопки удаления """ import asyncio import time import os import requests from playwright.async_api import async_playwright async def wait_for_server_ready(url: str, timeout: int = 60) -> bool: """Ждем готовности сервера""" start_time = time.time() while time.time() - start_time < timeout: try: response = requests.get(url, timeout=5) if response.status_code == 200: return True except: pass await asyncio.sleep(2) return False async def test_delete_button(frontend_url): """Тест поиска кнопки удаления с улучшенной обработкой ошибок""" # Проверяем готовность фронтенда print(f"🌐 Проверяем готовность фронтенда {frontend_url}...") if not await wait_for_server_ready(frontend_url): print(f"❌ Фронтенд {frontend_url} не готов в течение 60 секунд") return False print(f"✅ Фронтенд {frontend_url} готов") async with async_playwright() as p: # Определяем headless режим из переменной окружения headless_mode = os.getenv("PLAYWRIGHT_HEADLESS", "true").lower() == "true" print(f"🔧 Headless режим: {headless_mode}") browser = await p.chromium.launch( headless=headless_mode, args=['--no-sandbox', '--disable-dev-shm-usage'] ) page = await browser.new_page() # Увеличиваем таймауты для CI page.set_default_timeout(30000) # 30 секунд page.set_default_navigation_timeout(30000) try: print(f"🌐 Открываем админ-панель на {frontend_url}...") await page.goto(f"{frontend_url}/login", wait_until="networkidle") print("✅ Страница логина загружена") print("🔐 Авторизуемся...") # Ждем появления полей ввода await page.wait_for_selector('input[type="email"]', timeout=15000) await page.wait_for_selector('input[type="password"]', timeout=15000) await page.fill('input[type="email"]', "test_admin@discours.io") await page.fill('input[type="password"]', "password123") await page.click('button[type="submit"]') # Ждем авторизации с увеличенным таймаутом await page.wait_for_url(f"{frontend_url}/admin/**", timeout=20000) print("✅ Авторизация успешна") print("📋 Переходим на страницу сообществ...") await page.goto(f"{frontend_url}/admin/communities", wait_until="networkidle") print("✅ Страница сообществ загружена") print("🔍 Ищем таблицу сообществ...") await page.wait_for_selector("table", timeout=15000) await page.wait_for_selector("table tbody tr", timeout=15000) print("✅ Таблица сообществ найдена") # Создаем папку для скриншотов если её нет os.makedirs("test-results", exist_ok=True) print("📸 Делаем скриншот таблицы...") await page.screenshot(path="test-results/communities_table_debug.png") # Получаем информацию о всех строках таблицы table_info = await page.evaluate(""" () => { const rows = document.querySelectorAll('table tbody tr'); return Array.from(rows).map((row, index) => { const cells = row.querySelectorAll('td'); const buttons = row.querySelectorAll('button'); return { rowIndex: index, id: cells[0]?.textContent?.trim(), name: cells[1]?.textContent?.trim(), slug: cells[2]?.textContent?.trim(), buttons: Array.from(buttons).map(btn => ({ text: btn.textContent?.trim(), className: btn.className, title: btn.title, ariaLabel: btn.getAttribute('aria-label') })) }; }); } """) print("📋 Информация о таблице:") for row in table_info: print(f" Строка {row['rowIndex']}: ID={row['id']}, Name='{row['name']}', Slug='{row['slug']}'") print(f" Кнопки: {row['buttons']}") # Ищем строку с "Test Community" test_community_row = None for row in table_info: if "Test Community" in row["name"]: test_community_row = row break if test_community_row: print(f"✅ Найдена строка с Test Community: {test_community_row}") # Пробуем найти кнопку удаления row_index = test_community_row["rowIndex"] # Способ 1: по классу delete_button = await page.query_selector( f"table tbody tr:nth-child({row_index + 1}) button.delete-button" ) print(f"Кнопка по классу delete-button: {'✅' if delete_button else '❌'}") # Способ 2: по символу × delete_button = await page.query_selector( f'table tbody tr:nth-child({row_index + 1}) button:has-text("×")' ) print(f"Кнопка по символу ×: {'✅' if delete_button else '❌'}") # Способ 3: в последней ячейке delete_button = await page.query_selector( f"table tbody tr:nth-child({row_index + 1}) td:last-child button" ) print(f"Кнопка в последней ячейке: {'✅' if delete_button else '❌'}") # Способ 4: все кнопки в строке buttons = await page.query_selector_all(f"table tbody tr:nth-child({row_index + 1}) button") print(f"Всего кнопок в строке: {len(buttons)}") for i, btn in enumerate(buttons): text = await btn.text_content() class_name = await btn.get_attribute("class") print(f" Кнопка {i}: текст='{text}', класс='{class_name}'") return True else: print("❌ Строка с Test Community не найдена") return False except Exception as e: print(f"❌ Ошибка: {e}") # Создаем папку для скриншотов если её нет os.makedirs("test-results", exist_ok=True) await page.screenshot(path=f"test-results/error_{int(time.time())}.png") return False finally: await browser.close() if __name__ == "__main__": result = asyncio.run(test_delete_button("http://localhost:3000")) if result: print("✅ Тест завершен успешно") else: print("❌ Тест завершен с ошибками") exit(1)