fix(ui): ограничить отображение каталога VXLAN-туннелей
This commit is contained in:
1 parent
c7aec1500c
commit
dcc8550482
6 files changed
+82
-12
No files matched your search
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useMemo } from "react"
|
||||
import { dataGridFeatures, type DataGridFeatures } from "@/components/reui/data-grid"
|
||||
import { useEffect, useMemo } from "react"
|
||||
import { DataGridContainer, DataGridScrollArea, DataGridTable, dataGridFeatures, type DataGridFeatures } from "@/components/reui/data-grid"
|
||||
import {
|
||||
type ColumnDef,
|
||||
useTable,
|
||||
@@ -47,6 +47,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
() => [
|
||||
{
|
||||
id: "name",
|
||||
size: 176,
|
||||
accessorKey: "name",
|
||||
header: ({ column }) => (
|
||||
<DataGridSortHeader column={column} title="Имя / VTEP" className="ml-1" />
|
||||
@@ -58,12 +59,12 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
<span
|
||||
className={cn(
|
||||
"size-2 rounded-full shrink-0 mt-1.5",
|
||||
failedServerIds.includes(t.serverId) ? "bg-muted-foreground" : t.status === "up" ? "bg-emerald-500" : "bg-red-500",
|
||||
failedServerIds.includes(t.serverId) ? "bg-muted-foreground" : t.status === "up" ? "bg-success" : "bg-destructive",
|
||||
)}
|
||||
/>
|
||||
<div className="min-w-0">
|
||||
<p className="font-mono font-medium text-sm truncate">{t.name}</p>
|
||||
<p className="text-[11px] text-muted-foreground font-mono">VTEP: {t.vtepIp}</p>
|
||||
<p className="font-mono font-medium text-sm break-all">{t.name}</p>
|
||||
<p className="text-[11px] text-muted-foreground font-mono break-all">VTEP: {t.vtepIp}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -76,6 +77,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "server",
|
||||
size: 128,
|
||||
accessorKey: "serverId",
|
||||
header: ({ column }) => <DataGridSortHeader column={column} title="Сервер" />,
|
||||
cell: ({ row }) => {
|
||||
@@ -96,6 +98,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "vni",
|
||||
size: 80,
|
||||
accessorKey: "vni",
|
||||
header: ({ column }) => <DataGridSortHeader column={column} title="VNI" />,
|
||||
cell: ({ row }) => <span className="font-mono text-sm">{row.original.vni}</span>,
|
||||
@@ -107,6 +110,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "dstPort",
|
||||
size: 104,
|
||||
accessorKey: "dstPort",
|
||||
header: ({ column }) => <DataGridSortHeader column={column} title="Port" />,
|
||||
cell: ({ row }) => <span className="font-mono text-sm">{row.original.dstPort}</span>,
|
||||
@@ -118,6 +122,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "remoteVteps",
|
||||
size: 160,
|
||||
header: () => (
|
||||
<span className="text-xs font-medium text-muted-foreground">Remote</span>
|
||||
),
|
||||
@@ -133,6 +138,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "arpProxy",
|
||||
size: 104,
|
||||
accessorKey: "arpProxy",
|
||||
header: () => <span className="sr-only">ARP</span>,
|
||||
enableSorting: false,
|
||||
@@ -152,6 +158,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "macLearning",
|
||||
size: 128,
|
||||
accessorKey: "macLearning",
|
||||
header: () => <span className="sr-only">MAC</span>,
|
||||
enableSorting: false,
|
||||
@@ -171,6 +178,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
},
|
||||
{
|
||||
id: "status",
|
||||
size: 104,
|
||||
accessorKey: "status",
|
||||
header: ({ column }) => <DataGridSortHeader column={column} title="Статус" />,
|
||||
cell: ({ row }) => (
|
||||
@@ -208,8 +216,8 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className={cn(
|
||||
"size-8 shrink-0 border-border/60 bg-background/80 text-muted-foreground shadow-none",
|
||||
"opacity-0 transition-opacity group-hover/row:opacity-100 focus-visible:opacity-100",
|
||||
"size-11 shrink-0 border-border/60 bg-background/80 text-muted-foreground shadow-none",
|
||||
"transition-colors",
|
||||
"data-popup-open:opacity-100",
|
||||
)}
|
||||
aria-label={`Действия: ${tunnel.name}`}
|
||||
@@ -229,7 +237,7 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
)
|
||||
},
|
||||
enableSorting: false,
|
||||
size: 56,
|
||||
size: 72,
|
||||
meta: {
|
||||
headerClassName: DATA_GRID_CELL_PAD_LAST,
|
||||
cellClassName: DATA_GRID_CELL_PAD_LAST,
|
||||
@@ -241,12 +249,20 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
|
||||
const table = useTable({
|
||||
features: dataGridFeatures,
|
||||
manualPagination: true,
|
||||
manualPagination: false,
|
||||
autoResetPageIndex: false,
|
||||
initialState: { pagination: { pageIndex: 0, pageSize: 50 }, columnPinning: { start: ["name"], end: [] } },
|
||||
data: tunnels,
|
||||
columns,
|
||||
getRowId: (row) => JSON.stringify([row.serverId, row.id]),
|
||||
})
|
||||
|
||||
const { pageIndex, pageSize } = table.state.pagination
|
||||
useEffect(() => {
|
||||
const lastPage = Math.max(0, Math.ceil(tunnels.length / pageSize) - 1)
|
||||
if (pageIndex > lastPage) table.setPageIndex(lastPage)
|
||||
}, [tunnels.length, pageIndex, pageSize, table])
|
||||
|
||||
if (tunnels.length === 0) {
|
||||
return (
|
||||
<EmptyState
|
||||
@@ -262,11 +278,17 @@ function VxlanDataGrid({ tunnels, servers, onExport, failedServerIds = [] }: Vxl
|
||||
<DataGridShell
|
||||
table={table}
|
||||
recordCount={tunnels.length}
|
||||
pagination={tunnels.length > 50 || pageSize !== 50}
|
||||
tableLayout={{ dense: true, columnsPinnable: true }}
|
||||
tableClassNames={{
|
||||
headerRow: "border-b border-border",
|
||||
bodyRow: cn("group/row", "[&[data-disabled=true]]:opacity-50"),
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<DataGridContainer border={false} className="w-full rounded-none border-0">
|
||||
<DataGridScrollArea orientation="horizontal"><DataGridTable /></DataGridScrollArea>
|
||||
</DataGridContainer>
|
||||
</DataGridShell>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. 12.4.2 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принLine truncated
|
||||
Этап 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 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принLine truncated
|
||||
|
||||
Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md).
|
||||
|
||||
|
||||
@@ -29,7 +29,15 @@
|
||||
| 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.4.1 main регрессия и профильный повтор записаны;12.4.2 context205 и unit28 прошли;12.3.13–12.3.25 приняты локально в описанных границах;12.4.4 context213 и12.4.5 main1110 прошли, 12.3.26–12.3.33 приняты локально; остаются VXLAN/network grids/общая регрессия после delta/внешняя приёмка |
|
||||
| 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.2 context205 и unit28 прошли;12.3.13–12.3.25 приняты локально в описанных границах;12.4.4 context213 и12.4.5 main1110 прошли, 12.3.26–12.3.33 приняты локально; 12.3.34 VXLAN принят; остаются GRE/network grids/общая регрессия после delta/внешняя приёмка |
|
||||
|
||||
## 12.3.34 — большой каталог VXLAN (2026-10-04)
|
||||
|
||||
Полный /vxlan API не ограничен страницей. Таблица использует client pagination50, global sort, сохранение страницы при refresh и clamp после поиска/сокращения. ReUI ScrollArea/start pinning сохраняют имя/VTEP на320px; длинные значения переносятся, меню экспорта видно без hover и имеет44px цель. Composite server/tunnel ID и неизменяемый export snapshot сохранены.
|
||||
|
||||
Профиль1000 туннелей/227787 JSON bytes:50 строк/2137 DOM nodes/1249ms ready в локальном dev с HTTP-моками. Проверены page20/refresh, поиск записи1000/глобальный VNI sort,503/cache/unknown/page,320px/закрепление имени/axe, экспорт устаревшего snapshot и1000→1 с точным VNI1000.22 browser (large/table/links/freshness/GRE-VXLAN layouts) прошли. TypeScript без incremental/ESLint и production frontend build прошли. [Снимок320px](ux-ui/screens/large-vxlan-320.png) просмотрен.
|
||||
|
||||
Осталось16 manualPagination:true specialized grids, включая bounded/demo источники. VXLAN поиск пока локальный; server/tunnel URL контекст сохранён. Следующий блок12.3.35: GRE tunnels1000/50 DOM/search/sort/refresh/действия/320px. OSPF neighbors сопровождаются большим SVG графом, поэтому ограничение одной таблицы не докажет производительность всего экрана; отдельный аудит topology остаётся. Общая main/context после delta и внешняя12.5 отдельно. Коммит локальный без push.
|
||||
|
||||
## 12.3.33 — достоверное чтение и контекст WireGuard (2026-10-04)
|
||||
|
||||
|
||||
@@ -454,3 +454,12 @@ Mounted/revision guards исключают позднее чтение/ошиб
|
||||
|
||||
Scope proof ограничен HTTP-моками и read/toggle context сценариями; реальный RouterOS/PG не проверены. Backend fallback running/disabled/type и остальные source-context операции требуют дальнейшего аудита, strict frontend не доказывает достоверность отсутствующих raw RouterOS flags. Следующий блок12.3.34: VXLAN1000/50 DOM/refresh/search/sort/export/320px; затем остальные17 specialized grids и общая main/context приёмка. Внешняя12.5 отдельно. Коммит локальный без push.
|
||||
|
||||
|
||||
## 12.3.34 — большой каталог VXLAN (2026-10-04)
|
||||
|
||||
Полный /vxlan API не ограничен страницей. Таблица использует client pagination50, global sort, сохранение страницы при refresh и clamp после поиска/сокращения. ReUI ScrollArea/start pinning сохраняют имя/VTEP на320px; длинные значения переносятся, меню экспорта видно без hover и имеет44px цель. Composite server/tunnel ID и неизменяемый export snapshot сохранены.
|
||||
|
||||
Профиль1000 туннелей/227787 JSON bytes:50 строк/2137 DOM nodes/1249ms ready в локальном dev с HTTP-моками. Проверены page20/refresh, поиск записи1000/глобальный VNI sort,503/cache/unknown/page,320px/закрепление имени/axe, экспорт устаревшего snapshot и1000→1 с точным VNI1000.22 browser (large/table/links/freshness/GRE-VXLAN layouts) прошли. TypeScript без incremental/ESLint и production frontend build прошли. [Снимок320px](ux-ui/screens/large-vxlan-320.png) просмотрен.
|
||||
|
||||
Осталось16 manualPagination:true specialized grids, включая bounded/demo источники. VXLAN поиск пока локальный; server/tunnel URL контекст сохранён. Следующий блок12.3.35: GRE tunnels1000/50 DOM/search/sort/refresh/действия/320px. OSPF neighbors сопровождаются большим SVG графом, поэтому ограничение одной таблицы не докажет производительность всего экрана; отдельный аудит topology остаётся. Общая main/context после delta и внешняя12.5 отдельно. Коммит локальный без push.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -0,0 +1,31 @@
|
||||
import { test, expect } from "@playwright/test"
|
||||
import { vxlanResponseSchema } from "../../lib/vxlan-response"
|
||||
import axe from "axe-core"
|
||||
test("VXLAN1000: page/refresh/full search/sort/cache/export/320px",async({page},info)=>{
|
||||
test.setTimeout(90000)
|
||||
let tunnels=Array.from({length:1000},(_,i)=>({id:"*"+(i+1),name:"vx-test-"+String(i+1).padStart(4,"0"),serverId:"1",vni:i+1,port:0,dstPort:8472,vtepIp:"192.0.2.1",remoteVteps:["198.51.100.1"],l2mtu:1500,arpProxy:false,macLearning:true,comment:"",enabled:true,status:"up"}))
|
||||
let failed=false,calls=0;const writes:string[]=[]
|
||||
await page.route("**/health",r=>r.fulfill({json:{ok:true}}))
|
||||
await page.route("**/api/**",r=>{const p=new URL(r.request().url()).pathname;if(r.request().method()!=="GET")writes.push(p);if(p==="/api/vxlan"){calls++;return r.fulfill(failed?{status:503,json:{error:"Опрос VXLAN недоступен"}}:{json:vxlanResponseSchema.parse({tunnels})})}return r.fulfill({json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[{id:1,name:"Роутер",host:"192.0.2.1",country:"RU",enabled:true,status:null}]:{}})})
|
||||
const started=Date.now();await page.goto("/vxlan?server=1&keep=1")
|
||||
const rows=page.locator("tr[data-row-id]");await expect(rows).toHaveCount(50)
|
||||
const profile={count:tunnels.length,jsonBytes:Buffer.byteLength(JSON.stringify(tunnels)),rows:await rows.count(),nodes:await page.locator("*").count(),readyMs:Date.now()-started};console.log("VXLAN profile",JSON.stringify(profile));await info.attach("profile",{body:JSON.stringify(profile),contentType:"application/json"})
|
||||
const next=page.getByRole("button",{name:"Следующая страница",exact:true})
|
||||
for(let i=0;i<19;i++)await next.click()
|
||||
await expect(next).toBeDisabled();await expect(rows.first()).toContainText("vx-test-0951")
|
||||
const before=calls;await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect.poll(()=>calls).toBeGreaterThan(before);await expect(rows.first()).toContainText("vx-test-0951")
|
||||
const search=page.getByPlaceholder("Поиск по имени, VNI, серверу…");await search.fill("vx-test-1000");await expect(rows).toHaveCount(1);await expect(rows.first()).toContainText("vx-test-1000");await search.fill("");await expect(rows).toHaveCount(50)
|
||||
await page.getByRole("table").getByRole("button",{name:"VNI",exact:true}).click();await expect(rows.first()).toContainText("vx-test-1000")
|
||||
await next.click();const previous=await rows.first().getAttribute("data-row-id")
|
||||
failed=true;await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(page.getByText("Ошибка загрузки: Опрос VXLAN недоступен",{exact:true})).toBeVisible();await expect(rows).toHaveCount(50);await expect(rows.first()).toHaveAttribute("data-row-id",previous!);await expect(rows.first()).toContainText("Неизвестно")
|
||||
await page.setViewportSize({width:320,height:1000})
|
||||
const action=rows.first().getByRole("button",{name:/Действия:/}),scroll=page.locator('[data-slot="data-grid"] [data-slot="scroll-area-viewport"]')
|
||||
await action.scrollIntoViewIfNeeded();await scroll.evaluate(el=>{el.scrollLeft=el.scrollWidth});await expect(action).toBeInViewport()
|
||||
expect(await rows.first().getByRole("cell").first().evaluate(el=>{const a=el.getBoundingClientRect(),v=el.closest('[data-slot="scroll-area-viewport"]')!.getBoundingClientRect();return a.left>=v.left-1&&a.right<=v.right+1})).toBe(true)
|
||||
await expect.poll(()=>page.evaluate(()=>document.documentElement.scrollWidth)).toBeLessThanOrEqual(320)
|
||||
await page.addScriptTag({content:axe.source});expect((await page.evaluate(async()=>(window as unknown as {axe:typeof axe}).axe.run(document.querySelector('[data-slot="data-grid"]')!,{runOnly:{type:"tag",values:["wcag2a","wcag2aa","wcag21a","wcag21aa"]}}))).violations).toEqual([])
|
||||
await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:info.outputPath("vxlan-320.png"),animations:"disabled"})
|
||||
await action.click();await page.getByRole("menuitem",{name:"Экспорт .rsc",exact:true}).click();await expect(page.getByRole("dialog")).toContainText("актуальность не подтверждена");await page.keyboard.press("Escape")
|
||||
failed=false;tunnels=[tunnels[999]];await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(rows).toHaveCount(1);await expect(rows.first()).toContainText("vx-test-1000")
|
||||
await action.click();await page.getByRole("menuitem",{name:"Экспорт .rsc",exact:true}).click();await expect(page.getByRole("dialog")).toContainText("vni=1000");await expect(page.getByRole("dialog")).toContainText("vx-test-1000");expect(writes).toEqual([])
|
||||
})
|
||||
Reference in new issue
Block a user