177 lines
7.8 KiB
Python
177 lines
7.8 KiB
Python
#!/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)
|