Skip to content

Commit

Permalink
test: 完善 button 组件测试用例
Browse files Browse the repository at this point in the history
  • Loading branch information
EricWXY committed May 3, 2024
1 parent 8de3bfc commit 7a69cd8
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 2 deletions.
162 changes: 161 additions & 1 deletion packages/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { describe, test, expect, vi } from "vitest";
import { describe, test, it, expect, vi } from "vitest";
import { mount } from "@vue/test-utils";

import Icon from "../Icon/Icon.vue";
import Button from "./Button.vue";
import ButtonGroup from "./ButtonGroup.vue";

describe("Button.vue", () => {
const onClick = vi.fn();
Expand Down Expand Up @@ -41,6 +42,7 @@ describe("Button.vue", () => {
// events
await wrapper.get("button").trigger("click");
expect(onClick).toHaveBeenCalledOnce();
expect(wrapper.emitted("click")).toBeUndefined();
});

test("loading button", () => {
Expand Down Expand Up @@ -90,4 +92,162 @@ describe("Button.vue", () => {
expect(iconElement.exists()).toBeTruthy();
expect(iconElement.attributes("icon")).toBe("arrow-up");
});

// Props: type
it("has the correct type class when type prop is set", () => {
const types = ["primary", "success", "warning", "danger", "info"];
types.forEach((type) => {
const wrapper = mount(Button, {
props: { type: type as any },
});
expect(wrapper.classes()).toContain(`er-button--${type}`);
});
});

// Props: size
it("has the correct size class when size prop is set", () => {
const sizes = ["large", "default", "small"];
sizes.forEach((size) => {
const wrapper = mount(Button, {
props: { size: size as any },
});
expect(wrapper.classes()).toContain(`er-button--${size}`);
});
});

// Props: plain, round, circle
it.each([
["plain", "is-plain"],
["round", "is-round"],
["circle", "is-circle"],
["disabled", "is-disabled"],
["loading", "is-loading"],
])("has the correct class when prop %s is set to true", (prop, className) => {
const wrapper = mount(Button, {
props: { [prop]: true },

global: {
stubs: ["ErIcon"],
},
});
expect(wrapper.classes()).toContain(className);
if (prop == "loading") {
// icon
const iconElement = wrapper.findComponent(Icon);
expect(iconElement.exists()).toBeTruthy();
expect(iconElement.attributes("icon")).toBe("spinner");
}
});

it("has the correct native type attribute when native-type prop is set", () => {
const wrapper = mount(Button, {
props: { nativeType: "submit" },
});
expect(wrapper.element.tagName).toBe("BUTTON");
expect((wrapper.element as any).type).toBe("submit");
});

// Test the click event with and without throttle
it.each([
["withoutThrottle", false],
["withThrottle", true],
])("emits click event %s", async (_, useThrottle) => {
const clickSpy = vi.fn();
const wrapper = mount(() => (
<Button
onClick={clickSpy}
{...{
useThrottle,
throttleDuration: 400,
}}
/>
));

await wrapper.get("button").trigger("click");
expect(clickSpy).toHaveBeenCalled();
});

// Props: tag
it("should renders the custom tag when tag prop is set", () => {
const wrapper = mount(Button, {
props: { tag: "a" },
});
expect(wrapper.element.tagName.toLowerCase()).toBe("a");
});

// Events: click
it("should emits a click event when the button is clicked", async () => {
const wrapper = mount(Button, {});
await wrapper.trigger("click");
expect(wrapper.emitted().click).toHaveLength(1);
});

// Exception Handling: loading state
it("should display loading icon and not emit click event when button is loading", async () => {
const wrapper = mount(Button, {
props: { loading: true },
global: {
stubs: ["ErIcon"],
},
});

expect(wrapper.find(".loading-icon").exists()).toBe(true);
await wrapper.trigger("click");
expect(wrapper.emitted("click")).toBeUndefined();
});
});

describe("ButtonGroup.vue", () => {
test("basic button group", async () => {
const wrapper = mount(() => (
<ButtonGroup>
<Button>button 1</Button>
<Button>button 2</Button>
</ButtonGroup>
));

expect(wrapper.classes()).toContain("er-button-group");
});

test("button group size", () => {
const sizes = ["large", "default", "small"];
sizes.forEach((size) => {
const wrapper = mount(() => (
<ButtonGroup size={size as any}>
<Button>button 1</Button>
<Button>button 2</Button>
</ButtonGroup>
));

const buttonWrapper = wrapper.findComponent(Button);
expect(buttonWrapper.classes()).toContain(`er-button--${size}`);
});
});

test("button group type", () => {
const types = ["primary", "success", "warning", "danger", "info"];
types.forEach((type) => {
const wrapper = mount(() => (
<ButtonGroup type={type as any}>
<Button>button 1</Button>
<Button>button 2</Button>
</ButtonGroup>
));

const buttonWrapper = wrapper.findComponent(Button);
expect(buttonWrapper.classes()).toContain(`er-button--${type}`);
});
});

test("button group disabled", () => {
const wrapper = mount(() => (
<ButtonGroup disabled>
<Button>button 1</Button>
<Button>button 2</Button>
</ButtonGroup>
));

const buttonWrapper = wrapper.findComponent(Button);
expect(buttonWrapper.classes()).toContain(`is-disabled`);
});
});
2 changes: 1 addition & 1 deletion packages/components/Button/Button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const iconStyle = computed(() => ({
}));
const handleBtnClick = (e: MouseEvent) => {
if (disabled.value) return;
emits("click", e);
};
const handlBtneCLickThrottle = throttle(handleBtnClick, props.throttleDuration);
Expand Down Expand Up @@ -63,6 +62,7 @@ defineExpose({
<template v-if="loading">
<slot name="loading">
<er-icon
class="loading-icon"
:icon="loadingIcon ?? 'spinner'"
:style="iconStyle"
size="1x"
Expand Down

0 comments on commit 7a69cd8

Please sign in to comment.