Create and adjust rule card tests
This commit is contained in:
@@ -77,6 +77,7 @@ function MultiSelectView({
|
|||||||
{showAddButton && (
|
{showAddButton && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
aria-label={addButtonText || "Add option"}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onAddClick?.();
|
onAddClick?.();
|
||||||
|
|||||||
+92
-25
@@ -43,8 +43,6 @@ export default {
|
|||||||
description: "Size variant of the card",
|
description: "Size variant of the card",
|
||||||
},
|
},
|
||||||
onClick: { action: "clicked" },
|
onClick: { action: "clicked" },
|
||||||
onPillClick: { action: "pillClicked" },
|
|
||||||
onCreateClick: { action: "createClicked" },
|
|
||||||
},
|
},
|
||||||
tags: ["autodocs"],
|
tags: ["autodocs"],
|
||||||
};
|
};
|
||||||
@@ -82,28 +80,69 @@ export const Expanded = {
|
|||||||
categories: [
|
categories: [
|
||||||
{
|
{
|
||||||
name: "Values",
|
name: "Values",
|
||||||
items: ["Consciousness", "Ecology", "Abundance", "Art", "Decisiveness"],
|
chipOptions: [
|
||||||
createUrl: "/create/value",
|
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||||
|
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||||
|
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||||
|
{ id: "values-4", label: "Art", state: "Unselected" },
|
||||||
|
{ id: "values-5", label: "Decisiveness", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Communication",
|
name: "Communication",
|
||||||
items: ["Signal"],
|
chipOptions: [
|
||||||
createUrl: "/create/communication",
|
{ id: "comm-1", label: "Signal", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Membership",
|
name: "Membership",
|
||||||
items: ["Open Admission"],
|
chipOptions: [
|
||||||
createUrl: "/create/membership",
|
{ id: "membership-1", label: "Open Admission", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Decision-making",
|
name: "Decision-making",
|
||||||
items: ["Lazy Consensus", "Modified Consensus"],
|
chipOptions: [
|
||||||
createUrl: "/create/decision-making",
|
{ id: "decision-1", label: "Lazy Consensus", state: "Unselected" },
|
||||||
|
{ id: "decision-2", label: "Modified Consensus", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Conflict management",
|
name: "Conflict management",
|
||||||
items: ["Code of Conduct", "Restorative Justice"],
|
chipOptions: [
|
||||||
createUrl: "/create/conflict-management",
|
{ id: "conflict-1", label: "Code of Conduct", state: "Unselected" },
|
||||||
|
{ id: "conflict-2", label: "Restorative Justice", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -160,23 +199,39 @@ export const ExpandedMedium = {
|
|||||||
categories: [
|
categories: [
|
||||||
{
|
{
|
||||||
name: "Values",
|
name: "Values",
|
||||||
items: ["Consciousness", "Ecology", "Abundance", "Art", "Decisiveness"],
|
chipOptions: [
|
||||||
|
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||||
|
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||||
|
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||||
|
{ id: "values-4", label: "Art", state: "Unselected" },
|
||||||
|
{ id: "values-5", label: "Decisiveness", state: "Unselected" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Communication",
|
name: "Communication",
|
||||||
items: ["Signal"],
|
chipOptions: [
|
||||||
|
{ id: "comm-1", label: "Signal", state: "Unselected" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Membership",
|
name: "Membership",
|
||||||
items: ["Open Admission"],
|
chipOptions: [
|
||||||
|
{ id: "membership-1", label: "Open Admission", state: "Unselected" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Decision-making",
|
name: "Decision-making",
|
||||||
items: ["Lazy Consensus", "Modified Consensus"],
|
chipOptions: [
|
||||||
|
{ id: "decision-1", label: "Lazy Consensus", state: "Unselected" },
|
||||||
|
{ id: "decision-2", label: "Modified Consensus", state: "Unselected" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Conflict management",
|
name: "Conflict management",
|
||||||
items: ["Code of Conduct", "Restorative Justice"],
|
chipOptions: [
|
||||||
|
{ id: "conflict-1", label: "Code of Conduct", state: "Unselected" },
|
||||||
|
{ id: "conflict-2", label: "Restorative Justice", state: "Unselected" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -286,19 +341,31 @@ export const InteractiveStates = {
|
|||||||
categories: [
|
categories: [
|
||||||
{
|
{
|
||||||
name: "Values",
|
name: "Values",
|
||||||
items: ["Consciousness", "Ecology", "Abundance"],
|
chipOptions: [
|
||||||
|
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||||
|
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||||
|
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Communication",
|
name: "Communication",
|
||||||
items: ["Signal"],
|
chipOptions: [
|
||||||
|
{ id: "comm-1", label: "Signal", state: "Unselected" },
|
||||||
|
],
|
||||||
|
onChipClick: (categoryName, chipId) => {
|
||||||
|
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||||
|
},
|
||||||
|
onAddClick: (categoryName) => {
|
||||||
|
console.log(`Add clicked: ${categoryName}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onPillClick: (category, item) => {
|
|
||||||
console.log(`Pill clicked: ${category} - ${item}`);
|
|
||||||
},
|
|
||||||
onCreateClick: (category) => {
|
|
||||||
console.log(`Create clicked: ${category}`);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
docs: {
|
docs: {
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { renderWithProviders as render } from "../utils/test-utils";
|
||||||
|
import InputLabel from "../../app/components/InputLabel";
|
||||||
|
import {
|
||||||
|
componentTestSuite,
|
||||||
|
type ComponentTestSuiteConfig,
|
||||||
|
} from "../utils/componentTestSuite";
|
||||||
|
|
||||||
|
type Props = React.ComponentProps<typeof InputLabel>;
|
||||||
|
|
||||||
|
const config: ComponentTestSuiteConfig<Props> = {
|
||||||
|
component: InputLabel,
|
||||||
|
name: "InputLabel",
|
||||||
|
props: {
|
||||||
|
label: "Test Label",
|
||||||
|
helpIcon: false,
|
||||||
|
asterisk: false,
|
||||||
|
helperText: false,
|
||||||
|
size: "S",
|
||||||
|
palette: "Default",
|
||||||
|
} as Props,
|
||||||
|
requiredProps: ["label"],
|
||||||
|
optionalProps: {
|
||||||
|
helpIcon: true,
|
||||||
|
asterisk: true,
|
||||||
|
helperText: true,
|
||||||
|
size: "M",
|
||||||
|
palette: "Inverse",
|
||||||
|
},
|
||||||
|
primaryRole: undefined, // InputLabel is not directly interactive
|
||||||
|
testCases: {
|
||||||
|
renders: true,
|
||||||
|
accessibility: true,
|
||||||
|
keyboardNavigation: false, // Not directly interactive
|
||||||
|
disabledState: false,
|
||||||
|
errorState: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
componentTestSuite<Props>(config);
|
||||||
|
|
||||||
|
describe("InputLabel – behaviour specifics", () => {
|
||||||
|
it("renders label text", () => {
|
||||||
|
render(<InputLabel label="Test Label" />);
|
||||||
|
expect(screen.getByText("Test Label")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows help icon when helpIcon is true", () => {
|
||||||
|
render(<InputLabel label="Test Label" helpIcon={true} />);
|
||||||
|
const helpIcon = screen.getByAltText("Help");
|
||||||
|
expect(helpIcon).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows asterisk when asterisk is true", () => {
|
||||||
|
render(<InputLabel label="Test Label" asterisk={true} />);
|
||||||
|
expect(screen.getByText("*")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows helper text when helperText is true", () => {
|
||||||
|
render(<InputLabel label="Test Label" helperText={true} />);
|
||||||
|
expect(screen.getByText("Optional text")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows custom helper text when helperText is a string", () => {
|
||||||
|
render(<InputLabel label="Test Label" helperText="Custom helper" />);
|
||||||
|
expect(screen.getByText("Custom helper")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies size S styling", () => {
|
||||||
|
render(<InputLabel label="Test Label" size="S" />);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label).toHaveClass("text-[length:var(--sizing-350,14px)]");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies size M styling", () => {
|
||||||
|
render(<InputLabel label="Test Label" size="M" />);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label).toHaveClass("text-[length:var(--sizing-400,16px)]");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies Default palette styling", () => {
|
||||||
|
render(<InputLabel label="Test Label" palette="Default" />);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label).toHaveClass(
|
||||||
|
"text-[color:var(--color-content-default-secondary,#d2d2d2)]",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies Inverse palette styling", () => {
|
||||||
|
render(<InputLabel label="Test Label" palette="Inverse" />);
|
||||||
|
const label = screen.getByText("Test Label");
|
||||||
|
expect(label).toHaveClass(
|
||||||
|
"text-[color:var(--color-content-inverse-secondary,#1f1f1f)]",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
import { renderWithProviders as render } from "../utils/test-utils";
|
||||||
|
import MultiSelect from "../../app/components/MultiSelect";
|
||||||
|
import {
|
||||||
|
componentTestSuite,
|
||||||
|
type ComponentTestSuiteConfig,
|
||||||
|
} from "../utils/componentTestSuite";
|
||||||
|
|
||||||
|
type Props = React.ComponentProps<typeof MultiSelect>;
|
||||||
|
|
||||||
|
const defaultChipOptions = [
|
||||||
|
{ id: "1", label: "Option 1", state: "Unselected" as const },
|
||||||
|
{ id: "2", label: "Option 2", state: "Selected" as const },
|
||||||
|
];
|
||||||
|
|
||||||
|
const config: ComponentTestSuiteConfig<Props> = {
|
||||||
|
component: MultiSelect,
|
||||||
|
name: "MultiSelect",
|
||||||
|
props: {
|
||||||
|
label: "Test Label",
|
||||||
|
showHelpIcon: false,
|
||||||
|
size: "S",
|
||||||
|
palette: "Default",
|
||||||
|
options: defaultChipOptions,
|
||||||
|
showAddButton: true,
|
||||||
|
addButtonText: "",
|
||||||
|
} as Props,
|
||||||
|
requiredProps: ["options"],
|
||||||
|
optionalProps: {
|
||||||
|
label: "Optional Label",
|
||||||
|
showHelpIcon: true,
|
||||||
|
size: "M",
|
||||||
|
palette: "Inverse",
|
||||||
|
onChipClick: vi.fn(),
|
||||||
|
onAddClick: vi.fn(),
|
||||||
|
showAddButton: false,
|
||||||
|
addButtonText: "Add",
|
||||||
|
},
|
||||||
|
primaryRole: undefined, // MultiSelect contains multiple interactive elements
|
||||||
|
testCases: {
|
||||||
|
renders: true,
|
||||||
|
accessibility: true,
|
||||||
|
keyboardNavigation: false, // Complex component with multiple interactive elements
|
||||||
|
disabledState: false,
|
||||||
|
errorState: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
componentTestSuite<Props>(config);
|
||||||
|
|
||||||
|
describe("MultiSelect – behaviour specifics", () => {
|
||||||
|
it("renders label when provided", () => {
|
||||||
|
render(<MultiSelect options={defaultChipOptions} label="Test Label" />);
|
||||||
|
expect(screen.getByText("Test Label")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders all chip options", () => {
|
||||||
|
render(<MultiSelect options={defaultChipOptions} />);
|
||||||
|
expect(screen.getByText("Option 1")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Option 2")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onChipClick when a chip is clicked", async () => {
|
||||||
|
const handleChipClick = vi.fn();
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
onChipClick={handleChipClick}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const chip = screen.getByText("Option 1");
|
||||||
|
await userEvent.click(chip);
|
||||||
|
|
||||||
|
expect(handleChipClick).toHaveBeenCalledWith("1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onAddClick when add button is clicked", async () => {
|
||||||
|
const handleAddClick = vi.fn();
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
onAddClick={handleAddClick}
|
||||||
|
showAddButton={true}
|
||||||
|
addButtonText="Add option"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const addButton = screen.getByRole("button", { name: "Add option" });
|
||||||
|
await userEvent.click(addButton);
|
||||||
|
|
||||||
|
expect(handleAddClick).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onAddClick when icon-only add button is clicked", async () => {
|
||||||
|
const handleAddClick = vi.fn();
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
onAddClick={handleAddClick}
|
||||||
|
showAddButton={true}
|
||||||
|
addButtonText=""
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const addButton = screen.getByRole("button", { name: "Add option" });
|
||||||
|
await userEvent.click(addButton);
|
||||||
|
|
||||||
|
expect(handleAddClick).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows help icon when showHelpIcon is true", () => {
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
label="Test Label"
|
||||||
|
showHelpIcon={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const helpIcon = screen.getByAltText("Help");
|
||||||
|
expect(helpIcon).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders add button text when provided", () => {
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
showAddButton={true}
|
||||||
|
addButtonText="Add option"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
expect(screen.getByText("Add option")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not render add button when showAddButton is false", () => {
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={defaultChipOptions}
|
||||||
|
showAddButton={false}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
expect(screen.queryByRole("button", { name: /add/i })).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles custom chip confirm", async () => {
|
||||||
|
const handleConfirm = vi.fn();
|
||||||
|
const customOptions = [
|
||||||
|
{ id: "custom-1", label: "", state: "Custom" as const },
|
||||||
|
];
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={customOptions}
|
||||||
|
onCustomChipConfirm={handleConfirm}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Type into the input first (check button is disabled until there's text)
|
||||||
|
const input = screen.getByPlaceholderText("Type to add");
|
||||||
|
await userEvent.type(input, "NewOption");
|
||||||
|
|
||||||
|
// Now the check button should be enabled
|
||||||
|
const checkButton = screen.getByRole("button", { name: "Confirm" });
|
||||||
|
expect(checkButton).not.toBeDisabled();
|
||||||
|
|
||||||
|
await userEvent.click(checkButton);
|
||||||
|
|
||||||
|
expect(handleConfirm).toHaveBeenCalledWith("custom-1", "NewOption");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles custom chip close", async () => {
|
||||||
|
const handleClose = vi.fn();
|
||||||
|
const customOptions = [
|
||||||
|
{ id: "custom-1", label: "", state: "Custom" as const },
|
||||||
|
];
|
||||||
|
render(
|
||||||
|
<MultiSelect
|
||||||
|
options={customOptions}
|
||||||
|
onCustomChipClose={handleClose}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const closeButton = screen.getByRole("button", { name: "Close" });
|
||||||
|
await userEvent.click(closeButton);
|
||||||
|
|
||||||
|
expect(handleClose).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -81,9 +81,8 @@ describe("RuleCard Component", () => {
|
|||||||
|
|
||||||
const card = screen.getByRole("button");
|
const card = screen.getByRole("button");
|
||||||
expect(card).toHaveClass(
|
expect(card).toHaveClass(
|
||||||
"hover:shadow-xl",
|
"hover:shadow-[0px_0px_64px_0px_rgba(0,0,0,0.15)]",
|
||||||
"hover:scale-[1.02]",
|
"transition-shadow",
|
||||||
"transition-all",
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -107,18 +106,19 @@ describe("RuleCard Component", () => {
|
|||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies proper responsive sizing", () => {
|
it("applies proper sizing for expanded states", () => {
|
||||||
render(<RuleCard {...defaultProps} />);
|
render(<RuleCard {...defaultProps} expanded={true} size="L" />);
|
||||||
|
|
||||||
const card = screen.getByRole("button");
|
const card = screen.getByRole("button");
|
||||||
expect(card).toHaveClass("md:h-[210px]", "lg:h-[277px]");
|
expect(card).toHaveClass("w-[568px]");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies focus styles correctly", () => {
|
it("applies proper accessibility attributes", () => {
|
||||||
render(<RuleCard {...defaultProps} />);
|
render(<RuleCard {...defaultProps} expanded={true} />);
|
||||||
|
|
||||||
const card = screen.getByRole("button");
|
const card = screen.getByRole("button");
|
||||||
expect(card).toHaveClass("focus:outline-none", "focus:ring-2");
|
expect(card).toHaveAttribute("aria-expanded", "true");
|
||||||
|
expect(card).toHaveAttribute("tabIndex", "0");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders without icon when not provided", () => {
|
it("renders without icon when not provided", () => {
|
||||||
@@ -131,7 +131,8 @@ describe("RuleCard Component", () => {
|
|||||||
render(<RuleCard {...defaultProps} />);
|
render(<RuleCard {...defaultProps} />);
|
||||||
|
|
||||||
const card = screen.getByRole("button");
|
const card = screen.getByRole("button");
|
||||||
expect(card).toHaveClass("shadow-lg", "backdrop-blur-sm");
|
expect(card).toHaveClass("shadow-[0px_0px_48px_0px_rgba(0,0,0,0.1)]");
|
||||||
|
expect(card).toHaveClass("rounded-[var(--radius-measures-radius-small)]");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maintains proper heading structure", () => {
|
it("maintains proper heading structure", () => {
|
||||||
@@ -142,10 +143,54 @@ describe("RuleCard Component", () => {
|
|||||||
expect(heading.tagName).toBe("H3");
|
expect(heading.tagName).toBe("H3");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies proper font classes", () => {
|
it("applies proper font classes for title", () => {
|
||||||
render(<RuleCard {...defaultProps} />);
|
render(<RuleCard {...defaultProps} size="L" />);
|
||||||
|
|
||||||
const heading = screen.getByRole("heading", { level: 3 });
|
const heading = screen.getByRole("heading", { level: 3 });
|
||||||
expect(heading).toHaveClass("font-space-grotesk", "font-bold");
|
expect(heading).toHaveClass("font-bricolage-grotesque", "font-extrabold");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders expanded state with categories", () => {
|
||||||
|
const categories = [
|
||||||
|
{
|
||||||
|
name: "Values",
|
||||||
|
chipOptions: [
|
||||||
|
{ id: "v1", label: "Consciousness", state: "Unselected" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
render(
|
||||||
|
<RuleCard
|
||||||
|
{...defaultProps}
|
||||||
|
expanded={true}
|
||||||
|
categories={categories}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText("Values")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders with logo URL", () => {
|
||||||
|
render(
|
||||||
|
<RuleCard
|
||||||
|
{...defaultProps}
|
||||||
|
logoUrl="http://localhost:3845/assets/test.png"
|
||||||
|
logoAlt="Test Logo"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const logo = screen.getByAltText("Test Logo");
|
||||||
|
expect(logo).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders with community initials fallback", () => {
|
||||||
|
render(
|
||||||
|
<RuleCard
|
||||||
|
{...defaultProps}
|
||||||
|
communityInitials="CE"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText("CE")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user