mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-29 01:51:38 -05:00
feat: surface option ids (#6339)
This commit is contained in:
committed by
GitHub
parent
3b07a6d013
commit
287c45f996
@@ -1,5 +1,5 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { cleanup, render } from "@testing-library/react";
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import { PictureSelectionResponse } from "./index";
|
||||
|
||||
@@ -7,7 +7,16 @@ import { PictureSelectionResponse } from "./index";
|
||||
vi.mock("next/image", () => ({
|
||||
__esModule: true,
|
||||
default: ({ src, alt, className }: { src: string; alt: string; className: string }) => (
|
||||
<img src={src} alt={alt} className={className} />
|
||||
<img src={src} alt={alt} className={className} data-testid="choice-image" />
|
||||
),
|
||||
}));
|
||||
|
||||
// Mock the IdBadge component
|
||||
vi.mock("@/modules/ui/components/id-badge", () => ({
|
||||
IdBadge: ({ id }: { id: string }) => (
|
||||
<div data-testid="id-badge" data-id={id}>
|
||||
ID: {id}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
@@ -33,7 +42,7 @@ describe("PictureSelectionResponse", () => {
|
||||
|
||||
test("renders images for selected choices", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice3"]} />
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice3"]} showId={false} />
|
||||
);
|
||||
|
||||
const images = container.querySelectorAll("img");
|
||||
@@ -44,13 +53,20 @@ describe("PictureSelectionResponse", () => {
|
||||
|
||||
test("renders nothing when selected is not an array", () => {
|
||||
// @ts-ignore - Testing invalid prop type
|
||||
const { container } = render(<PictureSelectionResponse choices={mockChoices} selected="choice1" />);
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected="choice1" showId={false} />
|
||||
);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
test("handles expanded layout", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice2"]} isExpanded={true} />
|
||||
<PictureSelectionResponse
|
||||
choices={mockChoices}
|
||||
selected={["choice1", "choice2"]}
|
||||
isExpanded={true}
|
||||
showId={false}
|
||||
/>
|
||||
);
|
||||
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
@@ -59,7 +75,12 @@ describe("PictureSelectionResponse", () => {
|
||||
|
||||
test("handles non-expanded layout", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice2"]} isExpanded={false} />
|
||||
<PictureSelectionResponse
|
||||
choices={mockChoices}
|
||||
selected={["choice1", "choice2"]}
|
||||
isExpanded={false}
|
||||
showId={false}
|
||||
/>
|
||||
);
|
||||
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
@@ -68,10 +89,75 @@ describe("PictureSelectionResponse", () => {
|
||||
|
||||
test("handles choices not in the mapping", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "nonExistentChoice"]} />
|
||||
<PictureSelectionResponse
|
||||
choices={mockChoices}
|
||||
selected={["choice1", "nonExistentChoice"]}
|
||||
showId={false}
|
||||
/>
|
||||
);
|
||||
|
||||
const images = container.querySelectorAll("img");
|
||||
expect(images).toHaveLength(1); // Only one valid image should be rendered
|
||||
});
|
||||
|
||||
test("shows IdBadge when showId=true", () => {
|
||||
render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice2"]} showId={true} />
|
||||
);
|
||||
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
expect(idBadges).toHaveLength(2);
|
||||
expect(idBadges[0]).toHaveAttribute("data-id", "choice1");
|
||||
expect(idBadges[1]).toHaveAttribute("data-id", "choice2");
|
||||
});
|
||||
|
||||
test("does not show IdBadge when showId=false", () => {
|
||||
render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice2"]} showId={false} />
|
||||
);
|
||||
|
||||
expect(screen.queryByTestId("id-badge")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies column layout when showId=true", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1"]} showId={true} />
|
||||
);
|
||||
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper).toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("does not apply column layout when showId=false", () => {
|
||||
const { container } = render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1"]} showId={false} />
|
||||
);
|
||||
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper).not.toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("renders images and IdBadges in same container when showId=true", () => {
|
||||
render(
|
||||
<PictureSelectionResponse choices={mockChoices} selected={["choice1", "choice2"]} showId={true} />
|
||||
);
|
||||
|
||||
const images = screen.getAllByTestId("choice-image");
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
|
||||
expect(images).toHaveLength(2);
|
||||
expect(idBadges).toHaveLength(2);
|
||||
|
||||
// Both images and badges should be in the same container
|
||||
const containers = screen.getAllByText("ID: choice1")[0].closest("div");
|
||||
expect(containers).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("handles default props correctly", () => {
|
||||
render(<PictureSelectionResponse choices={mockChoices} selected={["choice1"]} showId={false} />);
|
||||
|
||||
const images = screen.getAllByTestId("choice-image");
|
||||
expect(images).toHaveLength(1);
|
||||
expect(screen.queryByTestId("id-badge")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/cn";
|
||||
import { IdBadge } from "@/modules/ui/components/id-badge";
|
||||
import Image from "next/image";
|
||||
|
||||
interface PictureSelectionResponseProps {
|
||||
choices: { id: string; imageUrl: string }[];
|
||||
selected: string | number | string[];
|
||||
isExpanded?: boolean;
|
||||
showId: boolean;
|
||||
}
|
||||
|
||||
export const PictureSelectionResponse = ({
|
||||
choices,
|
||||
selected,
|
||||
isExpanded = true,
|
||||
showId,
|
||||
}: PictureSelectionResponseProps) => {
|
||||
if (typeof selected !== "object") return null;
|
||||
|
||||
@@ -25,17 +28,22 @@ export const PictureSelectionResponse = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("my-1 flex gap-x-5 gap-y-4", isExpanded ? "flex-wrap" : "")}>
|
||||
<div className={cn("my-1 flex gap-x-5 gap-y-4", isExpanded ? "flex-wrap" : "", showId ? "flex-col" : "")}>
|
||||
{selected.map((id) => (
|
||||
<div className="relative h-10 w-16" key={id}>
|
||||
<div className="flex items-center gap-2" key={id}>
|
||||
{choiceImageMapping[id] && (
|
||||
<Image
|
||||
src={choiceImageMapping[id]}
|
||||
alt={choiceImageMapping[id].split("/").pop() || "Image"}
|
||||
fill
|
||||
style={{ objectFit: "cover" }}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<>
|
||||
<div className="relative h-10 w-16">
|
||||
<Image
|
||||
src={choiceImageMapping[id]}
|
||||
alt={choiceImageMapping[id].split("/").pop() || "Image"}
|
||||
fill
|
||||
style={{ objectFit: "cover" }}
|
||||
className="rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
{showId && <IdBadge id={id} />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, test } from "vitest";
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import { RankingResponse } from "./index";
|
||||
|
||||
// Mock the IdBadge component
|
||||
vi.mock("@/modules/ui/components/id-badge", () => ({
|
||||
IdBadge: ({ id }: { id: string }) => (
|
||||
<div data-testid="id-badge" data-id={id}>
|
||||
ID: {id}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
describe("RankingResponse", () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test("renders ranked items correctly", () => {
|
||||
const rankedItems = ["Apple", "Banana", "Cherry"];
|
||||
test("renders ranked items correctly with new object format", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
{ value: "Cherry", id: "choice3" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} />);
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
expect(screen.getByText("#1")).toBeInTheDocument();
|
||||
expect(screen.getByText("#2")).toBeInTheDocument();
|
||||
@@ -21,10 +34,57 @@ describe("RankingResponse", () => {
|
||||
expect(screen.getByText("Cherry")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies expanded layout", () => {
|
||||
const rankedItems = ["Apple", "Banana"];
|
||||
test("renders ranked items with undefined id", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: undefined },
|
||||
{ value: "Cherry", id: "choice3" },
|
||||
];
|
||||
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} />);
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={true} />);
|
||||
|
||||
expect(screen.getByText("Apple")).toBeInTheDocument();
|
||||
expect(screen.getByText("Banana")).toBeInTheDocument();
|
||||
expect(screen.getByText("Cherry")).toBeInTheDocument();
|
||||
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
expect(idBadges).toHaveLength(2); // Only items with defined ids should have badges
|
||||
expect(idBadges[0]).toHaveAttribute("data-id", "choice1");
|
||||
expect(idBadges[1]).toHaveAttribute("data-id", "choice3");
|
||||
});
|
||||
|
||||
test("shows IdBadge when showId=true", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={true} />);
|
||||
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
expect(idBadges).toHaveLength(2);
|
||||
expect(idBadges[0]).toHaveAttribute("data-id", "choice1");
|
||||
expect(idBadges[1]).toHaveAttribute("data-id", "choice2");
|
||||
});
|
||||
|
||||
test("does not show IdBadge when showId=false", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
expect(screen.queryByTestId("id-badge")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies expanded layout", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
];
|
||||
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
const parentDiv = container.firstChild;
|
||||
expect(parentDiv).not.toHaveClass("flex");
|
||||
@@ -32,19 +92,44 @@ describe("RankingResponse", () => {
|
||||
});
|
||||
|
||||
test("applies non-expanded layout", () => {
|
||||
const rankedItems = ["Apple", "Banana"];
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
];
|
||||
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={false} />);
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={false} showId={false} />);
|
||||
|
||||
const parentDiv = container.firstChild;
|
||||
expect(parentDiv).toHaveClass("flex");
|
||||
expect(parentDiv).toHaveClass("space-x-2");
|
||||
});
|
||||
|
||||
test("handles empty values", () => {
|
||||
const rankedItems = ["Apple", "", "Cherry"];
|
||||
test("applies column layout when showId=true", () => {
|
||||
const rankedItems = [{ value: "Apple", id: "choice1" }];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} />);
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} showId={true} />);
|
||||
|
||||
const parentDiv = container.firstChild;
|
||||
expect(parentDiv).toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("does not apply column layout when showId=false", () => {
|
||||
const rankedItems = [{ value: "Apple", id: "choice1" }];
|
||||
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
const parentDiv = container.firstChild;
|
||||
expect(parentDiv).not.toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("handles empty values", () => {
|
||||
const rankedItems = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "", id: "choice2" },
|
||||
{ value: "Cherry", id: "choice3" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
expect(screen.getByText("#1")).toBeInTheDocument();
|
||||
expect(screen.getByText("#3")).toBeInTheDocument();
|
||||
@@ -54,9 +139,13 @@ describe("RankingResponse", () => {
|
||||
});
|
||||
|
||||
test("displays items in the correct order", () => {
|
||||
const rankedItems = ["First", "Second", "Third"];
|
||||
const rankedItems = [
|
||||
{ value: "First", id: "choice1" },
|
||||
{ value: "Second", id: "choice2" },
|
||||
{ value: "Third", id: "choice3" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} />);
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
const rankNumbers = screen.getAllByText(/^#\d$/);
|
||||
const rankItems = screen.getAllByText(/(First|Second|Third)/);
|
||||
@@ -72,11 +161,33 @@ describe("RankingResponse", () => {
|
||||
});
|
||||
|
||||
test("renders with RTL support", () => {
|
||||
const rankedItems = ["תפוח", "בננה", "דובדבן"];
|
||||
const rankedItems = [
|
||||
{ value: "תפוח", id: "choice1" },
|
||||
{ value: "בננה", id: "choice2" },
|
||||
{ value: "דובדבן", id: "choice3" },
|
||||
];
|
||||
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} />);
|
||||
const { container } = render(<RankingResponse value={rankedItems} isExpanded={true} showId={false} />);
|
||||
|
||||
const parentDiv = container.firstChild as HTMLElement;
|
||||
expect(parentDiv).toHaveAttribute("dir", "auto");
|
||||
});
|
||||
|
||||
test("renders items and badges together when showId=true", () => {
|
||||
const rankedItems = [
|
||||
{ value: "First", id: "choice1" },
|
||||
{ value: "Second", id: "choice2" },
|
||||
];
|
||||
|
||||
render(<RankingResponse value={rankedItems} isExpanded={true} showId={true} />);
|
||||
|
||||
// Check that both items and badges are rendered
|
||||
expect(screen.getByText("First")).toBeInTheDocument();
|
||||
expect(screen.getByText("Second")).toBeInTheDocument();
|
||||
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
expect(idBadges).toHaveLength(2);
|
||||
expect(idBadges[0]).toHaveAttribute("data-id", "choice1");
|
||||
expect(idBadges[1]).toHaveAttribute("data-id", "choice2");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import { cn } from "@/lib/cn";
|
||||
import { IdBadge } from "@/modules/ui/components/id-badge";
|
||||
|
||||
interface RankingResponseProps {
|
||||
value: string[];
|
||||
value: { value: string; id: string | undefined }[];
|
||||
isExpanded: boolean;
|
||||
showId: boolean;
|
||||
}
|
||||
|
||||
export const RankingResponse = ({ value, isExpanded }: RankingResponseProps) => {
|
||||
export const RankingResponse = ({ value, isExpanded, showId }: RankingResponseProps) => {
|
||||
return (
|
||||
<div className={cn("my-1 font-semibold text-slate-700", isExpanded ? "" : "flex space-x-2")} dir="auto">
|
||||
<div
|
||||
className={cn("text-slate-700", isExpanded ? "space-y-2" : "flex space-x-2", showId ? "flex-col" : "")}
|
||||
dir="auto">
|
||||
{value.map(
|
||||
(item, index) =>
|
||||
item && (
|
||||
<div key={index} className="mb-1 flex items-center">
|
||||
<span className="mr-2 text-slate-400">#{index + 1}</span>
|
||||
<div className="rounded bg-slate-100 px-2 py-1">{item}</div>
|
||||
item.value && (
|
||||
<div key={item.value} className="flex items-center space-x-2">
|
||||
<span className="text-slate-400">#{index + 1}</span>
|
||||
<div className="rounded bg-slate-100 px-2 py-1 font-semibold">{item.value}</div>
|
||||
{item.id && showId && <IdBadge id={item.id} />}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, test } from "vitest";
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import { ResponseBadges } from "./index";
|
||||
|
||||
// Mock the IdBadge component
|
||||
vi.mock("@/modules/ui/components/id-badge", () => ({
|
||||
IdBadge: ({ id }: { id: string }) => (
|
||||
<div data-testid="id-badge" data-id={id}>
|
||||
ID: {id}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
describe("ResponseBadges", () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test("renders string items correctly", () => {
|
||||
const items = ["Apple", "Banana", "Cherry"];
|
||||
render(<ResponseBadges items={items} />);
|
||||
test("renders items with value property correctly", () => {
|
||||
const items = [{ value: "Apple" }, { value: "Banana" }, { value: "Cherry" }];
|
||||
render(<ResponseBadges items={items} showId={false} />);
|
||||
|
||||
expect(screen.getByText("Apple")).toBeInTheDocument();
|
||||
expect(screen.getByText("Banana")).toBeInTheDocument();
|
||||
@@ -28,37 +37,109 @@ describe("ResponseBadges", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("renders number items correctly", () => {
|
||||
const items = [1, 2, 3];
|
||||
render(<ResponseBadges items={items} />);
|
||||
test("renders number items with value property correctly", () => {
|
||||
const items = [{ value: 1 }, { value: 2 }, { value: 3 }];
|
||||
render(<ResponseBadges items={items} showId={false} />);
|
||||
|
||||
expect(screen.getByText("1")).toBeInTheDocument();
|
||||
expect(screen.getByText("2")).toBeInTheDocument();
|
||||
expect(screen.getByText("3")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies expanded layout when isExpanded=true", () => {
|
||||
const items = ["Apple", "Banana", "Cherry"];
|
||||
test("renders items with id property and shows IdBadge when showId=true", () => {
|
||||
const items = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
{ value: "Cherry" }, // No id property
|
||||
];
|
||||
render(<ResponseBadges items={items} showId={true} />);
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} isExpanded={true} />);
|
||||
expect(screen.getByText("Apple")).toBeInTheDocument();
|
||||
expect(screen.getByText("Banana")).toBeInTheDocument();
|
||||
expect(screen.getByText("Cherry")).toBeInTheDocument();
|
||||
|
||||
// Should show IdBadges for items with id
|
||||
const idBadges = screen.getAllByTestId("id-badge");
|
||||
expect(idBadges).toHaveLength(2);
|
||||
expect(idBadges[0]).toHaveAttribute("data-id", "choice1");
|
||||
expect(idBadges[1]).toHaveAttribute("data-id", "choice2");
|
||||
});
|
||||
|
||||
test("does not render IdBadge when showId=false", () => {
|
||||
const items = [
|
||||
{ value: "Apple", id: "choice1" },
|
||||
{ value: "Banana", id: "choice2" },
|
||||
];
|
||||
render(<ResponseBadges items={items} showId={false} />);
|
||||
|
||||
expect(screen.getByText("Apple")).toBeInTheDocument();
|
||||
expect(screen.getByText("Banana")).toBeInTheDocument();
|
||||
|
||||
// Should not show IdBadges when showId=false
|
||||
expect(screen.queryByTestId("id-badge")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("does not render IdBadge when item has no id property", () => {
|
||||
const items = [{ value: "Apple" }, { value: "Banana" }];
|
||||
render(<ResponseBadges items={items} showId={true} />);
|
||||
|
||||
expect(screen.getByText("Apple")).toBeInTheDocument();
|
||||
expect(screen.getByText("Banana")).toBeInTheDocument();
|
||||
|
||||
// Should not show IdBadges when items have no id
|
||||
expect(screen.queryByTestId("id-badge")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies expanded layout when isExpanded=true", () => {
|
||||
const items = [{ value: "Apple" }, { value: "Banana" }, { value: "Cherry" }];
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} isExpanded={true} showId={false} />);
|
||||
|
||||
const wrapper = container.firstChild;
|
||||
expect(wrapper).toHaveClass("flex-wrap");
|
||||
});
|
||||
|
||||
test("does not apply expanded layout when isExpanded=false", () => {
|
||||
const items = ["Apple", "Banana", "Cherry"];
|
||||
const items = [{ value: "Apple" }, { value: "Banana" }, { value: "Cherry" }];
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} isExpanded={false} />);
|
||||
const { container } = render(<ResponseBadges items={items} isExpanded={false} showId={false} />);
|
||||
|
||||
const wrapper = container.firstChild;
|
||||
expect(wrapper).not.toHaveClass("flex-wrap");
|
||||
});
|
||||
|
||||
test("applies default styles correctly", () => {
|
||||
const items = ["Apple"];
|
||||
test("applies column layout when showId=true", () => {
|
||||
const items = [{ value: "Apple", id: "choice1" }];
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} />);
|
||||
const { container } = render(<ResponseBadges items={items} showId={true} />);
|
||||
|
||||
const wrapper = container.firstChild;
|
||||
expect(wrapper).toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("does not apply column layout when showId=false", () => {
|
||||
const items = [{ value: "Apple", id: "choice1" }];
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} showId={false} />);
|
||||
|
||||
const wrapper = container.firstChild;
|
||||
expect(wrapper).not.toHaveClass("flex-col");
|
||||
});
|
||||
|
||||
test("renders with icon when provided", () => {
|
||||
const items = [{ value: "Apple" }];
|
||||
const icon = <span data-testid="test-icon">📱</span>;
|
||||
|
||||
render(<ResponseBadges items={items} icon={icon} showId={false} />);
|
||||
|
||||
expect(screen.getByTestId("test-icon")).toBeInTheDocument();
|
||||
expect(screen.getByText("📱")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("applies default styles correctly", () => {
|
||||
const items = [{ value: "Apple" }];
|
||||
|
||||
const { container } = render(<ResponseBadges items={items} showId={false} />);
|
||||
|
||||
const wrapper = container.firstChild;
|
||||
expect(wrapper).toHaveClass("my-1");
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
import { cn } from "@/lib/cn";
|
||||
import { IdBadge } from "@/modules/ui/components/id-badge";
|
||||
import React from "react";
|
||||
|
||||
interface ResponseBadgesProps {
|
||||
items: string[] | number[];
|
||||
items: { value: string | number; id?: string }[];
|
||||
isExpanded?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
showId: boolean;
|
||||
}
|
||||
|
||||
export const ResponseBadges: React.FC<ResponseBadgesProps> = ({ items, isExpanded = false, icon }) => {
|
||||
export const ResponseBadges: React.FC<ResponseBadgesProps> = ({
|
||||
items,
|
||||
isExpanded = false,
|
||||
icon,
|
||||
showId,
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn("my-1 flex gap-2", isExpanded ? "flex-wrap" : "")}>
|
||||
<div className={cn("my-1 flex gap-2", isExpanded ? "flex-wrap" : "", showId ? "flex-col" : "")}>
|
||||
{items.map((item, index) => (
|
||||
<span key={index} className="flex items-center rounded-md bg-slate-200 px-2 py-1 font-medium">
|
||||
{icon && <span className="mr-1.5">{icon}</span>}
|
||||
{item}
|
||||
</span>
|
||||
<div key={`${item.value}-${index}`} className={cn("flex items-center gap-2")}>
|
||||
<span className="flex items-center rounded-md bg-slate-200 px-2 py-1 font-medium">
|
||||
{icon && <span className="mr-1.5">{icon}</span>}
|
||||
{item.value}
|
||||
</span>
|
||||
{item.id && showId && <IdBadge id={item.id} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user