Expose builder chip selection beyond color, raise unselected contrast, and make the five-value limit visible.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -125,4 +125,32 @@ describe("ApplicableScopeField behavior", () => {
|
||||
|
||||
expect(screen.queryByAltText("Help")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("exposes selected state on chips and keeps unselected chips enabled", () => {
|
||||
renderWithProviders(<ApplicableScopeField {...baseProps} />);
|
||||
|
||||
const selected = screen.getByRole("button", { name: /Deselect Finance/i });
|
||||
const unselected = screen.getByRole("button", {
|
||||
name: /Select Operations/i,
|
||||
});
|
||||
|
||||
expect(selected).toHaveAttribute("aria-pressed", "true");
|
||||
expect(selected).toBeEnabled();
|
||||
expect(unselected).toHaveAttribute("aria-pressed", "false");
|
||||
expect(unselected).toBeEnabled();
|
||||
});
|
||||
|
||||
it("uses a real disabled state when readOnly", () => {
|
||||
renderWithProviders(<ApplicableScopeField {...baseProps} readOnly />);
|
||||
|
||||
expect(
|
||||
screen.getByRole("button", { name: /Deselect Finance/i }),
|
||||
).toBeDisabled();
|
||||
expect(
|
||||
screen.getByRole("button", { name: /Select Operations/i }),
|
||||
).toBeDisabled();
|
||||
expect(
|
||||
screen.queryByRole("button", { name: /Add Applicable Scope/i }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { describe } from "vitest";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { screen } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import {
|
||||
componentTestSuite,
|
||||
type ComponentTestSuiteConfig,
|
||||
} from "../utils/componentTestSuite";
|
||||
import { renderWithProviders as render } from "../utils/test-utils";
|
||||
import Chip from "../../app/components/controls/Chip";
|
||||
|
||||
type Props = React.ComponentProps<typeof Chip>;
|
||||
@@ -30,4 +33,18 @@ const config: ComponentTestSuiteConfig<Props> = {
|
||||
|
||||
describe("Chip", () => {
|
||||
componentTestSuite<Props>(config);
|
||||
|
||||
it("exposes aria-pressed false when unselected", () => {
|
||||
render(<Chip label="Worker cooperative" state="unselected" />);
|
||||
const chip = screen.getByRole("button", { name: "Worker cooperative" });
|
||||
expect(chip).toHaveAttribute("aria-pressed", "false");
|
||||
expect(chip.querySelector("svg")).toBeNull();
|
||||
});
|
||||
|
||||
it("exposes aria-pressed and a check mark when selected", () => {
|
||||
render(<Chip label="Worker cooperative" state="selected" />);
|
||||
const chip = screen.getByRole("button", { name: "Worker cooperative" });
|
||||
expect(chip).toHaveAttribute("aria-pressed", "true");
|
||||
expect(chip.querySelector("svg[aria-hidden]")).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { screen } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { renderWithProviders } from "../utils/test-utils";
|
||||
import { CommunityStructureSelectScreen } from "../../app/(app)/create/screens/select/CommunityStructureSelectScreen";
|
||||
|
||||
describe("CommunityStructureSelectScreen", () => {
|
||||
it("does not render dummy help icons", () => {
|
||||
renderWithProviders(<CommunityStructureSelectScreen />);
|
||||
|
||||
expect(screen.getByText("Organization Type")).toBeInTheDocument();
|
||||
expect(screen.getByText("Scale")).toBeInTheDocument();
|
||||
expect(screen.getByText("Maturity")).toBeInTheDocument();
|
||||
expect(screen.queryByAltText("Help")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -389,4 +389,38 @@ describe("CoreValuesSelectScreen", () => {
|
||||
expect(countCustomChips(CUSTOM_LABEL)).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("five-value limit", () => {
|
||||
async function addPresetValue(label: string) {
|
||||
fireEvent.click(screen.getByText(label));
|
||||
const dialog = await screen.findByRole("dialog");
|
||||
fireEvent.click(within(dialog).getByRole("button", { name: "Add Value" }));
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
}
|
||||
|
||||
it("shows a counter, disables remaining chips, and announces the limit", async () => {
|
||||
renderWithProviders(<CoreValuesSelectScreen />);
|
||||
expect(screen.getByText("0 of 5")).toBeInTheDocument();
|
||||
|
||||
await addPresetValue("Accessibility");
|
||||
await addPresetValue("Accountability");
|
||||
await addPresetValue("Adaptability");
|
||||
await addPresetValue("Agency");
|
||||
await addPresetValue("Altruism");
|
||||
|
||||
expect(screen.getByText("5 of 5")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"Five of five values selected. Remaining values are unavailable until one is removed.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole("button", { name: "Anti-oppression" }),
|
||||
).toBeDisabled();
|
||||
expect(screen.getByRole("button", { name: "Add value" })).toBeDisabled();
|
||||
expect(screen.getByRole("button", { name: /^add$/i })).toBeDisabled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,6 +123,44 @@ describe("MultiSelect – behaviour specifics", () => {
|
||||
expect(helpIcon).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not show a help icon by default", () => {
|
||||
render(<MultiSelect options={defaultChipOptions} label="Test Label" />);
|
||||
expect(screen.queryByAltText("Help")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("disables leftover chips and add when maxSelections is reached", async () => {
|
||||
const handleChipClick = vi.fn();
|
||||
const handleAddClick = vi.fn();
|
||||
const options = [
|
||||
{ id: "1", label: "One", state: "selected" as const },
|
||||
{ id: "2", label: "Two", state: "selected" as const },
|
||||
{ id: "3", label: "Three", state: "unselected" as const },
|
||||
];
|
||||
render(
|
||||
<MultiSelect
|
||||
options={options}
|
||||
onChipClick={handleChipClick}
|
||||
onAddClick={handleAddClick}
|
||||
addButton
|
||||
addButtonText="Add option"
|
||||
maxSelections={2}
|
||||
selectionCountText="2 of 2"
|
||||
limitReachedAnnouncement="Limit reached"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText("2 of 2")).toBeInTheDocument();
|
||||
expect(screen.getByText("Limit reached")).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "One" })).toBeEnabled();
|
||||
expect(screen.getByRole("button", { name: "Three" })).toBeDisabled();
|
||||
expect(screen.getByRole("button", { name: "Add option" })).toBeDisabled();
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "Three" }));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Add option" }));
|
||||
expect(handleChipClick).not.toHaveBeenCalled();
|
||||
expect(handleAddClick).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders add button text when provided", () => {
|
||||
render(
|
||||
<MultiSelect
|
||||
|
||||
Reference in New Issue
Block a user