fix(test): актуализировать данные общей UX регрессии

This commit is contained in:
Denozordec committed 2026-10-04 03:55:30 +07:00
1 parent c4110fa323
commit 91c1194550
9 files changed
+1238 -15

No files matched your search

+10 -6
View File
@@ -22,7 +22,7 @@
| [backups-data-grid.tsx](../components/data-grids/backups-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [certificates-data-grid.tsx](../components/data-grids/certificates-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [communities-data-grid.tsx](../components/data-grids/communities-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [data-collection-scheduler-data-grid.tsx](../components/data-grids/data-collection-scheduler-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [data-collection-scheduler-data-grid.tsx](../components/data-grids/data-collection-scheduler-data-grid.tsx) | UI строится из11 SCHEDULER_JOB_KEYS; fixture1000 не соответствует источнику |
| [filters-data-grid.tsx](../components/data-grids/filters-data-grid.tsx) | Порядок/drag и операции до ограничения DOM |
| [firewall-rules-data-grid.tsx](../components/data-grids/firewall-rules-data-grid.tsx) | Порядок/drag и операции до ограничения DOM |
| [firewall-scenario-rules-data-grid.tsx](../components/data-grids/firewall-scenario-rules-data-grid.tsx) | Порядок/drag и операции до ограничения DOM |
@@ -32,22 +32,20 @@
| [ospf-neighbors-data-grid.tsx](../components/data-grids/ospf-neighbors-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [ospf-routes-data-grid.tsx](../components/data-grids/ospf-routes-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [probes-schedule-data-grid.tsx](../components/data-grids/probes-schedule-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [probes-speed-probes-data-grid.tsx](../components/data-grids/probes-speed-probes-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [recursive-routes-data-grid.tsx](../components/data-grids/recursive-routes-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [route-optimizer-comm-recs-data-grid.tsx](../components/data-grids/route-optimizer-comm-recs-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [route-optimizer-full-routes-data-grid.tsx](../components/data-grids/route-optimizer-full-routes-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [route-optimizer-ospf-preview-data-grid.tsx](../components/data-grids/route-optimizer-ospf-preview-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [route-optimizer-wan-matrix-data-grid.tsx](../components/data-grids/route-optimizer-wan-matrix-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [subusers-data-grid.tsx](../components/data-grids/subusers-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [traffic-flows-data-grid.tsx](../components/data-grids/traffic-flows-data-grid.tsx) | API page/limit, manualSorting и общий счётчик |
| [uptime-resources-data-grid.tsx](../components/data-grids/uptime-resources-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [uptime-speed-history-data-grid.tsx](../components/data-grids/uptime-speed-history-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [traffic-flows-data-grid.tsx](../components/data-grids/traffic-flows-data-grid.tsx) | FlowAnalyticsPanel получает conversationsList с backend cap50; API page/limit здесь нет |
| [uptime-speed-history-data-grid.tsx](../components/data-grids/uptime-speed-history-data-grid.tsx) | Реальный GET runs ограничен200; локальные новые run тоже ограничены20, проверить200 вместо выдуманного1000 |
| [users-data-grid.tsx](../components/data-grids/users-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [vxlan-data-grid.tsx](../components/data-grids/vxlan-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [wireguard-data-grid.tsx](../components/data-grids/wireguard-data-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
| [wireguard-peers-grid.tsx](../components/data-grids/wireguard-peers-grid.tsx) | Потребитель API, контекст/детали и fixture1000 |
Осталось25 специализированных grids; ни один из оставшегося перечня не принят этим документом на больших данных. CompactDataGrid дополнительно проверен на повторном получении100 active probes: страница сохраняется; сокращение100→1 ограничивает индекс. Следующая группа12.3.6 — uptime-resources/probes-speed/probes-schedule, затем сетевые/admin grids по профилям. Общий журнал: [ux-ui-progress.md](ux-ui-progress.md).
Осталось25 специализированных grids; ни один из оставшегося перечня не принят этим документом на больших данных. CompactDataGrid дополнительно проверен на повторном получении100 active probes: страница сохраняется; сокращение100→1 ограничивает индекс. Speed probes и uptime resources приняты в блоках12.3.7–12.3.9 и исключены из оставшегося перечня. Следующие большие профили: probes-schedule, затем сетевые/admin grids с учётом границ API. Общий журнал: [ux-ui-progress.md](ux-ui-progress.md).
12.3.6:1000 speed probes baseline —1000 rendered rows/23590 DOM nodes/3741ms dev ready; профиль collector-probes4 cases и ESLint прошли. Далее12.3.7 ограничение DOM speed grid; этот baseline не означает принятую производительность.
@@ -58,3 +56,9 @@
12.3.9:1000 предупреждений CPU90% — warning nodes2009→21, страница4739→2751 при закрытом списке.5→55→105→5→55 карточек по явному раскрытию; полный счётчик сохранён.9 browser и tagged axe прошли. Полное постепенное раскрытие допускает весь список, это не виртуализация.
12.3.11: ServerTileRail1001 устройств —50 options на странице (All отдельный aggregate), mobile Sheet тоже50. Speed probes + каталог:11265→1778 DOM nodes,739 nodes speed секции/50 строк. Поиск/URL/граница площадок/клавиатура/refresh/320px/axe обе темы проверены;47 browser и production build прошли. Полные DTO остаются в памяти.
## Уточнение ограниченных источников перед общей регрессией
Статический аудит исходников на c4110fa: schedulerGridRows строится из SCHEDULER_JOB_KEYS (11), поэтому отсутствие client pagination не означает1000 строк. TrafficFlowsDataGrid получает analytics.conversationsList, а buildFlowAnalyticsUncached задаёт top=min(50,max(10,settings.topN)) и slice(0,top); page/limit в этом пути нет. Старый /traffic/flows listFlowTalkers — другой источник с settings.topN, его нельзя смешивать с текущей таблицей analytics. Uptime speed history GET /uptime/speed-test/runs использует DB limit200; frontend локальный run список ограничен20. Эти ограничения установлены чтением кода, не нагрузочным испытанием PG. Остальные строки карты требуют проверки по своим потребителям;25 manualPagination:true файлов не означают25 одинаковых дефектов.
Statistics pivot в backend/src/services/statistics-aggregate.ts ограничен PIVOT_ROW_CAP=50 и PIVOT_COL_CAP=15; при превышении добавляются агрегаты __other__. Проверять фактическую границу51×16, прокрутку и переходы к срезам, а не произвольную матрицу1000×1000. Это статический аудит источника; browser evidence широкой pivot ещё требуется.
+1 -1
View File
@@ -4,7 +4,7 @@
## Актуальная точка продолжения — 2026-10-04
Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. Следующий блок12.4.1:main browser regression1091 тест/163 файла, затем context и оставшиеся grids;12.4/12.5 ещё не завершены. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются.
Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. 12.4.1 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. Следующий блок12.4.2:23 context файла и backend-switch, затем оставшиеся grids/pivot;12.4/12.5 ещё не завершены. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются.
Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md).
+9 -1
View File
@@ -29,13 +29,21 @@
| 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 |
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 |
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | В работе;12.1/12.2.1–12.2.10 и12.3.1–12.3.5 и12.3.7–12.3.12 приняты в описанных локальных границах |
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | В работе;12.1/12.2.1–12.2.10 и12.3.1–12.3.5 и12.3.7–12.3.12 приняты в описанных локальных границах;12.4.1 main регрессия и профильный повтор записаны |
## 12.4.1 — общая регрессия и актуальные fixtures (2026-10-04)
Main Playwright/Edge на c4110fa:1091 сценарий в163 файлах,1088 passed/3 failed/0 skipped/0 flaky,24.9 минуты,workers1/retries0. Все три падения воспроизведены как устаревшие fixtures: admin-tables обслуживал legacy /api/certificates вместо /api/certificates/state; Filters ожидал демо Community, не предоставляя подтверждённый Evolution catalog. Fixtures обновлены по strict schemas; keyboard/SAN/sort/write assertions сохранены. Повтор обоих файлов:6 passed. Полный прогон после fixtures не повторялся: production код не менялся; это1088 успешных сценариев общей регрессии плюс исправленные3 в профильном повторе, а не новый единый1091/1091 прогон.
Typecheck и ESLint двух изменённых файлов прошли. Production/contracts build34 страницы ранее прошёл на том же production HEAD c4110fa. Исходный отчёт сохранён в [main-regression-2026-10-04.json](ux-ui/acceptance/main-regression-2026-10-04.json), новые просмотренные снимки rail320px — в docs/ux-ui/screens/large-server-rail-dark-320.png и large-server-rail-light-320.png. Перегенерированные исторические screenshots восстановлены; чужие изменения не включены. Карта производительности уточнена по фактическим backend caps (scheduler11/flows50/speed history200/pivot51×16 с Other); большие browser профили оставшихся25 grids и pivot ещё требуются.
Следующий блок12.4.2: единый последовательный context прогон23 исключённых файлов с backend URL local, затем backend-switch. После context — оставшиеся границы производительности12.3 и матрица builds/checklist.12.5 реальная PG/RouterOS/интеграционная приёмка отдельно. Локальный коммит, без push.
## 12.3.12 — ручная страница BGP при выборе сессии из URL (2026-10-04)
Воспроизведён возврат со страницы19 на20 после ручного Previous при selectedSessionId из URL. Эффект BGP больше не зависит от меняющегося объекта useTable: используются стабильный setPageIndex и вычисленный индекс выбранной сессии. Глобальная сортировка и первичное восстановление выбранной сессии сохранены; ручная страница19 сохраняется при refresh, reload восстанавливает linked session на20.
+8
View File
@@ -223,3 +223,11 @@ ServerTileRail сохраняет существующую композицию
16 browser BGP/data/links/1000 sessions прошли после исправления; Typecheck/ESLint и frontend production/contracts build(34 страницы) прошли. Метрики BGP50 строк/1932 nodes остаются. Реальный BGP/RouterOS не проверен.
Следующий шаг12.4.1: общий main browser прогон (1091 тест в163 файлах) с JSON отчётом; ограничить ранние падения20, затем разобрать причины и профильные повторы. Это проверка после изменения общей основы;12.3 ещё имеет25 specialized grids и широкую pivot для проверки. После main — context конфигурации и итоговая матрица;12.5 внешняя приёмка отдельно. Без push.
## 12.4.1 — общая регрессия и актуальные fixtures (2026-10-04)
Main Playwright/Edge на c4110fa:1091 сценарий в163 файлах,1088 passed/3 failed/0 skipped/0 flaky,24.9 минуты,workers1/retries0. Все три падения воспроизведены как устаревшие fixtures: admin-tables обслуживал legacy /api/certificates вместо /api/certificates/state; Filters ожидал демо Community, не предоставляя подтверждённый Evolution catalog. Fixtures обновлены по strict schemas; keyboard/SAN/sort/write assertions сохранены. Повтор обоих файлов:6 passed. Полный прогон после fixtures не повторялся: production код не менялся; это1088 успешных сценариев общей регрессии плюс исправленные3 в профильном повторе, а не новый единый1091/1091 прогон.
Typecheck и ESLint двух изменённых файлов прошли. Production/contracts build34 страницы ранее прошёл на том же production HEAD c4110fa. Исходный отчёт сохранён в [main-regression-2026-10-04.json](ux-ui/acceptance/main-regression-2026-10-04.json), новые просмотренные снимки rail320px — в docs/ux-ui/screens/large-server-rail-dark-320.png и large-server-rail-light-320.png. Перегенерированные исторические screenshots восстановлены; чужие изменения не включены. Карта производительности уточнена по фактическим backend caps (scheduler11/flows50/speed history200/pivot51×16 с Other); большие browser профили оставшихся25 grids и pivot ещё требуются.
Следующий блок12.4.2: единый последовательный context прогон23 исключённых файлов с backend URL local, затем backend-switch. После context — оставшиеся границы производительности12.3 и матрица builds/checklist.12.5 реальная PG/RouterOS/интеграционная приёмка отдельно. Локальный коммит, без push.
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

+9 -7
View File
@@ -1,6 +1,7 @@
import { test, expect, type Page } from "@playwright/test"
import { appUserReadSchema } from "../../packages/contracts/src/users"
import { certificatesListResponseSchema } from "../../packages/contracts/src/certificates"
import { certificatesStateSchema } from "../../packages/contracts/src/certificates"
import { certificateState, server } from "./fixtures/certificates"
import type { BackupItem } from "../../shared/api/backups"
const ids = Array.from({ length: 12 }, (_, i) => i + 1)
@@ -9,11 +10,12 @@ const users = ids.map(i => appUserReadSchema.parse({
role: "viewer", active: true, avatar: "U", lastSeen: null, sections: [], servers: [], bindings: [],
createdAt: "2026-09-14T00:00:00Z", updatedAt: "2026-09-14T00:00:00Z",
}))
const certificates = certificatesListResponseSchema.parse({ failures: [], certificates: ids.map(i => ({
id: String(i), name: `cert-${i}`, serverId: "1", commonName: `host${i}.example.test`,
sans: [`alt${i}.example.test`], issuedBy: "Test CA", validFrom: "2026-09-01", validUntil: "2027-09-01",
const certificates = certificatesStateSchema.parse(certificateState(ids.map(i => ({
id: `1:*${i}`, rosId: `*${i}`, name: `cert-${i}`, serverId: "1", commonName: `host${i}.example.test`,
sans: [`alt${i}.example.test`], issuedBy: "Test CA", validFrom: "2026-09-01T00:00:00Z", validUntil: "2027-09-01T00:00:00Z",
rawValidFrom: "2026-09-01", rawValidUntil: "2027-09-01",
daysLeft: 300 + i, keySize: 2048, usage: ["server"], trusted: true, status: "valid",
})) })
}))))
const backups: BackupItem[] = ids.map(i => ({ id: String(i), serverId: 1, serverName: "Тестовый роутер",
filename: `backup-${i}.backup`, sizeBytes: i === 12 ? 1048576 : i * 1024, createdAt: "2026-09-14T00:00:00Z", kind: i > 6 ? "auto" : "manual", storage: "local" }))
@@ -22,12 +24,12 @@ async function setup(page: Page, url: string) {
await page.route("**/api/**", route => {
const path = new URL(route.request().url()).pathname
return route.fulfill({ json: path === "/api/users" ? { users }
: path === "/api/certificates" ? certificates : path === "/api/backups" ? backups
: path === "/api/certificates/state" ? certificates : path === "/api/backups" ? backups
: path === "/api/certificates/acme-settings" ? { directoryUrl: "https://acme.example.test/directory", defaultZoneId: "", tokenConfigured: false }
: path === "/api/certificates/renew-settings" ? { enabled: false, intervalSec: 3600, renewBeforeDays: 30 }
: path === "/api/backups/schedule" ? { enabled: false, frequency: "daily", hour: 3, minute: 0, weekDay: 0, monthDay: 1, keepCount: 7, format: "backup", serverIds: [] }
: path === "/api/backups/storage" ? { provider: "local", s3Endpoint: "", s3Region: "", s3Bucket: "", s3Prefix: "", s3AccessKeyId: "", secretConfigured: false, s3ForcePathStyle: false, keepLocalCopy: true }
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [] : {} })
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [server] : {} })
})
await page.goto(url)
}
+10
View File
@@ -1,5 +1,12 @@
import { test, expect } from "@playwright/test"
import { mkdirSync } from "node:fs"
import { evoSettings, evoCatalog } from "./fixtures/evobgp"
import { parseEvoBgpCatalog } from "../../lib/evobgp-catalog"
const catalog = parseEvoBgpCatalog({ ...evoCatalog, communities: [{
id: "blackhole", value: "65535:666", name: "RFC Blackhole", description: "RTBH",
type: "standard", filterIds: [], serverCount: 2, prefixCount: null, action: "deny", enabled: true,
}] })
for (const device of ["desktop", "mobile"] as const) {
test(`Filters: клавиатурный ввод и layout ${device}`, async ({ page }) => {
@@ -27,6 +34,8 @@ for (const device of ["desktop", "mobile"] as const) {
return route.fulfill({ json: path === "/api/filters/rules" ? { rulesets: id ? rulesets.filter(rs => rs.serverId === id) : rulesets, greTunnels: [], live: true }
: path === "/api/servers" ? [1, 2].map(i => ({ id: i, name: i === 1 ? "Основной роутер" : "Резервный роутер", host: "192.0.2." + i, type: "exit-node", enabled: true, country: "RU", site: "CORE", asn: "65001", status: "online", latency: 3 }))
: path === "/api/filters/gre-tunnels" ? { tunnels: [tunnel(id ?? "1")] }
: path === "/api/evobgp/settings" ? evoSettings
: path === "/api/evobgp/catalog" ? catalog
: path === "/api/recursive-routes" ? { routes: [], stale: false }
: path === "/api/auth/config" ? { required: false } : {} })
})
@@ -53,6 +62,7 @@ for (const device of ["desktop", "mobile"] as const) {
await expect(dialog.getByRole("alert")).toContainText("BGP Community обязательно")
const community = dialog.getByRole("combobox", { name: /BGP Community/ })
await community.fill("65535")
await expect(page.getByRole("option", { name: /65535:666/ })).toBeVisible()
await page.keyboard.press("ArrowDown")
await page.keyboard.press("Enter")
await expect(community).toHaveValue("65535:666")