import React from "react";
import type { ReactNode } from "react";
import { render, screen, userEvent } from "@testing-library/react-native";
import { SelectItem, SelectItemPrefix, SelectItemSuffix } from "./SelectItem";
import { SelectTrigger } from "./SelectTrigger";
import { SelectRoot } from "../SelectRoot";
import { SelectPrimitive } from "../../primitives/Select";
import { Icon } from "../../Icon";
import { Text } from "../../Text";
import { PortalHostWrapper } from "../../utils/test";
import { tokens } from "../../utils/design";
const user = userEvent.setup();
beforeAll(() => {
const MockNativeMethods = require("react-native/jest/MockNativeMethods");
const mockedMethods = MockNativeMethods.default ?? MockNativeMethods;
mockedMethods.measure.mockImplementation(
(
callback: (
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => void,
) => {
callback(0, 0, 320, 48, 20, 100);
},
);
});
function renderItems(
items: ReactNode,
defaultValue?: { value: string; label: string },
onValueChange?: (option?: { value: string; label: string }) => void,
) {
return render(
{items}
,
{ wrapper: PortalHostWrapper },
);
}
async function openSelect() {
await user.press(screen.getByTestId("ATL-Select-Trigger"));
}
describe("Select.Item", () => {
it("renders the option label from the label prop", async () => {
renderItems();
await openSelect();
expect(screen.getByText("Toronto")).toBeDefined();
});
it("shows the default checkmark on the selected row only", async () => {
renderItems(
<>
>,
{ value: "tor", label: "Toronto" },
);
await openSelect();
// The indicator self-hides on unselected rows, so only the selected row's
// checkmark is in the tree.
expect(screen.getAllByTestId("checkmark")).toHaveLength(1);
});
it("renders prefix and suffix slots around the label", async () => {
renderItems(
}
suffix={
ON
}
/>,
);
await openSelect();
expect(screen.getByTestId("home")).toBeDefined();
expect(screen.getByText("ON")).toBeDefined();
expect(screen.getByText("Toronto")).toBeDefined();
});
it("shows the suffix alongside the checkmark on the selected row", async () => {
renderItems(
ON
}
/>,
{ value: "tor", label: "Toronto" },
);
await openSelect();
// The suffix coexists with the selected-state marker (it doesn't replace it).
expect(screen.getByText("ON")).toBeDefined();
expect(screen.getByTestId("checkmark")).toBeDefined();
});
it("overrides the default checkmark via the indicator prop", async () => {
renderItems(
}
/>,
{ value: "tor", label: "Toronto" },
);
await openSelect();
expect(screen.getByTestId("starFill")).toBeDefined();
expect(screen.queryByTestId("checkmark")).toBeNull();
});
it("selects an option on press (selection flows through the sugar)", async () => {
const onValueChange = jest.fn();
renderItems(
,
undefined,
onValueChange,
);
await openSelect();
await user.press(screen.getByText("Toronto"));
expect(onValueChange).toHaveBeenCalledWith({
value: "tor",
label: "Toronto",
});
});
it("greys a disabled option's label", async () => {
renderItems();
await openSelect();
expect(screen.getByText("Vancouver")).toHaveStyle({
color: tokens["color-disabled"],
});
});
});