# UI Test Cases — ET-014 Playwright UI тест-кейсы для визуальной приёмки фикса z-index. Все тесты выполняются на test-среде https://openclaw.mva154.duckdns.org/enduro/. Общие соображения: - Карта инициализируется ~2–4 секунды (MapLibre + загрузка стилей/тайлов). Везде где идёт первый `navigate` — пауза 4000 мс перед действиями. - Селекторы взяты из `src/web/index.html`. --- ### TC-UI-01 — Mobile: фильтры открываются ПОВЕРХ панели слоёв - type: ui - viewport: mobile - viewport-size: 390 × 844 - theme: dark (по умолчанию) Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. screenshot: 01-map-loaded 4. click: #terrain-toggle 5. wait: 400 6. screenshot: 02-terrain-popup-open 7. check-visual: видна панель `#terrain-popup` с чекбоксами; visible(`#public-tracks-cb`) === true 8. click: #public-tracks-cb 9. wait: 300 10. check-visual: visible(`#public-tracks-filters-btn`) === true (кнопка «Фильтры…» появилась) 11. click: #public-tracks-filters-btn 12. wait: 600 13. screenshot: 03-filters-sheet-opened 14. check-visual: `#sheet-gps-filters` имеет класс `open`; заголовок «Фильтры публичных треков», секции «ТИП АКТИВНОСТИ», «ИСТОЧНИК», «ЦВЕТ ЛИНИЙ» и кнопка `✕` полностью видны в viewport 15. check-visual: `document.elementFromPoint(195, 600)` принадлежит `#sheet-gps-filters` или его потомкам (НЕ `#terrain-popup`) 16. check-visual: bounding box `#sheet-gps-filters` не пересекается с видимой частью `#terrain-popup`, либо если пересекается — sheet поверх (через elementFromPoint в центрах пересечения) Ожидаемый результат: панель фильтров полностью видна, ничем не перекрыта. --- ### TC-UI-02 — Desktop: фильтры открываются ПОВЕРХ панели слоёв - type: ui - viewport: desktop - viewport-size: 1440 × 900 - theme: dark Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #terrain-toggle 4. wait: 400 5. click: #public-tracks-cb 6. wait: 300 7. click: #public-tracks-filters-btn 8. wait: 600 9. screenshot: desktop-filters-opened 10. check-visual: `#sheet-gps-filters` виден слева (получить bbox через `getBoundingClientRect`, ожидание: left ≤ 80, right ≥ 380) 11. check-visual: `document.elementFromPoint(bbox.left + bbox.width/2, bbox.top + bbox.height/2)` принадлежит `#sheet-gps-filters` или его потомкам Ожидаемый результат: на desktop sheet открыт как боковая панель, terrain-popup не перекрывает. --- ### TC-UI-03 — Закрытие фильтров кнопкой ✕ - type: ui - viewport: mobile - viewport-size: 390 × 844 Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #terrain-toggle 4. wait: 300 5. click: #public-tracks-cb 6. wait: 300 7. click: #public-tracks-filters-btn 8. wait: 500 9. click: #sheet-gps-filters .sheet-close 10. wait: 600 11. screenshot: after-close 12. check-visual: `#sheet-gps-filters` НЕ имеет класса `open` 13. check-visual: `#sheet-backdrop` НЕ имеет класса `visible` 14. check-visual: `document.elementFromPoint(195, 600)` принадлежит `#map` или его canvas-потомку (карта снова интерактивна) Ожидаемый результат: возврат к карте, никаких артефактов. --- ### TC-UI-04 — Повторное открытие/закрытие фильтров - type: ui - viewport: mobile - viewport-size: 390 × 844 Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #terrain-toggle 4. wait: 300 5. click: #public-tracks-cb 6. wait: 300 7. click: #public-tracks-filters-btn 8. wait: 500 9. click: #sheet-gps-filters .sheet-close 10. wait: 500 11. click: #terrain-toggle 12. wait: 300 13. click: #public-tracks-filters-btn 14. wait: 500 15. screenshot: second-open 16. check-visual: `#sheet-gps-filters` имеет класс `open`, виден полностью, элемент в центре sheet'а через elementFromPoint принадлежит sheet'у 17. click: #sheet-gps-filters .sheet-close 18. wait: 500 19. click: #terrain-toggle 20. wait: 300 21. click: #public-tracks-filters-btn 22. wait: 500 23. check-visual: третий цикл — sheet снова открыт корректно Ожидаемый результат: 3 цикла open/close без деградации. --- ### TC-UI-05 — Регрессия остальных bottom-sheets - type: ui - viewport: mobile - viewport-size: 390 × 844 Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #tb-route 4. wait: 400 5. check-visual: `#sheet-route` имеет класс `open`, заголовок «Маршрут» виден 6. screenshot: sheet-route 7. click: #sheet-route .sheet-close 8. wait: 400 9. click: #tb-recon 10. wait: 400 11. check-visual: `#sheet-recon` имеет класс `open` 12. screenshot: sheet-recon 13. click: #sheet-recon .sheet-close 14. wait: 400 15. click: #tb-scenic 16. wait: 400 17. check-visual: `#sheet-scenic` имеет класс `open` 18. screenshot: sheet-scenic 19. click: #sheet-scenic .sheet-close 20. wait: 400 21. click: #tb-link 22. wait: 400 23. check-visual: `#sheet-link` имеет класс `open` 24. screenshot: sheet-link 25. click: #sheet-link .sheet-close 26. wait: 400 27. click: #tb-gpx 28. wait: 400 29. check-visual: `#sheet-gpx` имеет класс `open` 30. screenshot: sheet-gpx 31. click: #sheet-gpx .sheet-close 32. wait: 400 Ожидаемый результат: все sheet'ы открываются и закрываются без артефактов и не «застревают». --- ### TC-UI-06 — Светлая тема: фильтры поверх - type: ui - viewport: mobile - viewport-size: 390 × 844 - theme: light Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #btn-theme 4. wait: 500 5. check-visual: `document.body` НЕ содержит класса `theme-dark` (или содержит `theme-light`) 6. screenshot: 01-light-theme 7. click: #terrain-toggle 8. wait: 300 9. click: #public-tracks-cb 10. wait: 300 11. click: #public-tracks-filters-btn 12. wait: 500 13. screenshot: 02-light-filters-open 14. check-visual: `#sheet-gps-filters` имеет класс `open`, текст читаем (контраст), sheet полностью виден 15. check-visual: elementFromPoint в центре sheet'а возвращает элемент внутри `#sheet-gps-filters` Ожидаемый результат: поведение полностью аналогично тёмной теме, без визуальных дефектов на светлом фоне. --- ### TC-UI-07 — Регрессия: terrain-popup сам по себе работает - type: ui - viewport: mobile - viewport-size: 390 × 844 Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #terrain-toggle 4. wait: 300 5. screenshot: terrain-popup 6. check-visual: `#terrain-popup` style.display !== 'none'; `#terrain-toggle` имеет класс `active` 7. click: #terrain-hillshade-cb 8. wait: 300 9. check-visual: popup всё ещё открыт; чекбокс перешёл в состояние checked 10. click: #base-btn-satellite 11. wait: 600 12. check-visual: popup всё ещё открыт; кнопка `#base-btn-satellite` имеет класс `active` 13. click: #map // клик по карте вне popup 14. wait: 400 15. check-visual: `#terrain-popup` style.display === 'none'; `#terrain-toggle` БЕЗ класса `active` Ожидаемый результат: без регрессий — popup ведёт себя как раньше. --- ### TC-UI-08 — Регрессия: marker-dialog поверх - type: ui - viewport: mobile - viewport-size: 390 × 844 Шаги: 1. navigate: https://openclaw.mva154.duckdns.org/enduro/ 2. wait: 4000 3. click: #tb-marker 4. wait: 400 5. click: #map // тап по карте чтобы открыть dialog выбора типа метки 6. wait: 500 7. screenshot: marker-dialog 8. check-visual: `#marker-dialog` виден (computed style: opacity > 0) 9. check-visual: elementFromPoint в центре dialog'а возвращает элемент внутри `#marker-dialog` Ожидаемый результат: marker-dialog корректно поверх всего. --- ## Helpers / Assertions Для check-visual использовать: - `await page.locator(selector).isVisible()` для базовой видимости. - `await page.evaluate(() => document.elementFromPoint(x, y)?.closest('#sheet-gps-filters')?.id)` для проверки stacking. - `await page.locator('#sheet-gps-filters').evaluate(el => el.classList.contains('open'))` для DOM-классов. - `await expect(page).toHaveScreenshot(...)` если используется baseline-сравнение. Скриншоты сохранять в `tests/e2e/__screenshots__/ET-014//.png`.