@taicode/common-web 1.1.19 → 1.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/output/catalyst/button.d.ts +1 -1
- package/output/catalyst/button.d.ts.map +1 -1
- package/output/loading-button/LoadingButtonDemo.d.ts +5 -0
- package/output/loading-button/LoadingButtonDemo.d.ts.map +1 -0
- package/output/loading-button/LoadingButtonDemo.js +33 -0
- package/output/loading-button/index.d.ts +26 -0
- package/output/loading-button/index.d.ts.map +1 -0
- package/output/loading-button/index.js +55 -0
- package/output/loading-button/index.test.d.ts +2 -0
- package/output/loading-button/index.test.d.ts.map +1 -0
- package/output/loading-button/index.test.js +129 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../source/catalyst/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAE7C,OAAO,KAAqB,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyJX,CAAA;AAED,
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../source/catalyst/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAE7C,OAAO,KAAqB,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyJX,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,CACtB;IAAE,KAAK,CAAC,EAAE,MAAM,OAAO,MAAM,CAAC,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GACtE;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/C;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAClD,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GAAG,CAClD,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,IAAI,CAAC,EAAE,WAAW,CAAC,CACjE,CAAA;AAEH,eAAO,MAAM,MAAM,iFAmBjB,CAAA;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAUtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoadingButtonDemo.d.ts","sourceRoot":"","sources":["../../source/loading-button/LoadingButtonDemo.tsx"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,iBAAiB,4CAsKhC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { LoadingButton } from '../loading-button';
|
|
4
|
+
/**
|
|
5
|
+
* LoadingButton 组件演示
|
|
6
|
+
*/
|
|
7
|
+
export function LoadingButtonDemo() {
|
|
8
|
+
const [result, setResult] = useState('');
|
|
9
|
+
// 模拟异步保存操作
|
|
10
|
+
const handleSave = async () => {
|
|
11
|
+
setResult('正在保存...');
|
|
12
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
13
|
+
setResult('保存成功!');
|
|
14
|
+
};
|
|
15
|
+
// 模拟可能失败的操作
|
|
16
|
+
const handleDelete = async () => {
|
|
17
|
+
setResult('正在删除...');
|
|
18
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
19
|
+
// 模拟随机失败
|
|
20
|
+
if (Math.random() > 0.5) {
|
|
21
|
+
setResult('删除成功!');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
setResult('删除失败!');
|
|
25
|
+
throw new Error('删除失败');
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// 同步操作
|
|
29
|
+
const handleClick = () => {
|
|
30
|
+
setResult('立即点击!');
|
|
31
|
+
};
|
|
32
|
+
return (_jsxs("div", { className: "space-y-8 p-8", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-2xl font-bold mb-4", children: "LoadingButton \u7EC4\u4EF6\u6F14\u793A" }), _jsx("p", { className: "text-gray-600 mb-4", children: "\u6F14\u793A\u5982\u4F55\u4F7F\u7528 LoadingButton \u7EC4\u4EF6\u5904\u7406\u5F02\u6B65\u64CD\u4F5C" })] }), result && (_jsx("div", { className: "p-4 bg-gray-100 dark:bg-gray-800 rounded-lg", children: _jsx("p", { className: "text-sm font-medium", children: result }) })), _jsxs("section", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: "\u57FA\u7840\u7528\u6CD5" }), _jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsx(LoadingButton, { color: "blue", onClick: handleSave, children: "\u4FDD\u5B58\u6570\u636E" }), _jsx(LoadingButton, { color: "red", onClick: handleDelete, children: "\u5220\u9664\u6570\u636E" }), _jsx(LoadingButton, { color: "green", onClick: handleClick, children: "\u540C\u6B65\u64CD\u4F5C" })] })] }), _jsxs("section", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: "\u4E0D\u540C\u6837\u5F0F" }), _jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsx(LoadingButton, { color: "emerald", onClick: handleSave, children: "Solid \u6837\u5F0F" }), _jsx(LoadingButton, { outline: true, onClick: handleSave, children: "Outline \u6837\u5F0F" }), _jsx(LoadingButton, { plain: true, onClick: handleSave, children: "Plain \u6837\u5F0F" })] })] }), _jsxs("section", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: "\u81EA\u5B9A\u4E49\u52A0\u8F7D\u6587\u672C" }), _jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsx(LoadingButton, { color: "blue", onClick: handleSave, loadingText: "\u6B63\u5728\u4FDD\u5B58\u6570\u636E...", children: "\u81EA\u5B9A\u4E49\u6587\u672C" }), _jsx(LoadingButton, { color: "purple", onClick: handleSave, loadingText: _jsxs("span", { className: "flex items-center gap-2", children: [_jsxs("svg", { className: "animate-spin h-4 w-4", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "\u5904\u7406\u4E2D"] }), children: "\u81EA\u5B9A\u4E49\u56FE\u6807" })] })] }), _jsxs("section", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: "\u989C\u8272\u9009\u9879" }), _jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsx(LoadingButton, { color: "red", onClick: handleSave, children: "Red" }), _jsx(LoadingButton, { color: "orange", onClick: handleSave, children: "Orange" }), _jsx(LoadingButton, { color: "amber", onClick: handleSave, children: "Amber" }), _jsx(LoadingButton, { color: "yellow", onClick: handleSave, children: "Yellow" }), _jsx(LoadingButton, { color: "lime", onClick: handleSave, children: "Lime" }), _jsx(LoadingButton, { color: "green", onClick: handleSave, children: "Green" }), _jsx(LoadingButton, { color: "emerald", onClick: handleSave, children: "Emerald" }), _jsx(LoadingButton, { color: "teal", onClick: handleSave, children: "Teal" }), _jsx(LoadingButton, { color: "cyan", onClick: handleSave, children: "Cyan" }), _jsx(LoadingButton, { color: "sky", onClick: handleSave, children: "Sky" }), _jsx(LoadingButton, { color: "blue", onClick: handleSave, children: "Blue" }), _jsx(LoadingButton, { color: "indigo", onClick: handleSave, children: "Indigo" }), _jsx(LoadingButton, { color: "violet", onClick: handleSave, children: "Violet" }), _jsx(LoadingButton, { color: "purple", onClick: handleSave, children: "Purple" }), _jsx(LoadingButton, { color: "fuchsia", onClick: handleSave, children: "Fuchsia" }), _jsx(LoadingButton, { color: "pink", onClick: handleSave, children: "Pink" }), _jsx(LoadingButton, { color: "rose", onClick: handleSave, children: "Rose" })] })] }), _jsxs("section", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: "\u7981\u7528\u72B6\u6001" }), _jsxs("div", { className: "flex gap-3 flex-wrap", children: [_jsx(LoadingButton, { color: "blue", disabled: true, onClick: handleSave, children: "\u7981\u7528\u6309\u94AE" }), _jsx(LoadingButton, { color: "green", onClick: handleSave, disableOnLoading: false, children: "\u52A0\u8F7D\u65F6\u4E0D\u7981\u7528" })] })] })] }));
|
|
33
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ButtonProps } from '../catalyst/button';
|
|
3
|
+
/**
|
|
4
|
+
* LoadingButton 组件属性类型
|
|
5
|
+
* 继承 Button 的所有属性,自动处理 onClick 的异步状态
|
|
6
|
+
*/
|
|
7
|
+
export type LoadingButtonProps = ButtonProps;
|
|
8
|
+
/**
|
|
9
|
+
* LoadingButton 组件
|
|
10
|
+
*
|
|
11
|
+
* 自动处理 onClick 异步操作的加载状态,在按钮末尾显示 loading 图标
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <LoadingButton
|
|
16
|
+
* color="blue"
|
|
17
|
+
* onClick={async () => {
|
|
18
|
+
* await saveData()
|
|
19
|
+
* }}
|
|
20
|
+
* >
|
|
21
|
+
* 保存
|
|
22
|
+
* </LoadingButton>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare const LoadingButton: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLElement>>;
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/loading-button/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAA;AACnD,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAG7D;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAA;AAM5C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,iFAkDxB,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { forwardRef, useState } from 'react';
|
|
14
|
+
import { Button } from '../catalyst/button';
|
|
15
|
+
import { catchIt } from '@taicode/common-base';
|
|
16
|
+
function isPromiseLike(value) {
|
|
17
|
+
return value != null && typeof value.then === 'function';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* LoadingButton 组件
|
|
21
|
+
*
|
|
22
|
+
* 自动处理 onClick 异步操作的加载状态,在按钮末尾显示 loading 图标
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <LoadingButton
|
|
27
|
+
* color="blue"
|
|
28
|
+
* onClick={async () => {
|
|
29
|
+
* await saveData()
|
|
30
|
+
* }}
|
|
31
|
+
* >
|
|
32
|
+
* 保存
|
|
33
|
+
* </LoadingButton>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const LoadingButton = forwardRef(function LoadingButton(_a, ref) {
|
|
37
|
+
var { children, onClick } = _a, props = __rest(_a, ["children", "onClick"]);
|
|
38
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
39
|
+
const handleClick = async (event) => {
|
|
40
|
+
if (!onClick || isLoading)
|
|
41
|
+
return;
|
|
42
|
+
const result = onClick(event);
|
|
43
|
+
// 检查是否是 Promise
|
|
44
|
+
if (isPromiseLike(result)) {
|
|
45
|
+
setIsLoading(true);
|
|
46
|
+
const catchResult = await catchIt(result);
|
|
47
|
+
setIsLoading(false);
|
|
48
|
+
// 错误由调用方处理
|
|
49
|
+
if (catchResult.isError()) {
|
|
50
|
+
throw catchResult.error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
return (_jsxs(Button, Object.assign({}, props, { ref: ref, onClick: handleClick, disabled: isLoading, children: [children, isLoading && (_jsxs("svg", { "data-slot": "icon", className: "animate-spin", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }))] })));
|
|
55
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../source/loading-button/index.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import { LoadingButton } from './index';
|
|
6
|
+
describe('LoadingButton', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
vi.useFakeTimers();
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.restoreAllMocks();
|
|
12
|
+
vi.useRealTimers();
|
|
13
|
+
});
|
|
14
|
+
it('应该正常渲染按钮', () => {
|
|
15
|
+
render(_jsx(LoadingButton, { children: "\u70B9\u51FB\u6211" }));
|
|
16
|
+
expect(screen.getByRole('button')).toHaveTextContent('点击我');
|
|
17
|
+
});
|
|
18
|
+
it('应该在同步 onClick 时不显示加载状态', async () => {
|
|
19
|
+
const handleClick = vi.fn();
|
|
20
|
+
const user = userEvent.setup({ delay: null });
|
|
21
|
+
render(_jsx(LoadingButton, { onClick: handleClick, children: "\u70B9\u51FB\u6211" }));
|
|
22
|
+
const button = screen.getByRole('button');
|
|
23
|
+
await user.click(button);
|
|
24
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
25
|
+
expect(button).toHaveTextContent('点击我');
|
|
26
|
+
});
|
|
27
|
+
it('应该在异步 onClick 时显示加载状态', async () => {
|
|
28
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 1000)));
|
|
29
|
+
const user = userEvent.setup({ delay: null });
|
|
30
|
+
render(_jsx(LoadingButton, { onClick: handleClick, children: "\u4FDD\u5B58" }));
|
|
31
|
+
const button = screen.getByRole('button');
|
|
32
|
+
await user.click(button);
|
|
33
|
+
// 应该显示加载文本
|
|
34
|
+
expect(button).toHaveTextContent('加载中...');
|
|
35
|
+
// 快进时间
|
|
36
|
+
vi.advanceTimersByTime(1000);
|
|
37
|
+
await waitFor(() => {
|
|
38
|
+
expect(button).toHaveTextContent('保存');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it('应该支持自定义加载文本', async () => {
|
|
42
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 1000)));
|
|
43
|
+
const user = userEvent.setup({ delay: null });
|
|
44
|
+
render(_jsx(LoadingButton, { onClick: handleClick, loadingText: "\u6B63\u5728\u4FDD\u5B58...", children: "\u4FDD\u5B58" }));
|
|
45
|
+
const button = screen.getByRole('button');
|
|
46
|
+
await user.click(button);
|
|
47
|
+
expect(button).toHaveTextContent('正在保存...');
|
|
48
|
+
});
|
|
49
|
+
it('应该在加载时禁用按钮', async () => {
|
|
50
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 1000)));
|
|
51
|
+
const user = userEvent.setup({ delay: null });
|
|
52
|
+
render(_jsx(LoadingButton, { onClick: handleClick, children: "\u4FDD\u5B58" }));
|
|
53
|
+
const button = screen.getByRole('button');
|
|
54
|
+
await user.click(button);
|
|
55
|
+
// 按钮应该被禁用
|
|
56
|
+
expect(button).toBeDisabled();
|
|
57
|
+
// 尝试再次点击不应该触发
|
|
58
|
+
await user.click(button);
|
|
59
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
60
|
+
});
|
|
61
|
+
it('应该在 disableOnLoading=false 时不禁用按钮', async () => {
|
|
62
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 1000)));
|
|
63
|
+
const user = userEvent.setup({ delay: null });
|
|
64
|
+
render(_jsx(LoadingButton, { onClick: handleClick, disableOnLoading: false, children: "\u4FDD\u5B58" }));
|
|
65
|
+
const button = screen.getByRole('button');
|
|
66
|
+
await user.click(button);
|
|
67
|
+
// 按钮不应该被禁用
|
|
68
|
+
expect(button).not.toBeDisabled();
|
|
69
|
+
});
|
|
70
|
+
it('应该在异步操作完成后恢复状态', async () => {
|
|
71
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 1000)));
|
|
72
|
+
const user = userEvent.setup({ delay: null });
|
|
73
|
+
render(_jsx(LoadingButton, { onClick: handleClick, children: "\u4FDD\u5B58" }));
|
|
74
|
+
const button = screen.getByRole('button');
|
|
75
|
+
await user.click(button);
|
|
76
|
+
expect(button).toHaveTextContent('加载中...');
|
|
77
|
+
expect(button).toBeDisabled();
|
|
78
|
+
// 快进时间
|
|
79
|
+
vi.advanceTimersByTime(1000);
|
|
80
|
+
await waitFor(() => {
|
|
81
|
+
expect(button).toHaveTextContent('保存');
|
|
82
|
+
expect(button).not.toBeDisabled();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it('应该在异步操作失败后恢复状态', async () => {
|
|
86
|
+
const error = new Error('保存失败');
|
|
87
|
+
const handleClick = vi.fn().mockImplementation(() => new Promise((_, reject) => setTimeout(() => reject(error), 1000)));
|
|
88
|
+
const user = userEvent.setup({ delay: null });
|
|
89
|
+
render(_jsx(LoadingButton, { onClick: handleClick, children: "\u4FDD\u5B58" }));
|
|
90
|
+
const button = screen.getByRole('button');
|
|
91
|
+
// 点击会抛出错误,需要捕获
|
|
92
|
+
await expect(async () => {
|
|
93
|
+
await user.click(button);
|
|
94
|
+
vi.advanceTimersByTime(1000);
|
|
95
|
+
}).rejects.toThrow('保存失败');
|
|
96
|
+
await waitFor(() => {
|
|
97
|
+
expect(button).toHaveTextContent('保存');
|
|
98
|
+
expect(button).not.toBeDisabled();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
it('应该支持所有 Button 的颜色选项', () => {
|
|
102
|
+
const { rerender } = render(_jsx(LoadingButton, { color: "blue", children: "\u84DD\u8272\u6309\u94AE" }));
|
|
103
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
104
|
+
rerender(_jsx(LoadingButton, { color: "red", children: "\u7EA2\u8272\u6309\u94AE" }));
|
|
105
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
106
|
+
rerender(_jsx(LoadingButton, { color: "green", children: "\u7EFF\u8272\u6309\u94AE" }));
|
|
107
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
108
|
+
});
|
|
109
|
+
it('应该支持 outline 样式', () => {
|
|
110
|
+
render(_jsx(LoadingButton, { outline: true, children: "\u8F6E\u5ED3\u6309\u94AE" }));
|
|
111
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
112
|
+
});
|
|
113
|
+
it('应该支持 plain 样式', () => {
|
|
114
|
+
render(_jsx(LoadingButton, { plain: true, children: "\u7B80\u5355\u6309\u94AE" }));
|
|
115
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
it('应该支持 disabled 属性', () => {
|
|
118
|
+
render(_jsx(LoadingButton, { disabled: true, children: "\u7981\u7528\u6309\u94AE" }));
|
|
119
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
120
|
+
});
|
|
121
|
+
it('应该在已禁用时不响应点击', async () => {
|
|
122
|
+
const handleClick = vi.fn();
|
|
123
|
+
const user = userEvent.setup({ delay: null });
|
|
124
|
+
render(_jsx(LoadingButton, { disabled: true, onClick: handleClick, children: "\u7981\u7528\u6309\u94AE" }));
|
|
125
|
+
const button = screen.getByRole('button');
|
|
126
|
+
await user.click(button);
|
|
127
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
128
|
+
});
|
|
129
|
+
});
|