import React from "react";
import { render } from "@testing-library/react-native";
import { Path } from "react-native-svg";
import { type IconNames, darkTokens } from "@jobber/design";
import { Icon } from ".";
import { AtlantisThemeContextProvider } from "../AtlantisThemeContext";
it("renders home icon", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders apple icon", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders large arrowDown icon", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders thumbsDown icon", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders small more icon", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders star icon with custom color", () => {
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("renders quote icon with themed color", () => {
// The intention is to make sure the color prop can be applied to an icon with a built-in default color
const tree = render().toJSON();
expect(tree).toMatchSnapshot();
});
it("applies testID prop to svg element", () => {
const { getByTestId } = render();
expect(getByTestId("home-icon")).toBeDefined();
});
it("applies name prop as testID when testID prop is not provided", () => {
const { getByTestId } = render();
expect(getByTestId("home")).toBeDefined();
});
it("renders an empty svg without throwing for an unknown icon name", () => {
const svg = render();
expect(svg.UNSAFE_root.findAllByType(Path)).toHaveLength(0);
});
it("renders the multi-color truck icon with its static fills", () => {
const svg = render();
const fills = svg.UNSAFE_root.findAllByType(Path).map(
path => path.props.fill as string,
);
expect(fills).toHaveLength(5);
expect(fills).toContain("#2B2B2B");
expect(fills.filter(fill => fill.startsWith("#"))).toHaveLength(4);
});
it("applies customColor to the truck body path but not its static artwork", () => {
const svg = render();
const fills = svg.UNSAFE_root.findAllByType(Path).map(
path => path.props.fill as string,
);
expect(fills).toHaveLength(5);
expect(fills.filter(fill => fill === "#abc123")).toHaveLength(1);
expect(fills).toEqual(
expect.arrayContaining(["#2B2B2B", "#000000", "#FFFFFF", "#2A2A2A"]),
);
});
describe("theme-aware fill", () => {
function getPathFills(svg: ReturnType) {
return svg.UNSAFE_root.findAllByType(Path).map(p => p.props.fill as string);
}
it("resolves the icon color to the dark-theme token under a dark theme", () => {
const expected = (darkTokens as Record)["color-icon"];
const svg = render(
,
);
expect(getPathFills(svg)[0]).toBe(expected);
expect(getPathFills(svg)[0]).not.toBe("hsl(198, 35%, 21%)");
});
it("resolves an icon's semantic default fill via live tokens when no color prop is given", () => {
// Regression check: semantic fills (e.g. quote -> color-quote) must
// resolve through their own token, not fall back to color-icon.
const expectedQuote = (darkTokens as Record)["color-quote"];
const fallbackIcon = (darkTokens as Record)["color-icon"];
const svg = render(
,
);
expect(getPathFills(svg)[0]).toBe(expectedQuote);
expect(getPathFills(svg)[0]).not.toBe(fallbackIcon);
});
it("defaults to the color-icon token when no color prop and no semantic default exist", () => {
const expected = (darkTokens as Record)["color-icon"];
const svg = render(
,
);
expect(getPathFills(svg)[0]).toBe(expected);
expect(getPathFills(svg)[0]).not.toBe("hsl(198, 35%, 21%)");
});
it("customColor still wins over theme tokens", () => {
const svg = render(
,
);
expect(getPathFills(svg)[0]).toBe("#f33323");
});
});