Files
crm.clientright.ru/test_mobile_keyboard_fix.html

890 lines
47 KiB
HTML
Raw Permalink 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.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Тест мобильной адаптации AI Drawer</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.test-container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.test-section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
.test-title {
color: #007bff;
font-size: 18px;
font-weight: bold;
margin-bottom: 15px;
}
.test-description {
color: #666;
margin-bottom: 15px;
line-height: 1.5;
}
.test-button {
background: #007bff;
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
margin: 5px;
}
.test-button:hover {
background: #0056b3;
}
.test-button.secondary {
background: #6c757d;
}
.test-button.secondary:hover {
background: #545b62;
}
.status {
padding: 10px;
border-radius: 5px;
margin: 10px 0;
font-weight: bold;
}
.status.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
.status.warning {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
}
.device-info {
background: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin: 15px 0;
font-family: monospace;
font-size: 14px;
}
.instructions {
background: #e7f3ff;
padding: 15px;
border-radius: 5px;
border-left: 4px solid #007bff;
margin: 15px 0;
}
.instructions h4 {
margin-top: 0;
color: #007bff;
}
.instructions ol {
margin: 10px 0;
padding-left: 20px;
}
.instructions li {
margin: 5px 0;
}
.log-container {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 5px;
padding: 15px;
margin: 15px 0;
font-family: 'Courier New', monospace;
font-size: 12px;
max-height: 300px;
overflow-y: auto;
white-space: pre-wrap;
}
.log-entry {
margin: 2px 0;
padding: 2px 5px;
border-radius: 3px;
}
.log-info {
background: #d1ecf1;
color: #0c5460;
}
.log-success {
background: #d4edda;
color: #155724;
}
.log-warning {
background: #fff3cd;
color: #856404;
}
.log-error {
background: #f8d7da;
color: #721c24;
}
.log-debug {
background: #e2e3e5;
color: #383d41;
}
</style>
</head>
<body>
<div class="test-container">
<h1>🧪 Тест мобильной адаптации AI Drawer</h1>
<div class="device-info">
<strong>Информация об устройстве:</strong><br>
Ширина экрана: <span id="screen-width">-</span>px<br>
Высота экрана: <span id="screen-height">-</span>px<br>
User Agent: <span id="user-agent">-</span><br>
Мобильное устройство: <span id="is-mobile">-</span>
</div>
<div class="test-section">
<div class="test-title">📱 Тест 1: Открытие AI Drawer на мобильном</div>
<div class="test-description">
Проверяем, что AI Drawer корректно открывается на мобильных устройствах и занимает всю ширину экрана.
</div>
<button class="test-button" onclick="testOpenDrawer()">Открыть AI Drawer</button>
<button class="test-button secondary" onclick="testCloseDrawer()">Закрыть AI Drawer</button>
<div id="test1-status"></div>
</div>
<div class="test-section">
<div class="test-title">⌨️ Тест 2: Адаптация к виртуальной клавиатуре</div>
<div class="test-description">
Проверяем, что поле ввода остается доступным при появлении виртуальной клавиатуры, правильно ужимается под размер экрана и поднимается выше от нижнего края.
</div>
<div class="instructions">
<h4>Инструкции для тестирования:</h4>
<ol>
<li>Откройте AI Drawer</li>
<li>Нажмите на поле ввода сообщения</li>
<li>Проверьте, что поле ввода и кнопка "Отправить" остаются видимыми</li>
<li>Проверьте, что поле ввода ужимается под размер экрана</li>
<li>Проверьте, что поле ввода поднимается выше от нижнего края (20-40px)</li>
<li>Проверьте, что кнопка "Отправить" не перекрывается</li>
<li>Проверьте, что чат автоматически прокручивается к последнему сообщению</li>
</ol>
</div>
<button class="test-button" onclick="testKeyboardAdaptation()">Начать тест клавиатуры</button>
<div id="test2-status"></div>
</div>
<div class="test-section">
<div class="test-title">📏 Тест 3: Размеры элементов на мобильном</div>
<div class="test-description">
Проверяем, что все элементы имеют подходящие размеры для мобильных устройств.
</div>
<button class="test-button" onclick="testElementSizes()">Проверить размеры</button>
<div id="test3-status"></div>
</div>
<div class="test-section">
<div class="test-title">🔄 Тест 4: Прокрутка и навигация</div>
<div class="test-description">
Проверяем плавность прокрутки и навигации в чате.
</div>
<button class="test-button" onclick="testScrolling()">Тест прокрутки</button>
<div id="test4-status"></div>
</div>
<div class="test-section">
<div class="test-title">🎨 Тест 5: Адаптивность интерфейса</div>
<div class="test-description">
Проверяем, что интерфейс корректно адаптируется к разным размерам экрана.
</div>
<button class="test-button" onclick="testResponsiveness()">Тест адаптивности</button>
<div id="test5-status"></div>
</div>
<div class="instructions">
<h4>🔧 Дополнительные тесты:</h4>
<ol>
<li><strong>Поворот экрана:</strong> Поверните устройство и проверьте адаптацию</li>
<li><strong>Разные браузеры:</strong> Протестируйте в Chrome, Safari, Firefox</li>
<li><strong>Разные размеры экрана:</strong> Протестируйте на разных устройствах</li>
<li><strong>Производительность:</strong> Проверьте плавность анимаций</li>
</ol>
</div>
<div class="test-section">
<div class="test-title">📋 Лог тестирования</div>
<div class="test-description">
Здесь отображаются подробные логи всех тестов и проверок.
</div>
<button class="test-button secondary" onclick="clearLog()">Очистить лог</button>
<button class="test-button secondary" onclick="exportLog()">Экспорт лога</button>
<button class="test-button secondary" onclick="loadServerLogs()">Загрузить с сервера</button>
<button class="test-button secondary" onclick="clearServerLogs()">Очистить сервер</button>
<button class="test-button secondary" onclick="checkServerStatus()">Статус сервера</button>
<div id="test-log" class="log-container"></div>
</div>
</div>
<!-- Подключаем AI Drawer -->
<link rel="stylesheet" href="layouts/v7/resources/css/ai-drawer.css">
<script src="layouts/v7/resources/js/ai-drawer.js"></script>
<script>
// Система логирования
let testLog = [];
function addLog(message, type = 'info', details = null) {
const timestamp = new Date().toLocaleTimeString();
const logEntry = {
timestamp: timestamp,
message: message,
type: type,
details: details,
userAgent: navigator.userAgent,
screenSize: `${window.innerWidth}x${window.innerHeight}`,
url: window.location.href
};
testLog.push(logEntry);
const logContainer = document.getElementById('test-log');
if (logContainer) {
const logElement = document.createElement('div');
logElement.className = `log-entry log-${type}`;
let logText = `[${timestamp}] ${message}`;
if (details) {
logText += `\nДетали: ${JSON.stringify(details, null, 2)}`;
}
logElement.textContent = logText;
logContainer.appendChild(logElement);
logContainer.scrollTop = logContainer.scrollHeight;
}
// Также выводим в консоль браузера
console.log(`[TEST LOG ${type.toUpperCase()}] ${message}`, details || '');
// Отправляем на сервер
sendLogToServer(logEntry);
}
function sendLogToServer(logEntry) {
fetch('/test_log_server.php?action=write', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(logEntry)
}).catch(error => {
console.warn('Не удалось отправить лог на сервер:', error);
});
}
function clearLog() {
testLog = [];
const logContainer = document.getElementById('test-log');
if (logContainer) {
logContainer.innerHTML = '';
}
addLog('Лог очищен', 'info');
}
function exportLog() {
const logText = testLog.map(entry =>
`[${entry.timestamp}] ${entry.type.toUpperCase()}: ${entry.message}` +
(entry.details ? `\nДетали: ${JSON.stringify(entry.details, null, 2)}` : '')
).join('\n\n');
const blob = new Blob([logText], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `ai-drawer-test-log-${new Date().toISOString().slice(0, 19)}.txt`;
a.click();
URL.revokeObjectURL(url);
addLog('Лог экспортирован', 'success');
}
function loadServerLogs() {
fetch('/test_log_server.php?action=read&limit=50')
.then(response => response.json())
.then(data => {
if (data.success) {
addLog(`Загружено ${data.logs.length} записей с сервера`, 'info');
// Добавляем серверные логи в контейнер
const logContainer = document.getElementById('test-log');
if (logContainer) {
data.logs.forEach(logEntry => {
const logElement = document.createElement('div');
logElement.className = `log-entry log-${logEntry.data.type || 'info'}`;
logElement.style.opacity = '0.7'; // Помечаем как серверные
let logText = `[СЕРВЕР ${logEntry.timestamp}] ${logEntry.data.message}`;
if (logEntry.data.details) {
logText += `\nДетали: ${JSON.stringify(logEntry.data.details, null, 2)}`;
}
logElement.textContent = logText;
logContainer.insertBefore(logElement, logContainer.firstChild);
});
}
} else {
addLog('Ошибка загрузки серверных логов', 'error', data.message);
}
})
.catch(error => {
addLog('Ошибка подключения к серверу логов', 'error', error.message);
});
}
function clearServerLogs() {
fetch('/test_log_server.php?action=clear')
.then(response => response.json())
.then(data => {
if (data.success) {
addLog('Серверные логи очищены', 'success');
} else {
addLog('Ошибка очистки серверных логов', 'error', data.message);
}
})
.catch(error => {
addLog('Ошибка подключения к серверу логов', 'error', error.message);
});
}
function checkServerStatus() {
fetch('/test_log_server.php?action=status')
.then(response => response.json())
.then(data => {
if (data.success) {
addLog('Статус сервера логов', 'info', data.status);
} else {
addLog('Ошибка получения статуса сервера', 'error', data.message);
}
})
.catch(error => {
addLog('Сервер логов недоступен', 'warning', error.message);
});
}
// Обновляем информацию об устройстве
function updateDeviceInfo() {
document.getElementById('screen-width').textContent = window.innerWidth;
document.getElementById('screen-height').textContent = window.innerHeight;
document.getElementById('user-agent').textContent = navigator.userAgent.substring(0, 50) + '...';
document.getElementById('is-mobile').textContent = window.innerWidth <= 768 ? 'Да' : 'Нет';
addLog('Информация об устройстве обновлена', 'info', {
width: window.innerWidth,
height: window.innerHeight,
isMobile: window.innerWidth <= 768,
userAgent: navigator.userAgent
});
}
// Обновляем информацию при изменении размера окна
window.addEventListener('resize', updateDeviceInfo);
updateDeviceInfo();
// Инициализируем AI Drawer
let aiDrawerInstance;
document.addEventListener('DOMContentLoaded', function() {
addLog('Начало инициализации AI Drawer', 'info');
try {
aiDrawerInstance = new AIDrawer();
addLog('AI Drawer успешно инициализирован', 'success', {
drawer: !!aiDrawerInstance.drawer,
toggleBtn: !!aiDrawerInstance.toggleBtn,
closeBtn: !!aiDrawerInstance.closeBtn,
chatInput: !!aiDrawerInstance.chatInput,
sendButton: !!aiDrawerInstance.sendButton
});
} catch (error) {
addLog('Ошибка инициализации AI Drawer', 'error', {
error: error.message,
stack: error.stack
});
}
});
// Тест 1: Открытие/закрытие drawer
function testOpenDrawer() {
const status = document.getElementById('test1-status');
addLog('Начало теста: Открытие AI Drawer', 'info');
try {
if (aiDrawerInstance) {
aiDrawerInstance.open();
addLog('AI Drawer открыт', 'success');
status.innerHTML = '<div class="status success">✅ AI Drawer успешно открыт</div>';
// Проверяем размеры
setTimeout(() => {
const drawer = document.querySelector('.ai-drawer');
if (drawer) {
const rect = drawer.getBoundingClientRect();
const isFullWidth = window.innerWidth <= 768 ? rect.width >= window.innerWidth * 0.95 : rect.width >= 350;
addLog('Проверка размеров drawer', 'debug', {
drawerWidth: rect.width,
screenWidth: window.innerWidth,
isMobile: window.innerWidth <= 768,
isFullWidth: isFullWidth,
expectedMinWidth: window.innerWidth <= 768 ? window.innerWidth * 0.95 : 350
});
if (isFullWidth) {
status.innerHTML += '<div class="status success">✅ Размеры drawer корректны</div>';
addLog('Размеры drawer корректны', 'success');
} else {
status.innerHTML += '<div class="status warning">⚠️ Размеры drawer могут быть некорректными</div>';
addLog('Размеры drawer некорректны', 'warning', {
actualWidth: rect.width,
expectedMinWidth: window.innerWidth <= 768 ? window.innerWidth * 0.95 : 350
});
}
} else {
addLog('Drawer элемент не найден', 'error');
}
}, 500);
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
addLog('AI Drawer не инициализирован', 'error');
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
addLog('Ошибка при открытии drawer', 'error', {
error: error.message,
stack: error.stack
});
}
}
function testCloseDrawer() {
const status = document.getElementById('test1-status');
try {
if (aiDrawerInstance) {
aiDrawerInstance.close();
status.innerHTML = '<div class="status success">✅ AI Drawer успешно закрыт</div>';
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
}
}
// Тест 2: Адаптация к клавиатуре
function testKeyboardAdaptation() {
const status = document.getElementById('test2-status');
addLog('Начало теста: Адаптация к виртуальной клавиатуре', 'info');
try {
if (aiDrawerInstance) {
aiDrawerInstance.open();
addLog('AI Drawer открыт для теста клавиатуры', 'info');
// Добавляем тестовые сообщения
aiDrawerInstance.addMessage('Тестовое сообщение 1', false);
aiDrawerInstance.addMessage('Тестовое сообщение 2', true);
aiDrawerInstance.addMessage('Тестовое сообщение 3', false);
addLog('Добавлены тестовые сообщения', 'info');
status.innerHTML = '<div class="status info"> Добавлены тестовые сообщения. Теперь нажмите на поле ввода для проверки адаптации к клавиатуре.</div>';
// Проверяем поле ввода
const input = document.querySelector('#ai-chat-input');
if (input) {
addLog('Поле ввода найдено, добавляем обработчик фокуса', 'info');
input.addEventListener('focus', function() {
addLog('Поле ввода получило фокус', 'info');
setTimeout(() => {
const inputContainer = document.querySelector('.ai-chat-input-container');
const inputField = document.querySelector('#ai-chat-input');
const sendButton = document.querySelector('#ai-send-button');
addLog('Начало проверки элементов после фокуса', 'debug', {
inputContainer: !!inputContainer,
inputField: !!inputField,
sendButton: !!sendButton
});
// Проверяем видимость контейнера
const containerRect = inputContainer.getBoundingClientRect();
const isContainerVisible = containerRect.top >= 0 && containerRect.bottom <= window.innerHeight;
// Проверяем размеры поля ввода
const inputRect = inputField.getBoundingClientRect();
const inputWidth = inputRect.width;
const screenWidth = window.innerWidth;
const inputWidthPercent = (inputWidth / screenWidth) * 100;
// Проверяем видимость кнопки отправки
const buttonRect = sendButton.getBoundingClientRect();
const isButtonVisible = buttonRect.top >= 0 && buttonRect.bottom <= window.innerHeight;
// Проверяем высоту поля ввода от нижнего края
const inputBottom = inputRect.bottom;
const screenHeight = window.innerHeight;
const distanceFromBottom = screenHeight - inputBottom;
addLog('Измерения элементов', 'debug', {
containerRect: {
top: containerRect.top,
bottom: containerRect.bottom,
left: containerRect.left,
right: containerRect.right,
width: containerRect.width,
height: containerRect.height
},
inputRect: {
top: inputRect.top,
bottom: inputRect.bottom,
left: inputRect.left,
right: inputRect.right,
width: inputRect.width,
height: inputRect.height
},
buttonRect: {
top: buttonRect.top,
bottom: buttonRect.bottom,
left: buttonRect.left,
right: buttonRect.right,
width: buttonRect.width,
height: buttonRect.height
},
screenDimensions: {
width: screenWidth,
height: screenHeight
},
calculations: {
inputWidthPercent: inputWidthPercent,
distanceFromBottom: distanceFromBottom,
isContainerVisible: isContainerVisible,
isButtonVisible: isButtonVisible
}
});
if (isContainerVisible) {
status.innerHTML += '<div class="status success">✅ Поле ввода остается видимым при появлении клавиатуры</div>';
addLog('Поле ввода остается видимым', 'success');
} else {
status.innerHTML += '<div class="status warning">⚠️ Поле ввода может быть скрыто клавиатурой</div>';
addLog('Поле ввода может быть скрыто клавиатурой', 'warning');
}
if (inputWidthPercent >= 60 && inputWidthPercent <= 80) {
status.innerHTML += '<div class="status success">✅ Поле ввода правильно ужимается под размер экрана (' + Math.round(inputWidthPercent) + '%)</div>';
addLog('Поле ввода правильно ужимается', 'success', { widthPercent: inputWidthPercent });
} else {
status.innerHTML += '<div class="status warning">⚠️ Поле ввода может быть слишком широким или узким (' + Math.round(inputWidthPercent) + '%)</div>';
addLog('Поле ввода неправильно ужимается', 'warning', { widthPercent: inputWidthPercent });
}
if (isButtonVisible) {
status.innerHTML += '<div class="status success">✅ Кнопка "Отправить" остается видимой</div>';
addLog('Кнопка "Отправить" остается видимой', 'success');
} else {
status.innerHTML += '<div class="status warning">⚠️ Кнопка "Отправить" может быть перекрыта</div>';
addLog('Кнопка "Отправить" может быть перекрыта', 'warning');
}
if (distanceFromBottom >= 200 && distanceFromBottom <= 400) {
status.innerHTML += '<div class="status success">✅ Поле ввода поднято на правильную высоту (' + Math.round(distanceFromBottom) + 'px от низа)</div>';
addLog('Поле ввода поднято на правильную высоту', 'success', { distanceFromBottom: distanceFromBottom });
} else {
status.innerHTML += '<div class="status warning">⚠️ Поле ввода может быть слишком низко или высоко (' + Math.round(distanceFromBottom) + 'px от низа)</div>';
addLog('Поле ввода неправильно позиционировано', 'warning', { distanceFromBottom: distanceFromBottom });
}
}, 500);
});
}
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
addLog('AI Drawer не инициализирован для теста клавиатуры', 'error');
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
addLog('Ошибка в тесте клавиатуры', 'error', {
error: error.message,
stack: error.stack
});
}
}
// Тест 3: Размеры элементов
function testElementSizes() {
const status = document.getElementById('test3-status');
addLog('Начало теста: Размеры элементов', 'info');
try {
if (aiDrawerInstance) {
aiDrawerInstance.open();
addLog('AI Drawer открыт для теста размеров', 'info');
setTimeout(() => {
const input = document.querySelector('#ai-chat-input');
const button = document.querySelector('#ai-send-button');
const header = document.querySelector('.ai-drawer-header');
addLog('Проверка размеров элементов', 'debug', {
input: !!input,
button: !!button,
header: !!header
});
let results = [];
if (input) {
const inputRect = input.getBoundingClientRect();
const isInputSizeOK = inputRect.height >= 40 && inputRect.height <= 60;
results.push(isInputSizeOK ? '✅ Поле ввода: размер OK' : '⚠️ Поле ввода: размер может быть некорректным');
addLog('Размер поля ввода', isInputSizeOK ? 'success' : 'warning', {
height: inputRect.height,
expectedRange: '40-60px',
isOK: isInputSizeOK
});
}
if (button) {
const buttonRect = button.getBoundingClientRect();
const isButtonSizeOK = buttonRect.height >= 40 && buttonRect.height <= 60;
results.push(isButtonSizeOK ? '✅ Кнопка отправки: размер OK' : '⚠️ Кнопка отправки: размер может быть некорректным');
addLog('Размер кнопки отправки', isButtonSizeOK ? 'success' : 'warning', {
height: buttonRect.height,
expectedRange: '40-60px',
isOK: isButtonSizeOK
});
}
if (header) {
const headerRect = header.getBoundingClientRect();
const isHeaderSizeOK = headerRect.height >= 50 && headerRect.height <= 80;
results.push(isHeaderSizeOK ? '✅ Заголовок: размер OK' : '⚠️ Заголовок: размер может быть некорректным');
addLog('Размер заголовка', isHeaderSizeOK ? 'success' : 'warning', {
height: headerRect.height,
expectedRange: '50-80px',
isOK: isHeaderSizeOK
});
}
status.innerHTML = '<div class="status info">📏 Результаты проверки размеров:</div>' +
results.map(r => '<div class="status ' + (r.includes('✅') ? 'success' : 'warning') + '">' + r + '</div>').join('');
}, 500);
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
addLog('AI Drawer не инициализирован для теста размеров', 'error');
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
addLog('Ошибка в тесте размеров', 'error', {
error: error.message,
stack: error.stack
});
}
}
// Тест 4: Прокрутка
function testScrolling() {
const status = document.getElementById('test4-status');
addLog('Начало теста: Прокрутка и навигация', 'info');
try {
if (aiDrawerInstance) {
aiDrawerInstance.open();
addLog('AI Drawer открыт для теста прокрутки', 'info');
// Добавляем много сообщений для тестирования прокрутки
for (let i = 1; i <= 10; i++) {
aiDrawerInstance.addMessage(`Тестовое сообщение ${i} для проверки прокрутки`, i % 2 === 0);
}
addLog('Добавлено 10 тестовых сообщений', 'info');
setTimeout(() => {
const content = document.querySelector('.ai-drawer-content');
if (content) {
const canScroll = content.scrollHeight > content.clientHeight;
addLog('Проверка прокрутки', 'debug', {
scrollHeight: content.scrollHeight,
clientHeight: content.clientHeight,
canScroll: canScroll
});
if (canScroll) {
status.innerHTML = '<div class="status success">✅ Прокрутка работает корректно</div>';
addLog('Прокрутка работает корректно', 'success');
// Проверяем автоматическую прокрутку к последнему сообщению
const lastMessage = content.querySelector('.ai-message:last-child');
if (lastMessage) {
const lastMessageRect = lastMessage.getBoundingClientRect();
const contentRect = content.getBoundingClientRect();
const isLastMessageVisible = lastMessageRect.bottom <= contentRect.bottom;
addLog('Проверка автоматической прокрутки', 'debug', {
lastMessageRect: {
top: lastMessageRect.top,
bottom: lastMessageRect.bottom
},
contentRect: {
top: contentRect.top,
bottom: contentRect.bottom
},
isLastMessageVisible: isLastMessageVisible
});
if (isLastMessageVisible) {
status.innerHTML += '<div class="status success">✅ Автоматическая прокрутка к последнему сообщению работает</div>';
addLog('Автоматическая прокрутка работает', 'success');
} else {
status.innerHTML += '<div class="status warning">⚠️ Автоматическая прокрутка может работать некорректно</div>';
addLog('Автоматическая прокрутка работает некорректно', 'warning');
}
} else {
addLog('Последнее сообщение не найдено', 'warning');
}
} else {
status.innerHTML = '<div class="status warning">⚠️ Прокрутка может работать некорректно</div>';
addLog('Прокрутка работает некорректно', 'warning');
}
} else {
addLog('Контейнер контента не найден', 'error');
}
}, 500);
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
addLog('AI Drawer не инициализирован для теста прокрутки', 'error');
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
addLog('Ошибка в тесте прокрутки', 'error', {
error: error.message,
stack: error.stack
});
}
}
// Тест 5: Адаптивность
function testResponsiveness() {
const status = document.getElementById('test5-status');
addLog('Начало теста: Адаптивность интерфейса', 'info');
try {
if (aiDrawerInstance) {
aiDrawerInstance.open();
addLog('AI Drawer открыт для теста адаптивности', 'info');
setTimeout(() => {
const drawer = document.querySelector('.ai-drawer');
if (drawer) {
const rect = drawer.getBoundingClientRect();
const isResponsive = window.innerWidth <= 768 ?
rect.width >= window.innerWidth * 0.95 :
rect.width >= 350 && rect.width <= 450;
addLog('Проверка адаптивности', 'debug', {
drawerWidth: rect.width,
screenWidth: window.innerWidth,
isMobile: window.innerWidth <= 768,
isResponsive: isResponsive,
expectedRange: window.innerWidth <= 768 ?
`${window.innerWidth * 0.95}px+` :
'350-450px'
});
if (isResponsive) {
status.innerHTML = '<div class="status success">✅ Адаптивность работает корректно</div>';
addLog('Адаптивность работает корректно', 'success');
} else {
status.innerHTML = '<div class="status warning">⚠️ Адаптивность может работать некорректно</div>';
addLog('Адаптивность работает некорректно', 'warning');
}
// Проверяем медиа-запросы
const mediaQuery = window.matchMedia('(max-width: 768px)');
const isMobileQuery = mediaQuery.matches;
addLog('Проверка медиа-запросов', 'debug', {
mediaQuery: '(max-width: 768px)',
isActive: isMobileQuery,
screenWidth: window.innerWidth
});
status.innerHTML += '<div class="status info">📱 Медиа-запрос (max-width: 768px): ' + (isMobileQuery ? 'Активен' : 'Неактивен') + '</div>';
} else {
addLog('Drawer элемент не найден для теста адаптивности', 'error');
}
}, 500);
} else {
status.innerHTML = '<div class="status warning">⚠️ AI Drawer не инициализирован</div>';
addLog('AI Drawer не инициализирован для теста адаптивности', 'error');
}
} catch (error) {
status.innerHTML = '<div class="status warning">⚠️ Ошибка: ' + error.message + '</div>';
addLog('Ошибка в тесте адаптивности', 'error', {
error: error.message,
stack: error.stack
});
}
}
// Дополнительная информация для отладки
addLog('Тестовая страница загружена', 'info', {
screenSize: `${window.innerWidth}x${window.innerHeight}`,
isMobile: window.innerWidth <= 768,
userAgent: navigator.userAgent
});
// Проверяем статус сервера логов при загрузке
setTimeout(() => {
checkServerStatus();
}, 1000);
console.log('Mobile Keyboard Fix Test Page loaded');
console.log('Screen size:', window.innerWidth + 'x' + window.innerHeight);
console.log('Is mobile:', window.innerWidth <= 768);
</script>
</body>
</html>