mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-20 21:41:43 +10:00
The icon picker grid starts with an empty string entry that renders the "no icon" (prohibit) symbol, but the onClick guard "if (icon)" treated the empty string as falsy and ignored the click. Change the guard to check for a defined string value so the empty/no-icon option can be selected. Closes #3252 Closes #3261 Co-authored-by: Devin <devin@example.com> Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
// @vitest-environment happy-dom
|
|
|
|
import { fireEvent, render, screen } from "@testing-library/react";
|
|
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
import { i18n } from "@lingui/core";
|
|
import { I18nProvider } from "@lingui/react";
|
|
|
|
type GridProps = {
|
|
rowCount: number;
|
|
columnCount: number;
|
|
cellComponent: React.ComponentType<
|
|
{ rowIndex: number; columnIndex: number; style: React.CSSProperties } & Record<string, unknown>
|
|
>;
|
|
cellProps: Record<string, unknown>;
|
|
};
|
|
|
|
// react-window's <Grid> uses ResizeObserver / IntersectionObserver heavily and
|
|
// expects measurable layouts that happy-dom can't provide. Stub it with a simple
|
|
// pass-through that renders the first row of cells via the supplied cellComponent.
|
|
vi.mock("react-window", () => ({
|
|
Grid: ({ rowCount, columnCount, cellComponent: CellComponent, cellProps }: GridProps) => {
|
|
const cells: React.ReactNode[] = [];
|
|
for (let r = 0; r < Math.min(rowCount, 1); r++) {
|
|
for (let c = 0; c < columnCount; c++) {
|
|
cells.push(<CellComponent key={`${r}-${c}`} rowIndex={r} columnIndex={c} style={{}} {...cellProps} />);
|
|
}
|
|
}
|
|
return <div data-testid="grid">{cells}</div>;
|
|
},
|
|
}));
|
|
|
|
const { IconPicker } = await import("./icon-picker");
|
|
|
|
beforeAll(() => {
|
|
i18n.loadAndActivate({ locale: "en", messages: {} });
|
|
});
|
|
|
|
const renderPicker = (props: Partial<React.ComponentProps<typeof IconPicker>> = {}) =>
|
|
render(
|
|
<I18nProvider i18n={i18n}>
|
|
<IconPicker value="globe" onChange={vi.fn()} {...props} />
|
|
</I18nProvider>,
|
|
);
|
|
|
|
describe("IconPicker", () => {
|
|
it("renders a trigger button containing the current icon", () => {
|
|
const { container } = renderPicker();
|
|
const i = container.querySelector("i.ph") as HTMLElement;
|
|
expect(i.className).toContain("ph-globe");
|
|
});
|
|
|
|
it("changes the trigger icon when value prop changes", () => {
|
|
const { container, rerender } = renderPicker({ value: "globe" });
|
|
const before = container.querySelector("i.ph")?.className ?? "";
|
|
expect(before).toContain("ph-globe");
|
|
|
|
rerender(
|
|
<I18nProvider i18n={i18n}>
|
|
<IconPicker value="star" onChange={vi.fn()} />
|
|
</I18nProvider>,
|
|
);
|
|
|
|
const after = container.querySelector("i.ph")?.className ?? "";
|
|
expect(after).toContain("ph-star");
|
|
});
|
|
|
|
it("renders the picker button as a single icon-size button", () => {
|
|
const { container } = renderPicker();
|
|
expect(container.querySelectorAll("button").length).toBeGreaterThanOrEqual(1);
|
|
});
|
|
|
|
it("calls onChange with an empty string when the no-icon cell is clicked", () => {
|
|
const onChange = vi.fn();
|
|
render(
|
|
<I18nProvider i18n={i18n}>
|
|
<IconPicker value="globe" onChange={onChange} popoverProps={{ defaultOpen: true }} />
|
|
</I18nProvider>,
|
|
);
|
|
|
|
const firstCell = screen.getByTestId("grid").querySelector("button");
|
|
if (firstCell) fireEvent.click(firstCell);
|
|
expect(onChange).toHaveBeenCalledWith("");
|
|
});
|
|
});
|