@firerian/fireui 1.0.0
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/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/fireui.cjs +2 -0
- package/dist/fireui.cjs.map +1 -0
- package/dist/fireui.css +1 -0
- package/dist/fireui.es.mjs +3867 -0
- package/dist/fireui.es.mjs.map +1 -0
- package/dist/fireui.umd.js +2 -0
- package/dist/fireui.umd.js.map +1 -0
- package/dist/types/index.d.ts +1590 -0
- package/package.json +132 -0
- package/src/components/button/button.test.ts +357 -0
- package/src/components/button/button.vue +366 -0
- package/src/components/button/index.ts +17 -0
- package/src/components/button/types.ts +76 -0
- package/src/components/form/form-item.vue +136 -0
- package/src/components/form/form.vue +76 -0
- package/src/components/form/index.ts +16 -0
- package/src/components/grid/col.vue +99 -0
- package/src/components/grid/index.ts +16 -0
- package/src/components/grid/row.vue +85 -0
- package/src/components/grid/types.ts +66 -0
- package/src/components/index.ts +36 -0
- package/src/components/input/index.ts +8 -0
- package/src/components/input/input.test.ts +129 -0
- package/src/components/input/input.vue +256 -0
- package/src/components/input/types.ts +100 -0
- package/src/components/layout/aside.vue +89 -0
- package/src/components/layout/container.vue +53 -0
- package/src/components/layout/footer.vue +57 -0
- package/src/components/layout/header.vue +56 -0
- package/src/components/layout/index.ts +28 -0
- package/src/components/layout/main.vue +36 -0
- package/src/components/layout/types.ts +74 -0
- package/src/components/table/index.ts +16 -0
- package/src/components/table/table-column.vue +69 -0
- package/src/components/table/table.vue +354 -0
- package/src/components/tips/index.ts +12 -0
- package/src/components/tips/tips.test.ts +96 -0
- package/src/components/tips/tips.vue +206 -0
- package/src/components/tips/types.ts +56 -0
- package/src/components/tooltip/index.ts +8 -0
- package/src/components/tooltip/tooltip.test.ts +187 -0
- package/src/components/tooltip/tooltip.vue +261 -0
- package/src/components/tooltip/types.ts +60 -0
- package/src/hooks/useForm.ts +233 -0
- package/src/hooks/useTable.ts +153 -0
- package/src/index.ts +48 -0
- package/src/styles/main.scss +6 -0
- package/src/styles/mixins.scss +48 -0
- package/src/styles/reset.scss +49 -0
- package/src/styles/variables.scss +137 -0
- package/src/types/component.ts +9 -0
- package/src/types/form.ts +149 -0
- package/src/types/global.d.ts +49 -0
- package/src/types/grid.ts +76 -0
- package/src/types/index.ts +23 -0
- package/src/types/table.ts +181 -0
- package/src/types/tooltip.ts +44 -0
- package/src/utils/auto-import.ts +41 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/install.ts +20 -0
- package/src/utils/useNamespace.ts +29 -0
package/package.json
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@firerian/fireui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A modern Vue 3 UI component library",
|
|
6
|
+
"main": "./dist/fireui.cjs",
|
|
7
|
+
"module": "./dist/fireui.es.mjs",
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"typings": "./dist/types/index.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
"*": {
|
|
12
|
+
"*": [
|
|
13
|
+
"./dist/types/index.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/types/index.d.ts",
|
|
20
|
+
"import": "./dist/fireui.es.mjs",
|
|
21
|
+
"require": "./dist/fireui.cjs",
|
|
22
|
+
"default": "./dist/fireui.es.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./dist/fireui.css": {
|
|
25
|
+
"import": "./dist/fireui.css",
|
|
26
|
+
"require": "./dist/fireui.css",
|
|
27
|
+
"default": "./dist/fireui.css"
|
|
28
|
+
},
|
|
29
|
+
"./fireui.css": {
|
|
30
|
+
"import": "./dist/fireui.css",
|
|
31
|
+
"require": "./dist/fireui.css",
|
|
32
|
+
"default": "./dist/fireui.css"
|
|
33
|
+
},
|
|
34
|
+
"./style.css": {
|
|
35
|
+
"import": "./dist/fireui.css",
|
|
36
|
+
"require": "./dist/fireui.css",
|
|
37
|
+
"default": "./dist/fireui.css"
|
|
38
|
+
},
|
|
39
|
+
"./dist/*": "./dist/*",
|
|
40
|
+
"./*": "./*"
|
|
41
|
+
},
|
|
42
|
+
"sideEffects": [
|
|
43
|
+
"dist/fireui.css",
|
|
44
|
+
"**/*.css"
|
|
45
|
+
],
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"src",
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"dev": "vite",
|
|
54
|
+
"build": "vue-tsc && vite build",
|
|
55
|
+
"build:lib": "npm run clean && vue-tsc --noEmit && vite build --config vite.config.build.ts",
|
|
56
|
+
"build:watch": "vite build --config vite.config.build.ts --watch",
|
|
57
|
+
"clean": "rimraf dist",
|
|
58
|
+
"preview": "vite preview",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest",
|
|
61
|
+
"test:coverage": "vitest run --coverage",
|
|
62
|
+
"docs:dev": "vitepress dev docs",
|
|
63
|
+
"docs:build": "vitepress build docs",
|
|
64
|
+
"docs:preview": "vitepress preview docs",
|
|
65
|
+
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
|
|
66
|
+
"lint:check": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
|
|
67
|
+
"format": "prettier --write src/ docs/",
|
|
68
|
+
"format:check": "prettier --check src/ docs/",
|
|
69
|
+
"prepublishOnly": "npm run build:lib",
|
|
70
|
+
"prepare": "husky"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"vue": "^3.5.0"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"@floating-ui/vue": "^1.1.10",
|
|
77
|
+
"async-validator": "^4.2.5",
|
|
78
|
+
"lucide-vue-next": "^0.454.0"
|
|
79
|
+
},
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@eslint/js": "^9.13.0",
|
|
82
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
83
|
+
"@types/node": "^22.10.1",
|
|
84
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
85
|
+
"@vitest/eslint-plugin": "^1.1.0",
|
|
86
|
+
"@vue/test-utils": "^2.4.0",
|
|
87
|
+
"autoprefixer": "^10.4.20",
|
|
88
|
+
"eslint": "^9.13.0",
|
|
89
|
+
"eslint-config-prettier": "^10.1.8",
|
|
90
|
+
"eslint-plugin-vue": "^9.30.0",
|
|
91
|
+
"globals": "^15.11.0",
|
|
92
|
+
"husky": "^9.1.7",
|
|
93
|
+
"jsdom": "^26.0.0",
|
|
94
|
+
"lint-staged": "^15.2.10",
|
|
95
|
+
"postcss": "^8.5.1",
|
|
96
|
+
"prettier": "^3.3.3",
|
|
97
|
+
"rimraf": "^6.0.1",
|
|
98
|
+
"sass": "^1.80.6",
|
|
99
|
+
"tailwindcss": "^4.0.0",
|
|
100
|
+
"terser": "^5.36.0",
|
|
101
|
+
"typescript": "~5.6.2",
|
|
102
|
+
"typescript-eslint": "^8.10.0",
|
|
103
|
+
"vite": "^6.0.3",
|
|
104
|
+
"vite-plugin-dts": "^4.3.0",
|
|
105
|
+
"vitepress": "^1.4.0",
|
|
106
|
+
"vitest": "^2.1.4",
|
|
107
|
+
"vue": "^3.5.13",
|
|
108
|
+
"vue-tsc": "^2.1.10"
|
|
109
|
+
},
|
|
110
|
+
"lint-staged": {
|
|
111
|
+
"*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}": [
|
|
112
|
+
"eslint --fix",
|
|
113
|
+
"prettier --write"
|
|
114
|
+
],
|
|
115
|
+
"*.{json,md}": [
|
|
116
|
+
"prettier --write"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"keywords": [
|
|
120
|
+
"vue",
|
|
121
|
+
"ui",
|
|
122
|
+
"components",
|
|
123
|
+
"fireui",
|
|
124
|
+
"component-library"
|
|
125
|
+
],
|
|
126
|
+
"author": "firerian",
|
|
127
|
+
"license": "MIT",
|
|
128
|
+
"repository": {
|
|
129
|
+
"type": "git",
|
|
130
|
+
"url": ""
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Button 组件测试
|
|
3
|
+
* @description 测试 Button 组件的功能和交互
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect } from 'vitest'
|
|
7
|
+
import { mount } from '@vue/test-utils'
|
|
8
|
+
import { h } from 'vue'
|
|
9
|
+
import FButton from './button.vue'
|
|
10
|
+
|
|
11
|
+
describe('FButton', () => {
|
|
12
|
+
// 基础渲染测试
|
|
13
|
+
describe('render', () => {
|
|
14
|
+
it('should render default button', () => {
|
|
15
|
+
const wrapper = mount(FButton, {
|
|
16
|
+
slots: { default: '按钮' },
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
expect(wrapper.text()).toContain('按钮')
|
|
20
|
+
expect(wrapper.classes()).toContain('f-button')
|
|
21
|
+
expect(wrapper.classes()).toContain('f-button--default')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should render with custom content', () => {
|
|
25
|
+
const wrapper = mount(FButton, {
|
|
26
|
+
slots: {
|
|
27
|
+
default: () => h('span', { class: 'custom-content' }, '自定义内容'),
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
expect(wrapper.find('.custom-content').exists()).toBe(true)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should have correct native type', () => {
|
|
35
|
+
const wrapper = mount(FButton, {
|
|
36
|
+
props: { nativeType: 'submit' },
|
|
37
|
+
slots: { default: '提交' },
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
expect(wrapper.attributes('type')).toBe('submit')
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// 类型测试
|
|
45
|
+
describe('type prop', () => {
|
|
46
|
+
const types = ['default', 'primary', 'success', 'warning', 'danger', 'info']
|
|
47
|
+
|
|
48
|
+
types.forEach((type) => {
|
|
49
|
+
it(`should render ${type} type`, () => {
|
|
50
|
+
const wrapper = mount(FButton, {
|
|
51
|
+
props: { type: type as any },
|
|
52
|
+
slots: { default: '按钮' },
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
expect(wrapper.classes()).toContain(`f-button--${type}`)
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 尺寸测试
|
|
61
|
+
describe('size prop', () => {
|
|
62
|
+
const sizes = ['small', 'default', 'large']
|
|
63
|
+
|
|
64
|
+
sizes.forEach((size) => {
|
|
65
|
+
it(`should render ${size} size`, () => {
|
|
66
|
+
const wrapper = mount(FButton, {
|
|
67
|
+
props: { size: size as any },
|
|
68
|
+
slots: { default: '按钮' },
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
expect(wrapper.classes()).toContain(`f-button--${size}`)
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// 状态测试
|
|
77
|
+
describe('status', () => {
|
|
78
|
+
it('should render disabled button', async () => {
|
|
79
|
+
const wrapper = mount(FButton, {
|
|
80
|
+
props: { disabled: true },
|
|
81
|
+
slots: { default: '禁用按钮' },
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
expect(wrapper.classes()).toContain('f-button--disabled')
|
|
85
|
+
expect(wrapper.attributes('disabled')).toBeDefined()
|
|
86
|
+
|
|
87
|
+
// 禁用状态下点击不应触发事件
|
|
88
|
+
await wrapper.trigger('click')
|
|
89
|
+
expect(wrapper.emitted('click')).toBeUndefined()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should render loading button', async () => {
|
|
93
|
+
const wrapper = mount(FButton, {
|
|
94
|
+
props: { loading: true },
|
|
95
|
+
slots: { default: '加载中' },
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
expect(wrapper.classes()).toContain('f-button--loading')
|
|
99
|
+
expect(wrapper.attributes('disabled')).toBeDefined()
|
|
100
|
+
|
|
101
|
+
// 检查是否显示加载图标
|
|
102
|
+
expect(wrapper.find('.f-button-loading-icon').exists()).toBe(true)
|
|
103
|
+
|
|
104
|
+
// 加载状态下点击不应触发事件
|
|
105
|
+
await wrapper.trigger('click')
|
|
106
|
+
expect(wrapper.emitted('click')).toBeUndefined()
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('should not have disabled attribute when not disabled or loading', () => {
|
|
110
|
+
const wrapper = mount(FButton, {
|
|
111
|
+
slots: { default: '按钮' },
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
expect(wrapper.attributes('disabled')).toBeUndefined()
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// 特殊样式测试
|
|
119
|
+
describe('special styles', () => {
|
|
120
|
+
it('should render circle button', () => {
|
|
121
|
+
const wrapper = mount(FButton, {
|
|
122
|
+
props: { circle: true },
|
|
123
|
+
slots: { default: '圆形' },
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
expect(wrapper.classes()).toContain('f-button--circle')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('should render block button', () => {
|
|
130
|
+
const wrapper = mount(FButton, {
|
|
131
|
+
props: { block: true },
|
|
132
|
+
slots: { default: '块级' },
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
expect(wrapper.classes()).toContain('f-button--block')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('should hide content when circle button', () => {
|
|
139
|
+
const wrapper = mount(FButton, {
|
|
140
|
+
props: { circle: true },
|
|
141
|
+
slots: { default: '内容' },
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// 圆形按钮应该隐藏内容文本
|
|
145
|
+
const contentElement = wrapper.find('.f-button-content')
|
|
146
|
+
expect(contentElement.exists()).toBe(true)
|
|
147
|
+
// 在 CSS 中通过 display: none 隐藏
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// 事件测试
|
|
152
|
+
describe('events', () => {
|
|
153
|
+
it('should emit click event', async () => {
|
|
154
|
+
const wrapper = mount(FButton, {
|
|
155
|
+
slots: { default: '按钮' },
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
await wrapper.trigger('click')
|
|
159
|
+
expect(wrapper.emitted('click')).toHaveLength(1)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('should pass click event object', async () => {
|
|
163
|
+
const wrapper = mount(FButton, {
|
|
164
|
+
slots: { default: '按钮' },
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
await wrapper.trigger('click')
|
|
168
|
+
const clickEvent = wrapper.emitted('click')![0][0]
|
|
169
|
+
expect(clickEvent).toBeInstanceOf(MouseEvent)
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('should not emit click when disabled', async () => {
|
|
173
|
+
const wrapper = mount(FButton, {
|
|
174
|
+
props: { disabled: true },
|
|
175
|
+
slots: { default: '按钮' },
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
await wrapper.trigger('click')
|
|
179
|
+
expect(wrapper.emitted('click')).toBeUndefined()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('should not emit click when loading', async () => {
|
|
183
|
+
const wrapper = mount(FButton, {
|
|
184
|
+
props: { loading: true },
|
|
185
|
+
slots: { default: '按钮' },
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
await wrapper.trigger('click')
|
|
189
|
+
expect(wrapper.emitted('click')).toBeUndefined()
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('should emit click only once per click', async () => {
|
|
193
|
+
const wrapper = mount(FButton, {
|
|
194
|
+
slots: { default: '按钮' },
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
await wrapper.trigger('click')
|
|
198
|
+
await wrapper.trigger('click')
|
|
199
|
+
|
|
200
|
+
expect(wrapper.emitted('click')).toHaveLength(2)
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
// 插槽测试
|
|
205
|
+
describe('slots', () => {
|
|
206
|
+
it('should render icon slot', () => {
|
|
207
|
+
const wrapper = mount(FButton, {
|
|
208
|
+
props: { icon: 'SearchIcon' },
|
|
209
|
+
slots: {
|
|
210
|
+
icon: () => h('span', { class: 'custom-icon' }, '🔍'),
|
|
211
|
+
default: '搜索',
|
|
212
|
+
},
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
expect(wrapper.find('.custom-icon').exists()).toBe(true)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
it('should render loading slot', () => {
|
|
219
|
+
const wrapper = mount(FButton, {
|
|
220
|
+
props: { loading: true },
|
|
221
|
+
slots: {
|
|
222
|
+
loading: () => h('span', { class: 'custom-loading' }, '加载中...'),
|
|
223
|
+
default: '按钮',
|
|
224
|
+
},
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
expect(wrapper.find('.custom-loading').exists()).toBe(true)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('should render default slot content', () => {
|
|
231
|
+
const wrapper = mount(FButton, {
|
|
232
|
+
slots: {
|
|
233
|
+
default: () => h('div', { class: 'custom-content' }, '自定义内容'),
|
|
234
|
+
},
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
expect(wrapper.find('.custom-content').exists()).toBe(true)
|
|
238
|
+
expect(wrapper.text()).toContain('自定义内容')
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('should render loading icon by default when loading', () => {
|
|
242
|
+
const wrapper = mount(FButton, {
|
|
243
|
+
props: { loading: true },
|
|
244
|
+
slots: { default: '按钮' },
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// 应该显示默认的 SVG 加载图标
|
|
248
|
+
expect(wrapper.find('.f-button-loading-svg').exists()).toBe(true)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('should render custom loading icon when loadingIcon prop is provided', () => {
|
|
252
|
+
const wrapper = mount(FButton, {
|
|
253
|
+
props: {
|
|
254
|
+
loading: true,
|
|
255
|
+
loadingIcon: '/loading.gif'
|
|
256
|
+
},
|
|
257
|
+
slots: { default: '按钮' },
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
const img = wrapper.find('.f-button-loading-img')
|
|
261
|
+
expect(img.exists()).toBe(true)
|
|
262
|
+
expect(img.attributes('src')).toBe('/loading.gif')
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// 原生属性透传测试
|
|
267
|
+
describe('native attributes', () => {
|
|
268
|
+
it('should render with nativeType="button"', () => {
|
|
269
|
+
const wrapper = mount(FButton, {
|
|
270
|
+
props: { nativeType: 'button' },
|
|
271
|
+
slots: { default: '按钮' },
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
expect(wrapper.attributes('type')).toBe('button')
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('should render with nativeType="submit"', () => {
|
|
278
|
+
const wrapper = mount(FButton, {
|
|
279
|
+
props: { nativeType: 'submit' },
|
|
280
|
+
slots: { default: '提交' },
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
expect(wrapper.attributes('type')).toBe('submit')
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('should render with nativeType="reset"', () => {
|
|
287
|
+
const wrapper = mount(FButton, {
|
|
288
|
+
props: { nativeType: 'reset' },
|
|
289
|
+
slots: { default: '重置' },
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
expect(wrapper.attributes('type')).toBe('reset')
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
// 组合测试
|
|
297
|
+
describe('combinations', () => {
|
|
298
|
+
it('should render primary large button', () => {
|
|
299
|
+
const wrapper = mount(FButton, {
|
|
300
|
+
props: {
|
|
301
|
+
type: 'primary',
|
|
302
|
+
size: 'large'
|
|
303
|
+
},
|
|
304
|
+
slots: { default: '按钮' },
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
expect(wrapper.classes()).toContain('f-button--primary')
|
|
308
|
+
expect(wrapper.classes()).toContain('f-button--large')
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('should render disabled circle button', () => {
|
|
312
|
+
const wrapper = mount(FButton, {
|
|
313
|
+
props: {
|
|
314
|
+
disabled: true,
|
|
315
|
+
circle: true
|
|
316
|
+
},
|
|
317
|
+
slots: { default: 'X' },
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
expect(wrapper.classes()).toContain('f-button--disabled')
|
|
321
|
+
expect(wrapper.classes()).toContain('f-button--circle')
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
it('should render loading success button', () => {
|
|
325
|
+
const wrapper = mount(FButton, {
|
|
326
|
+
props: {
|
|
327
|
+
type: 'success',
|
|
328
|
+
loading: true
|
|
329
|
+
},
|
|
330
|
+
slots: { default: '保存' },
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
expect(wrapper.classes()).toContain('f-button--success')
|
|
334
|
+
expect(wrapper.classes()).toContain('f-button--loading')
|
|
335
|
+
})
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
// 辅助函数测试
|
|
339
|
+
describe('helper functions', () => {
|
|
340
|
+
it('should have buttonClasses computed property', () => {
|
|
341
|
+
const wrapper = mount(FButton, {
|
|
342
|
+
props: {
|
|
343
|
+
type: 'primary',
|
|
344
|
+
size: 'large',
|
|
345
|
+
disabled: true
|
|
346
|
+
},
|
|
347
|
+
slots: { default: '按钮' },
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
const classes = wrapper.classes()
|
|
351
|
+
expect(classes).toContain('f-button')
|
|
352
|
+
expect(classes).toContain('f-button--primary')
|
|
353
|
+
expect(classes).toContain('f-button--large')
|
|
354
|
+
expect(classes).toContain('f-button--disabled')
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
})
|