fix(network-topology): harden with edge-case fixes, logging, and test coverage (#583)

* fix(network-topology): harden with edge-case fixes, logging, and test coverage

Fixes stale data on node switch (topology now refreshes when active node changes),
adds manual refresh button to toolbar, and guards against containers with empty
Names arrays by falling back to a 12-char short ID. Adds operational and diagnostic
logging around topology fetches, and introduces 25 unit tests covering happy paths,
system network filtering, stack resolution, container deduplication, edge cases,
and error handling.

* docs: refresh screenshots
This commit is contained in:
Anso
2026-04-14 10:59:11 -04:00
committed by GitHub
parent 5bc709fc25
commit 23fc702296
8 changed files with 616 additions and 3 deletions
@@ -16,10 +16,11 @@ import '@xyflow/react/dist/style.css';
import dagre from '@dagrejs/dagre';
import { apiFetch } from '@/lib/api';
import { toast } from '@/components/ui/toast-store';
import { Container, Network, Loader2 } from 'lucide-react';
import { Container, Network, Loader2, RefreshCw } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
// ── Types ─────────────────────────────────────────────────────────────────────
@@ -309,6 +310,16 @@ export default function NetworkTopologyView({ onContainerClick }: NetworkTopolog
<Label htmlFor="show-system" className="text-xs cursor-pointer">
Show system networks
</Label>
<Button
variant="ghost"
size="icon"
className="ml-auto h-7 w-7"
onClick={() => fetchTopology()}
disabled={loading}
aria-label="Refresh topology"
>
<RefreshCw className={cn('w-3.5 h-3.5', loading && 'animate-spin')} strokeWidth={1.5} />
</Button>
</div>
<div className="h-[500px] w-full">
<ReactFlow
@@ -841,6 +841,7 @@ export default function ResourcesView() {
</div>
}>
<NetworkTopologyView
key={activeNode?.id}
onContainerClick={(id, name) => {
window.dispatchEvent(new CustomEvent<SenchoOpenLogsDetail>(SENCHO_OPEN_LOGS_EVENT, {
detail: { containerId: id, containerName: name },