Files
fusion/packages/dashboard/app/components/__tests__/NodeStatusIndicator.test.tsx
gsxdsm c4a48491e2 feat(FN-1232): add remote node mesh dashboard integration
- Add core proxy API infrastructure (api-node.ts) with remote node communication
- Create NodeContext for centralized node state management
- Implement useNodeProxy hook for node operations (metrics, events, health)
- Implement useRemoteNodeData hook with 10-second polling for live metrics
- Implement useRemoteNodeEvents hook for real-time SSE event subscription
- Add NodeStatusIndicator component with animated status indicators
- Add comprehensive tests for all new hooks and components
- Update dashboard styles for node status visualization
2026-04-09 13:01:19 -07:00

156 lines
5.4 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { NodeStatusIndicator } from "../NodeStatusIndicator";
import type { NodeConfig } from "@fusion/core";
describe("NodeStatusIndicator", () => {
describe("when node is null", () => {
it("renders Local text badge", () => {
render(<NodeStatusIndicator node={null} />);
expect(screen.getByText("Local")).toBeInTheDocument();
expect(screen.getByText("Local")).toHaveClass("node-status-indicator__label");
});
it("does not show details when showDetails is true but node is null", () => {
render(<NodeStatusIndicator node={null} showDetails />);
expect(screen.getByText("Local")).toBeInTheDocument();
expect(screen.queryByText(/·/)).not.toBeInTheDocument();
});
});
describe("when node type is local", () => {
const localNode: NodeConfig = {
id: "node_local",
name: "Local Node",
type: "local",
status: "online",
maxConcurrent: 4,
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:00:00.000Z",
};
it("renders Local text badge", () => {
render(<NodeStatusIndicator node={localNode} />);
expect(screen.getByText("Local")).toBeInTheDocument();
});
it("does not show status dot for local nodes", () => {
const { container } = render(<NodeStatusIndicator node={localNode} />);
const dots = container.querySelectorAll(".node-status-indicator__dot");
expect(dots).toHaveLength(0);
});
it("renders with --local modifier class", () => {
render(<NodeStatusIndicator node={localNode} />);
const container = screen.getByText("Local").closest(".node-status-indicator");
expect(container).toHaveClass("node-status-indicator--local");
});
});
describe("when node type is remote", () => {
const remoteNode: NodeConfig = {
id: "node_abc123",
name: "Remote Server",
type: "remote",
url: "http://remote:4040",
status: "online",
maxConcurrent: 2,
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:00:00.000Z",
};
it("renders node name", () => {
render(<NodeStatusIndicator node={remoteNode} />);
expect(screen.getByText("Remote Server")).toBeInTheDocument();
});
it("shows green dot for online status", () => {
const { container } = render(<NodeStatusIndicator node={remoteNode} />);
const dot = container.querySelector(".node-status-indicator__dot--online");
expect(dot).toBeInTheDocument();
});
it("renders with --remote modifier class", () => {
render(<NodeStatusIndicator node={remoteNode} />);
const container = screen.getByText("Remote Server").closest(".node-status-indicator");
expect(container).toHaveClass("node-status-indicator--remote");
});
it("shows red dot for offline status", () => {
const offlineNode = { ...remoteNode, status: "offline" as const };
const { container } = render(<NodeStatusIndicator node={offlineNode} />);
const dot = container.querySelector(".node-status-indicator__dot--offline");
expect(dot).toBeInTheDocument();
});
it("shows red dot for error status", () => {
const errorNode = { ...remoteNode, status: "error" as const };
const { container } = render(<NodeStatusIndicator node={errorNode} />);
const dot = container.querySelector(".node-status-indicator__dot--error");
expect(dot).toBeInTheDocument();
});
it("shows yellow spinner for connecting status", () => {
const connectingNode = { ...remoteNode, status: "connecting" as const };
const { container } = render(<NodeStatusIndicator node={connectingNode} />);
const dot = container.querySelector(".node-status-indicator__dot--connecting");
expect(dot).toBeInTheDocument();
expect(dot?.querySelector(".node-status-indicator__spinner")).toBeInTheDocument();
});
});
describe("showDetails option", () => {
const remoteNode: NodeConfig = {
id: "node_abc123",
name: "Remote Server",
type: "remote",
url: "http://remote:4040",
status: "online",
maxConcurrent: 2,
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:00:00.000Z",
};
it("does not show details by default", () => {
render(<NodeStatusIndicator node={remoteNode} />);
expect(screen.queryByText(/·/)).not.toBeInTheDocument();
});
it("shows details when showDetails is true", () => {
render(<NodeStatusIndicator node={remoteNode} showDetails />);
const details = screen.getByText(/remote · Online/);
expect(details).toBeInTheDocument();
expect(details).toHaveClass("node-status-indicator__details");
});
it("shows correct details for offline status", () => {
const offlineNode = { ...remoteNode, status: "offline" as const };
render(<NodeStatusIndicator node={offlineNode} showDetails />);
const details = screen.getByText(/remote · Offline/);
expect(details).toBeInTheDocument();
});
it("shows correct details for connecting status", () => {
const connectingNode = { ...remoteNode, status: "connecting" as const };
render(<NodeStatusIndicator node={connectingNode} showDetails />);
const details = screen.getByText(/remote · Connecting/);
expect(details).toBeInTheDocument();
});
});
});