281 lines
6.8 KiB
TypeScript
281 lines
6.8 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
|
|
import {
|
|
customJsxComponentByName,
|
|
customJsxComponentRegistry,
|
|
getCustomJsxBindingType,
|
|
} from "../core/component-registry";
|
|
|
|
const mantineCore941ComponentExports = [
|
|
"RemoveScroll",
|
|
"Collapse",
|
|
"ScrollArea",
|
|
"UnstyledButton",
|
|
"VisuallyHidden",
|
|
"Paper",
|
|
"Popover",
|
|
"ActionIcon",
|
|
"CloseButton",
|
|
"Group",
|
|
"Loader",
|
|
"Overlay",
|
|
"ModalBase",
|
|
"Input",
|
|
"InputBase",
|
|
"Flex",
|
|
"FloatingIndicator",
|
|
"Accordion",
|
|
"Affix",
|
|
"Alert",
|
|
"Anchor",
|
|
"AngleSlider",
|
|
"AppShell",
|
|
"AspectRatio",
|
|
"Autocomplete",
|
|
"Avatar",
|
|
"BackgroundImage",
|
|
"Badge",
|
|
"Blockquote",
|
|
"Breadcrumbs",
|
|
"Burger",
|
|
"Button",
|
|
"Card",
|
|
"Center",
|
|
"Checkbox",
|
|
"Chip",
|
|
"Code",
|
|
"ColorPicker",
|
|
"ColorInput",
|
|
"ColorSwatch",
|
|
"Combobox",
|
|
"ComboboxPopover",
|
|
"Container",
|
|
"CopyButton",
|
|
"DataList",
|
|
"Dialog",
|
|
"Divider",
|
|
"Drawer",
|
|
"EmptyState",
|
|
"Fieldset",
|
|
"FileButton",
|
|
"FileInput",
|
|
"FloatingWindow",
|
|
"FocusTrap",
|
|
"Grid",
|
|
"Highlight",
|
|
"HoverCard",
|
|
"Image",
|
|
"Indicator",
|
|
"JsonInput",
|
|
"Kbd",
|
|
"List",
|
|
"LoadingOverlay",
|
|
"Mark",
|
|
"Marquee",
|
|
"MaskInput",
|
|
"Menu",
|
|
"Menubar",
|
|
"Modal",
|
|
"MultiSelect",
|
|
"NativeSelect",
|
|
"NavLink",
|
|
"Notification",
|
|
"NumberFormatter",
|
|
"NumberInput",
|
|
"OverflowList",
|
|
"Pagination",
|
|
"PasswordInput",
|
|
"Pill",
|
|
"PillsInput",
|
|
"PinInput",
|
|
"Portal",
|
|
"Progress",
|
|
"Radio",
|
|
"Rating",
|
|
"RollingNumber",
|
|
"RingProgress",
|
|
"Scroller",
|
|
"SegmentedControl",
|
|
"Select",
|
|
"SemiCircleProgress",
|
|
"SimpleGrid",
|
|
"Skeleton",
|
|
"Slider",
|
|
"Space",
|
|
"Splitter",
|
|
"Spoiler",
|
|
"Stack",
|
|
"Stepper",
|
|
"Switch",
|
|
"Table",
|
|
"TableOfContents",
|
|
"Tabs",
|
|
"TagsInput",
|
|
"Text",
|
|
"Textarea",
|
|
"TextInput",
|
|
"ThemeIcon",
|
|
"Timeline",
|
|
"Title",
|
|
"Tooltip",
|
|
"Transition",
|
|
"Tree",
|
|
"TreeSelect",
|
|
"Typography",
|
|
] as const;
|
|
|
|
const mantineCharts941ComponentExports = [
|
|
"ChartTooltip",
|
|
"ChartLegend",
|
|
"AreaChart",
|
|
"BarChart",
|
|
"LineChart",
|
|
"Sparkline",
|
|
"DonutChart",
|
|
"PieChart",
|
|
"RadarChart",
|
|
"ScatterChart",
|
|
"BubbleChart",
|
|
"CompositeChart",
|
|
"RadialBarChart",
|
|
"FunnelChart",
|
|
"Heatmap",
|
|
"BarsList",
|
|
"Treemap",
|
|
"SankeyChart",
|
|
] as const;
|
|
|
|
const mantineDates941ComponentExports = [
|
|
"DatesProvider",
|
|
"HiddenDatesInput",
|
|
"TimeInput",
|
|
"TimePicker",
|
|
"TimeValue",
|
|
"Day",
|
|
"WeekdaysRow",
|
|
"Month",
|
|
"PickerControl",
|
|
"YearsList",
|
|
"MonthsList",
|
|
"CalendarHeader",
|
|
"DecadeLevel",
|
|
"YearLevel",
|
|
"MonthLevel",
|
|
"LevelsGroup",
|
|
"DecadeLevelGroup",
|
|
"YearLevelGroup",
|
|
"MonthLevelGroup",
|
|
"PickerInputBase",
|
|
"Calendar",
|
|
"YearPicker",
|
|
"MonthPicker",
|
|
"DatePicker",
|
|
"DateInput",
|
|
"DateTimePicker",
|
|
"InlineDateTimePicker",
|
|
"YearPickerInput",
|
|
"MonthPickerInput",
|
|
"DatePickerInput",
|
|
"TimeGrid",
|
|
"MiniCalendar",
|
|
] as const;
|
|
|
|
describe("customJsxComponentRegistry", () => {
|
|
test("classifies every component name exactly once", () => {
|
|
const names = customJsxComponentRegistry.map(({ name }) => name);
|
|
expect(new Set(names).size).toBe(names.length);
|
|
});
|
|
|
|
test.each([
|
|
["ChartTooltip", "wrapped"],
|
|
["ChartLegend", "wrapped"],
|
|
["VisuallyHidden", "wrapped"],
|
|
["SubFetch", "wrapped"],
|
|
["Portal", "denied"],
|
|
["TextInput", "wrapped"],
|
|
["ModalRoot", "denied"],
|
|
["AppShellMain", "denied"],
|
|
] as const)("classifies %s as %s", (name, safety) => {
|
|
expect(customJsxComponentByName.get(name)?.safety).toBe(safety);
|
|
});
|
|
|
|
test("documents why every denied component is unavailable", () => {
|
|
for (const component of customJsxComponentRegistry) {
|
|
if (component.safety === "denied") {
|
|
expect(component.reason, component.name).toBeTruthy();
|
|
}
|
|
}
|
|
});
|
|
|
|
test("publishes the minimal safe runtime metadata for every component", () => {
|
|
for (const component of customJsxComponentRegistry) {
|
|
expect(component.supportedProps, component.name).toBeInstanceOf(Array);
|
|
expect(component.blockedProps, component.name).toBeInstanceOf(Array);
|
|
expect(component.supportedProps, component.name).not.toContain("renderOption");
|
|
expect(component.supportedProps, component.name).not.toContain("rootRef");
|
|
expect(component.supportedProps, component.name).not.toContain("popoverTarget");
|
|
}
|
|
});
|
|
|
|
test.each([
|
|
["Tabs.List", "grow"],
|
|
["ScrollArea", "offsetScrollbars"],
|
|
["SubData", "fit"],
|
|
["SubData", "alt"],
|
|
] as const)("supports the %s.%s authoring prop", (component, prop) => {
|
|
expect(customJsxComponentByName.get(component)?.supportedProps).toContain(prop);
|
|
});
|
|
|
|
test.each([
|
|
...mantineCore941ComponentExports,
|
|
...mantineCharts941ComponentExports,
|
|
...mantineDates941ComponentExports,
|
|
])("classifies the Mantine 9.4.1 export %s", (name) => {
|
|
expect(customJsxComponentByName.has(name), `${name} is not classified`).toBe(true);
|
|
});
|
|
|
|
test.each([
|
|
["TextInput", "string"],
|
|
["NumberInput", "number"],
|
|
["Switch", "boolean"],
|
|
["Select", "string"],
|
|
["MultiSelect", "string[]"],
|
|
["DateInput", "string"],
|
|
["DatePicker", "string"],
|
|
["Tabs", "string"],
|
|
["Popover", "boolean"],
|
|
["RangeSlider", "number[]"],
|
|
] as const)("infers %s bindings as %s", (component, type) => {
|
|
expect(getCustomJsxBindingType(component)).toBe(type);
|
|
});
|
|
|
|
test("infers range and multiple date controls from their authored props", () => {
|
|
for (const component of [
|
|
"DatePicker",
|
|
"DatePickerInput",
|
|
"MonthPicker",
|
|
"MonthPickerInput",
|
|
"YearPicker",
|
|
"YearPickerInput",
|
|
]) {
|
|
expect(getCustomJsxBindingType(component, { type: "multiple" })).toBe("string[]");
|
|
expect(getCustomJsxBindingType(component, { type: "range" })).toBe("string[]");
|
|
}
|
|
expect(getCustomJsxBindingType("DateTimePicker", { type: "range" })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("DateTimePicker", { type: "multiple" })).toBe("string");
|
|
expect(getCustomJsxBindingType("InlineDateTimePicker", { type: "range" })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("InlineDateTimePicker", { type: "multiple" })).toBe("string");
|
|
expect(getCustomJsxBindingType("Accordion", { multiple: true })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("TreeSelect", { mode: "multiple" })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("TreeSelect", { mode: "checkbox" })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("Chip.Group", { multiple: true })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("ChipGroup", { multiple: true })).toBe("string[]");
|
|
expect(getCustomJsxBindingType("RadioGroup")).toBe("string");
|
|
expect(getCustomJsxBindingType("CheckboxGroup")).toBe("string[]");
|
|
expect(getCustomJsxBindingType("SwitchGroup")).toBe("string[]");
|
|
expect(getCustomJsxBindingType("Calendar")).toBeNull();
|
|
expect(getCustomJsxBindingType("HoverCard")).toBeNull();
|
|
expect(getCustomJsxBindingType("Text", {})).toBeNull();
|
|
});
|
|
});
|