nexus/ui/src/components/SkillCard.test.tsx
Mikkel Georgsen 86d4de87e3 feat(12-02): StarRating component, API extensions, DesignGuide entry
- Create StarRating component with interactive/readonly modes, amber stars, size sm/md
- Add PersonalRating type and taskCount/avgCostUsd/lastUsedAt to SkillListItem
- Add getRatings and addRating to skillRegistryApi
- Add Rating System section to DesignGuide with all variants
- Fix SkillCard fixture and DesignGuide examples to include new SkillListItem fields
2026-04-04 03:55:42 +00:00

81 lines
2.5 KiB
TypeScript

// @vitest-environment node
import { describe, expect, it, vi } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";
import { SkillCard } from "./SkillCard";
import type { SkillListItem } from "../api/skillRegistry";
// Stub @/lib/router Link as an <a> tag for SSR
vi.mock("@/lib/router", () => ({
Link: ({ to, children, ...props }: { to: string; children: React.ReactNode; [key: string]: unknown }) =>
<a href={to as string} {...props}>{children}</a>,
}));
const mockSkill: SkillListItem = {
id: "test-source/test-skill",
name: "Test Skill",
description: "A test skill for unit testing",
sourceId: "test-source",
category: "testing",
activeVersionId: null,
removedAt: null,
averageRating: 4.2,
ratingCount: 10,
taskCount: null,
avgCostUsd: null,
lastUsedAt: null,
};
describe("SkillCard", () => {
it("renders skill name as a link", () => {
const html = renderToStaticMarkup(<SkillCard skill={mockSkill} />);
expect(html).toContain("Test Skill");
expect(html).toContain("skills/detail/");
});
it("renders source badge", () => {
const html = renderToStaticMarkup(<SkillCard skill={mockSkill} />);
expect(html).toContain("test-source");
});
it("renders star rating when averageRating is non-null", () => {
const html = renderToStaticMarkup(<SkillCard skill={mockSkill} />);
expect(html).toContain("4.2");
});
it("shows Install skill button when not installed", () => {
const html = renderToStaticMarkup(
<SkillCard skill={mockSkill} onInstall={() => {}} />,
);
expect(html).toContain("Install skill");
});
it("shows Update skill button when installed with update", () => {
const html = renderToStaticMarkup(
<SkillCard skill={mockSkill} isInstalled hasUpdate onUpdate={() => {}} />,
);
expect(html).toContain("Update skill");
});
it("shows update badge when hasUpdate is true", () => {
const html = renderToStaticMarkup(
<SkillCard skill={mockSkill} isInstalled hasUpdate onUpdate={() => {}} />,
);
expect(html).toContain("Update");
expect(html).toContain("amber");
});
it("shows check icon when installed without update", () => {
const html = renderToStaticMarkup(
<SkillCard skill={mockSkill} isInstalled />,
);
expect(html).toContain("Installed");
});
it("shows loading state on install button", () => {
const html = renderToStaticMarkup(
<SkillCard skill={mockSkill} onInstall={() => {}} isLoading />,
);
expect(html).toContain("Installing");
});
});