fix(web-hud): support hyphenated widget IDs with regression tests
Some checks failed
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/web Pipeline failed

This commit is contained in:
Jason Woltje
2026-02-17 15:49:09 -06:00
parent 4d089cd020
commit f4ad7eba37
4 changed files with 46 additions and 3 deletions

View File

@@ -73,7 +73,7 @@ export function HUD({ className = "" }: HUDProps): React.JSX.Element {
const handleAddWidget = (widgetType: WidgetRegistryKey): void => {
const widgetConfig = WIDGET_REGISTRY[widgetType];
const widgetId = `${widgetType.toLowerCase()}-${String(Date.now())}`;
const widgetId = `${widgetConfig.name}-${String(Date.now())}`;
// Find the next available position
const maxY = currentLayout?.layout.reduce((max, w): number => Math.max(max, w.y + w.h), 0) ?? 0;

View File

@@ -0,0 +1,37 @@
import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { WidgetRenderer } from "./WidgetRenderer";
import type { WidgetPlacement } from "@mosaic/shared";
vi.mock("@/components/widgets", () => ({
TasksWidget: ({ id }: { id: string }): React.JSX.Element => <div>Tasks Widget {id}</div>,
CalendarWidget: ({ id }: { id: string }): React.JSX.Element => <div>Calendar Widget {id}</div>,
QuickCaptureWidget: ({ id }: { id: string }): React.JSX.Element => (
<div>Quick Capture Widget {id}</div>
),
AgentStatusWidget: ({ id }: { id: string }): React.JSX.Element => (
<div>Agent Status Widget {id}</div>
),
}));
function createWidgetPlacement(id: string): WidgetPlacement {
return {
i: id,
x: 0,
y: 0,
w: 2,
h: 2,
};
}
describe("WidgetRenderer", () => {
it("renders hyphenated quick-capture widget IDs correctly", () => {
render(<WidgetRenderer widget={createWidgetPlacement("quick-capture-123")} />);
expect(screen.getByText("Quick Capture Widget quick-capture-123")).toBeInTheDocument();
});
it("renders hyphenated agent-status widget IDs correctly", () => {
render(<WidgetRenderer widget={createWidgetPlacement("agent-status-123")} />);
expect(screen.getByText("Agent Status Widget agent-status-123")).toBeInTheDocument();
});
});

View File

@@ -50,8 +50,12 @@ export function WidgetRenderer({
isEditing = false,
onRemove,
}: WidgetRendererProps): React.JSX.Element {
// Extract widget type from ID (e.g., "tasks-123" -> "tasks")
const widgetType = widget.i.split("-")[0] as keyof typeof WIDGET_COMPONENTS;
// Extract widget type from ID by removing the trailing unique suffix
// (e.g., "agent-status-123" -> "agent-status").
const separatorIndex = widget.i.lastIndexOf("-");
const widgetType = (
separatorIndex > 0 ? widget.i.substring(0, separatorIndex) : widget.i
) as keyof typeof WIDGET_COMPONENTS;
const WidgetComponent = WIDGET_COMPONENTS[widgetType];
const config = WIDGET_CONFIG[widgetType] || { displayName: "Widget", description: "" };