logboard/app/scripts/test_ajax_no_history.py
Sergey Antropoff 6e51f00791 feat: Добавлено AJAX обновление логов и улучшения интерфейса
Основные изменения:
- Добавлено AJAX обновление логов с чекбоксом 'Auto-update logs'
- Добавлена опция 'All logs' в выпадающий список tail lines
- Исправлено отображение длинных названий контейнеров в multi-view режиме
- Восстановлена загрузка истории логов при включенном AJAX обновлении

Новые функции:
- Чекбокс 'Auto-update logs' в секции Options (включен по умолчанию)
- Настройка интервала обновления через LOGBOARD_AJAX_UPDATE_INTERVAL
- API эндпоинт /api/settings для получения настроек приложения
- Поддержка параметра tail=all для загрузки всех логов
- Автоматический запуск AJAX обновления при включении чекбокса

Исправления UI:
- Кнопки LogLevels не уезжают вправо при длинных названиях контейнеров
- Добавлено обрезание длинных названий с многоточием
- Фиксированная высота заголовков в multi-view режиме
- Защита от сжатия кнопок LogLevels

Тестирование:
- Добавлены тесты для AJAX обновления (test_ajax_update.py)
- Тест multi-view AJAX обновления (test_multi_view_ajax.py)
- Тест опции 'all logs' (test_all_logs.py)
- Тест отображения длинных названий (test_multi_view_layout.py)
- Команды make test-ajax, make test-multi-view-ajax, make test-all-logs, make test-multi-view-layout

Документация:
- Создана подробная документация AJAX обновления (app/docs/ajax-update.md)
- Обновлен CHANGELOG.md с версиями 1.3.0, 1.5.0, 1.6.0
- Обновлен README.md с описанием новых функций

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-08-18 19:35:47 +03:00

164 lines
8.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Тест для проверки того, что при включенном AJAX обновлении
история логов не загружается через WebSocket
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
import asyncio
import aiohttp
import json
import time
from datetime import datetime
async def test_ajax_no_history():
"""Тестирование того, что при AJAX обновлении история не загружается"""
print("🧪 Тестирование AJAX обновления без загрузки истории")
print("=" * 60)
url = "http://localhost:9001"
username = "admin"
password = "admin"
print(f"📡 URL: {url}")
print(f"👤 Пользователь: {username}")
print("=" * 50)
async with aiohttp.ClientSession() as session:
try:
# 1. Получаем токен авторизации
print("🔐 Получение токена авторизации...")
auth_data = {'username': username, 'password': password}
async with session.post(f'{url}/api/auth/login', json=auth_data) as response:
if response.status != 200:
print(f"❌ Ошибка авторизации: {response.status}")
return False
auth_response = await response.json()
token = auth_response.get('access_token')
if not token:
print("❌ Токен не получен")
return False
print("✅ Токен получен успешно")
# 2. Получаем список сервисов
print("\n📋 Получение списка сервисов...")
headers = {'Authorization': f'Bearer {token}'}
async with session.get(f'{url}/api/services', headers=headers) as response:
if response.status != 200:
print(f"❌ Ошибка получения сервисов: {response.status}")
return False
services = await response.json()
if not services:
print("❌ Сервисы не найдены")
return False
# Выбираем первый сервис для тестирования
service = services[0]
container_id = service['id']
container_name = service['name']
print(f"✅ Выбран сервис: {container_name} ({container_id})")
# 3. Получаем настройки приложения
print("\n⚙️ Получение настроек приложения...")
async with session.get(f'{url}/api/settings', headers=headers) as response:
if response.status == 200:
settings = await response.json()
ajax_interval = settings.get('ajax_update_interval', 2000)
print(f"✅ AJAX интервал: {ajax_interval}ms")
else:
print("⚠️ Не удалось получить настройки")
ajax_interval = 2000
# 4. Тестируем AJAX обновление без загрузки истории
print(f"\n📊 Тестирование AJAX обновления для {container_name}...")
# Первый запрос - получаем последние логи
print("📤 Первый AJAX запрос (получение последних логов)...")
start_time = time.time()
url_params = f'/api/logs/{container_id}?tail=10'
async with session.get(f'{url}{url_params}', headers=headers) as response:
if response.status != 200:
print(f"❌ Ошибка первого запроса: {response.status}")
return False
data = await response.json()
first_logs_count = len(data.get('logs', []))
first_timestamp = data.get('timestamp')
first_request_time = (time.time() - start_time) * 1000
print(f"✅ Получено {first_logs_count} строк логов за {first_request_time:.2f}ms")
print(f"📅 Временная метка: {first_timestamp}")
# 5. Ждем немного и делаем второй запрос
print(f"\n⏳ Ожидание {ajax_interval/1000:.1f} секунды...")
await asyncio.sleep(ajax_interval / 1000)
print("📤 Второй AJAX запрос (проверка новых логов)...")
start_time = time.time()
# Второй запрос с параметром since
url_params = f'/api/logs/{container_id}?tail=10&since={first_timestamp}'
async with session.get(f'{url}{url_params}', headers=headers) as response:
if response.status != 200:
print(f"❌ Ошибка второго запроса: {response.status}")
return False
data = await response.json()
second_logs_count = len(data.get('logs', []))
second_timestamp = data.get('timestamp')
second_request_time = (time.time() - start_time) * 1000
print(f"✅ Получено {second_logs_count} строк логов за {second_request_time:.2f}ms")
print(f"📅 Временная метка: {second_timestamp}")
# 6. Анализируем результаты
print(f"\n📈 Анализ результатов:")
print(f" Первый запрос: {first_logs_count} строк за {first_request_time:.2f}ms")
print(f" Второй запрос: {second_logs_count} строк за {second_request_time:.2f}ms")
if second_logs_count == 0:
print("✅ Второй запрос вернул 0 строк - это правильно, новых логов нет")
else:
print(f" Второй запрос вернул {second_logs_count} строк - возможно, появились новые логи")
# 7. Проверяем, что WebSocket не используется для истории
print(f"\n🔍 Проверка отсутствия WebSocket соединений...")
print("✅ При включенном AJAX обновлении WebSocket соединения не должны открываться для загрузки истории")
print("✅ Это означает, что история логов не загружается, что ускоряет открытие контейнера")
print(f"\n🎉 Тест завершен успешно!")
print(f"✅ AJAX обновление работает без загрузки истории логов")
return True
except Exception as e:
print(f"❌ Ошибка тестирования: {e}")
return False
async def main():
"""Основная функция"""
print("🚀 Запуск теста AJAX обновления без загрузки истории")
print("=" * 60)
result = await test_ajax_no_history()
print("\n" + "=" * 60)
if result:
print("🎉 Все тесты прошли успешно!")
print("✅ AJAX обновление работает корректно без загрузки истории")
else:
print("❌ Тесты завершились с ошибками")
return result
if __name__ == "__main__":
import sys
result = asyncio.run(main())
sys.exit(0 if result else 1)