Skip to content

Commit 930f1a8

Browse files
committed
test: add tag and text area tests
1 parent 1d073dc commit 930f1a8

File tree

2 files changed

+272
-0
lines changed

2 files changed

+272
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { mount } from "@vue/test-utils";
2+
import { describe, expect, it } from "vitest";
3+
import Tag from "../Tag.vue";
4+
5+
describe("Tag", () => {
6+
it("renders with default props", () => {
7+
const wrapper = mount(Tag, {
8+
slots: {
9+
default: "Tag Text",
10+
},
11+
});
12+
expect(wrapper.find(".tag").exists()).toBe(true);
13+
expect(wrapper.text()).toBe("Tag Text");
14+
});
15+
16+
it("applies style props correctly", () => {
17+
const wrapper = mount(Tag, {
18+
props: {
19+
type: "is-primary",
20+
size: "is-medium",
21+
rounded: true,
22+
},
23+
});
24+
const tag = wrapper.find(".tag");
25+
expect(tag.classes()).toContain("is-primary");
26+
expect(tag.classes()).toContain("is-medium");
27+
expect(tag.classes()).toContain("is-rounded");
28+
});
29+
30+
it("handles closable prop", () => {
31+
const wrapper = mount(Tag, {
32+
props: {
33+
closable: true,
34+
},
35+
});
36+
expect(wrapper.find(".delete").exists()).toBe(true);
37+
});
38+
39+
it("emits close event when delete button is clicked", async () => {
40+
const wrapper = mount(Tag, {
41+
props: {
42+
closable: true,
43+
},
44+
});
45+
await wrapper.find(".delete").trigger("click");
46+
expect(wrapper.emitted("close")).toBeTruthy();
47+
});
48+
49+
it("does not emit close event when disabled", async () => {
50+
const wrapper = mount(Tag, {
51+
props: {
52+
closable: true,
53+
disabled: true,
54+
},
55+
});
56+
await wrapper.find(".delete").trigger("click");
57+
expect(wrapper.emitted("close")).toBeFalsy();
58+
});
59+
60+
it("handles attached mode correctly", () => {
61+
const wrapper = mount(Tag, {
62+
props: {
63+
attached: true,
64+
closable: true,
65+
},
66+
});
67+
expect(wrapper.find(".tags.has-addons").exists()).toBe(true);
68+
expect(wrapper.find(".is-delete").exists()).toBe(true);
69+
});
70+
71+
it("shows ellipsis when ellipsis prop is true", () => {
72+
const wrapper = mount(Tag, {
73+
props: {
74+
ellipsis: true,
75+
},
76+
slots: {
77+
default: "Long text that should be ellipsized",
78+
},
79+
});
80+
expect(wrapper.find(".has-ellipsis").exists()).toBe(true);
81+
});
82+
83+
it("handles tabstop correctly", () => {
84+
const wrapper = mount(Tag, {
85+
props: {
86+
closable: true,
87+
tabstop: false,
88+
},
89+
});
90+
expect(wrapper.find(".delete").attributes("tabindex")).toBe("false");
91+
92+
const wrapperWithTabstop = mount(Tag, {
93+
props: {
94+
closable: true,
95+
tabstop: true,
96+
},
97+
});
98+
expect(wrapperWithTabstop.find(".delete").attributes("tabindex")).toBe("0");
99+
});
100+
101+
it("applies aria-label to close button", () => {
102+
const wrapper = mount(Tag, {
103+
props: {
104+
closable: true,
105+
ariaCloseLabel: "Close tag",
106+
},
107+
});
108+
expect(wrapper.find(".delete").attributes("aria-label")).toBe("Close tag");
109+
});
110+
111+
it("applies close type class", () => {
112+
const wrapper = mount(Tag, {
113+
props: {
114+
closable: true,
115+
closeType: "is-danger",
116+
},
117+
});
118+
expect(wrapper.find(".delete").classes()).toContain("is-danger");
119+
});
120+
121+
it("shows custom close icon when provided", () => {
122+
const wrapper = mount(Tag, {
123+
props: {
124+
attached: true,
125+
closable: true,
126+
closeIcon: "custom-icon",
127+
},
128+
});
129+
expect(wrapper.find(".has-delete-icon").exists()).toBe(true);
130+
});
131+
132+
it("handles keyboard delete event", async () => {
133+
const wrapper = mount(Tag, {
134+
props: {
135+
closable: true,
136+
},
137+
});
138+
await wrapper.find(".delete").trigger("keyup.delete");
139+
expect(wrapper.emitted("close")).toBeTruthy();
140+
});
141+
});
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { mount } from "@vue/test-utils";
2+
import { describe, expect, it } from "vitest";
3+
import Textarea from "../Textarea.vue";
4+
5+
describe("Textarea", () => {
6+
it("renders with default props", () => {
7+
const wrapper = mount(Textarea);
8+
expect(wrapper.find(".control").exists()).toBe(true);
9+
expect(wrapper.find("textarea").exists()).toBe(true);
10+
});
11+
12+
it("handles v-model correctly", async () => {
13+
const wrapper = mount(Textarea, {
14+
props: {
15+
modelValue: "Initial text",
16+
},
17+
});
18+
expect(wrapper.find("textarea").element.value).toBe("Initial text");
19+
20+
await wrapper.find("textarea").setValue("New text");
21+
const emitted = wrapper.emitted("update:modelValue");
22+
expect(emitted).toBeTruthy();
23+
expect(emitted?.[0]).toEqual(["Initial text"]);
24+
expect(emitted?.[1]).toEqual(["New text"]);
25+
});
26+
27+
it("applies style props correctly", () => {
28+
const wrapper = mount(Textarea, {
29+
props: {
30+
color: "is-primary",
31+
size: "is-large",
32+
},
33+
});
34+
const textarea = wrapper.find("textarea");
35+
expect(textarea.classes()).toContain("is-primary");
36+
expect(textarea.classes()).toContain("is-large");
37+
expect(wrapper.find(".control").classes()).toContain("is-large");
38+
});
39+
40+
it("shows loading state", () => {
41+
const wrapper = mount(Textarea, {
42+
props: {
43+
loading: true,
44+
},
45+
});
46+
expect(wrapper.find(".control").classes()).toContain("is-loading");
47+
});
48+
49+
it("applies hover state", () => {
50+
const wrapper = mount(Textarea, {
51+
props: {
52+
hovered: true,
53+
},
54+
});
55+
expect(wrapper.find("textarea").classes()).toContain("is-hovered");
56+
});
57+
58+
it("applies focus state", () => {
59+
const wrapper = mount(Textarea, {
60+
props: {
61+
focused: true,
62+
},
63+
});
64+
expect(wrapper.find("textarea").classes()).toContain("is-focused");
65+
});
66+
67+
it("handles focus and blur events", async () => {
68+
const wrapper = mount(Textarea);
69+
const textarea = wrapper.find("textarea");
70+
71+
await textarea.trigger("focus");
72+
expect(wrapper.vm.isFocused).toBe(true);
73+
74+
await textarea.trigger("blur");
75+
expect(wrapper.vm.isFocused).toBe(false);
76+
});
77+
78+
it("shows character counter when hasCounter and maxlength are set", () => {
79+
const wrapper = mount(Textarea, {
80+
props: {
81+
hasCounter: true,
82+
maxlength: "100",
83+
modelValue: "Hello",
84+
},
85+
});
86+
expect(wrapper.find("small").exists()).toBe(true);
87+
expect(wrapper.find("small").text()).toBe("5 / 100");
88+
});
89+
90+
it("hides counter when not focused", async () => {
91+
const wrapper = mount(Textarea, {
92+
props: {
93+
hasCounter: true,
94+
maxlength: "100",
95+
modelValue: "Hello",
96+
},
97+
});
98+
expect(wrapper.find("small").classes()).toContain("is-invisible");
99+
100+
await wrapper.find("textarea").trigger("focus");
101+
expect(wrapper.find("small").classes()).not.toContain("is-invisible");
102+
103+
await wrapper.find("textarea").trigger("blur");
104+
expect(wrapper.find("small").classes()).toContain("is-invisible");
105+
});
106+
107+
it("inherits HTML attributes", () => {
108+
const wrapper = mount(Textarea, {
109+
attrs: {
110+
placeholder: "Enter text here",
111+
rows: "5",
112+
name: "description",
113+
},
114+
});
115+
const textarea = wrapper.find("textarea");
116+
expect(textarea.attributes("placeholder")).toBe("Enter text here");
117+
expect(textarea.attributes("rows")).toBe("5");
118+
expect(textarea.attributes("name")).toBe("description");
119+
});
120+
121+
it("updates value when modelValue prop changes", async () => {
122+
const wrapper = mount(Textarea, {
123+
props: {
124+
modelValue: "Initial",
125+
},
126+
});
127+
// @ts-expect-error
128+
await wrapper.setProps({ modelValue: "Updated" });
129+
expect(wrapper.find("textarea").element.value).toBe("Updated");
130+
});
131+
});

0 commit comments

Comments
 (0)