vueless
Version:
Vue Styleless UI Component Library, powered by Tailwind CSS.
388 lines (314 loc) • 10.8 kB
text/typescript
import { flushPromises, mount } from "@vue/test-utils";
import { describe, it, expect } from "vitest";
import { nextTick } from "vue";
import URadioGroup from "../URadioGroup.vue";
import URadio from "../../ui.form-radio/URadio.vue";
import ULabel from "../../ui.form-label/ULabel.vue";
import type { Props } from "../types";
describe("URadioGroup.vue", () => {
const defaultOptions = [
{ label: "Email Notifications", value: "email" },
{ label: "SMS Alerts", value: "sms" },
{ label: "Push Notifications", value: "push" },
];
const defaultName = "test-group";
describe("Props", () => {
it("Options - renders radios for each option", () => {
const component = mount(URadioGroup, {
props: {
options: defaultOptions,
name: defaultName,
},
});
const radios = component.findAllComponents(URadio);
expect(radios).toHaveLength(defaultOptions.length);
radios.forEach((radio, index) => {
expect(radio.props("label")).toBe(defaultOptions[index].label);
expect(radio.props("value")).toBe(defaultOptions[index].value);
});
});
it("Options – radio emits value on change", async () => {
const updatedValue = "sms";
const component = mount(URadioGroup, {
props: {
options: defaultOptions,
name: "notification-preferences",
modelValue: "",
},
});
const radioInput = component.find(`input[type='radio'][value='${updatedValue}']`);
await radioInput.setValue(true);
await nextTick();
expect(component.emitted("update:modelValue")![0][0]).toBe(updatedValue);
});
it("Label – passes label to ULabel component", () => {
const labelText = "Test Label";
const component = mount(URadioGroup, {
props: {
label: labelText,
name: defaultName,
},
});
expect(component.getComponent(ULabel).props("label")).toBe(labelText);
});
it("Description – passes description to ULabel component", () => {
const descriptionText = "This is a description";
const component = mount(URadioGroup, {
props: {
description: descriptionText,
name: defaultName,
},
});
expect(component.getComponent(ULabel).props("description")).toBe(descriptionText);
});
it("Error – passes error to ULabel component", () => {
const errorText = "This is an error message";
const component = mount(URadioGroup, {
props: {
error: errorText,
name: defaultName,
},
});
expect(component.getComponent(ULabel).props("error")).toBe(errorText);
});
it("Size – applies the correct size class", () => {
const size = {
sm: "size-4",
md: "size-5",
lg: "size-6",
};
Object.entries(size).forEach(([size, classes]) => {
const component = mount(URadioGroup, {
props: {
size: size as Props["size"],
name: defaultName,
options: defaultOptions,
},
});
const radioInput = component.getComponent(URadio).get("input");
expect(radioInput.attributes("class")).toContain(classes);
});
});
it("Name – sets the correct URadio name prop", async () => {
const name = "radio-name";
const component = mount(URadioGroup, {
props: {
name,
options: defaultOptions,
},
});
await flushPromises();
component.findAllComponents("input").forEach((radio) => {
expect(radio.attributes("name")).toBe(name);
});
});
it("Color – sets correct URadio color prop", () => {
const colors = [
"primary",
"secondary",
"error",
"warning",
"success",
"info",
"notice",
"neutral",
"grayscale",
];
colors.forEach((color) => {
const component = mount(URadioGroup, {
props: {
color: color as Props["color"],
name: defaultName,
options: defaultOptions,
},
});
component.findAllComponents(URadio).forEach(async (radio) => {
const radioInput = radio.get("input");
await radioInput.trigger("input");
expect(radioInput.attributes("class")).toContain(color);
});
});
});
it("Disabled – sets correct URadio disabled prop", () => {
const component = mount(URadioGroup, {
props: {
disabled: true,
name: defaultName,
options: defaultOptions,
},
});
component.findAllComponents(URadio).forEach((radio) => {
expect(radio.props("disabled")).toBe(true);
});
});
it("Data test – sets correct data-test attribute to radios", () => {
const dataTestValue = "radio";
const component = mount(URadioGroup, {
props: {
"data-test": dataTestValue,
name: defaultName,
options: defaultOptions,
},
});
component.findAllComponents(URadio).forEach((radio, idx) => {
expect(radio.attributes("data-test")).toBe(`${dataTestValue}-item-${idx}-label`);
});
});
it("LabelKey – uses custom label key for option labels", () => {
const customOptions = [
{ value: "option-1", name: "Option 1" },
{ value: "option-2", name: "Option 2" },
{ value: "option-3", name: "Option 3" },
];
const component = mount(URadioGroup, {
props: {
name: defaultName,
options: customOptions,
labelKey: "name",
},
});
const radios = component.findAllComponents(URadio);
radios.forEach((radio, index) => {
expect(radio.props("label")).toBe(customOptions[index].name);
});
});
it("ValueKey – uses custom value key for option values", () => {
const customOptions = [
{ id: "option-1", label: "Option 1" },
{ id: "option-2", label: "Option 2" },
{ id: "option-3", label: "Option 3" },
];
const component = mount(URadioGroup, {
props: {
name: defaultName,
options: customOptions,
valueKey: "id",
},
});
const radios = component.findAllComponents(URadio);
radios.forEach((radio, index) => {
expect(radio.props("value")).toBe(customOptions[index].id);
});
});
it("LabelKey and ValueKey – works with complex objects", async () => {
const customOptions = [
{ planId: "basic", title: "Basic Plan" },
{ planId: "pro", title: "Pro Plan" },
];
const component = mount(URadioGroup, {
props: {
name: defaultName,
options: customOptions,
labelKey: "title",
valueKey: "planId",
modelValue: "",
},
});
const radios = component.findAllComponents(URadio);
expect(radios[0].props("label")).toBe("Basic Plan");
expect(radios[0].props("value")).toBe("basic");
expect(radios[1].props("label")).toBe("Pro Plan");
expect(radios[1].props("value")).toBe("pro");
});
});
describe("Slots", () => {
it("Label – renders custom content from label slot", () => {
const customLabelContent = "Custom Label Content";
const component = mount(URadioGroup, {
props: {
label: "Default Label",
name: defaultName,
},
slots: {
label: customLabelContent,
},
});
const labelComponent = component.getComponent(ULabel);
const labelElement = labelComponent.find("[vl-child-key='label']");
expect(labelElement.text()).toBe(customLabelContent);
});
it("Label – exposes label prop to slot", () => {
const defaultLabel = "Test Label";
const component = mount(URadioGroup, {
props: {
label: defaultLabel,
name: defaultName,
},
slots: {
label: "Modified {{ params.label }}",
},
});
const labelComponent = component.getComponent(ULabel);
const labelElement = labelComponent.find("[vl-child-key='label']");
expect(labelElement.text()).toBe(`Modified ${defaultLabel}`);
});
it("Description – renders custom content from description slot", () => {
const customDescription = "Custom description content";
const component = mount(URadioGroup, {
props: {
description: "Default description",
name: defaultName,
},
slots: {
description: customDescription,
},
});
const labelComponent = component.getComponent(ULabel);
const descriptionElement = labelComponent.find("[vl-child-key='description']");
expect(descriptionElement.text()).toBe(customDescription);
});
it("Error – renders custom content from error slot", () => {
const customError = "Custom error content";
const component = mount(URadioGroup, {
props: {
error: "Default error message",
name: defaultName,
},
slots: {
error: customError,
},
});
const labelComponent = component.getComponent(ULabel);
const errorElement = labelComponent.find("[vl-child-key='error']");
expect(errorElement.text()).toBe(customError);
});
it("Default slot – renders custom URadio components", () => {
const component = mount(URadioGroup, {
props: {
modelValue: "",
name: "custom-group",
},
slots: {
default: `
<URadio value="option1" label="Custom Option 1" />
<URadio value="option2" label="Custom Option 2" />
<URadio value="option3" label="Custom Option 3" />
`,
},
global: {
components: {
URadio,
},
},
});
const radios = component.findAllComponents(URadio);
expect(radios).toHaveLength(3);
expect(radios[0].props("value")).toBe("option1");
expect(radios[0].props("label")).toBe("Custom Option 1");
expect(radios[1].props("value")).toBe("option2");
expect(radios[1].props("label")).toBe("Custom Option 2");
expect(radios[2].props("value")).toBe("option3");
expect(radios[2].props("label")).toBe("Custom Option 3");
});
});
describe("Exposed properties", () => {
it("exposes listRef", () => {
const component = mount(URadioGroup, {
props: {
name: defaultName,
},
});
expect(component.vm.listRef).toBeDefined();
});
});
});