diff --git a/devui/rate/__tests__/rate.spec.ts b/devui/rate/__tests__/rate.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..647572d45a8f59283d7b3ffb3b7a8f2bad00da5e
--- /dev/null
+++ b/devui/rate/__tests__/rate.spec.ts
@@ -0,0 +1,135 @@
+import { mount } from '@vue/test-utils'
+import { ref, nextTick } from 'vue'
+import DRate from '../src/rate'
+
+describe('rate', () => {
+ describe('rate basic', () => {
+ const TestComponent = {
+ components: {
+ 'd-rate': DRate,
+ },
+ template: `
+
+
+
+ `,
+ setup() {
+ const value = ref(0)
+
+ return {
+ value,
+ }
+ },
+ }
+ const wrapper = mount(TestComponent)
+ it('Rate demo has created successfully', async () => {
+ expect(wrapper).toBeTruthy()
+ })
+
+ it('Rate should have content', () => {
+ const container = wrapper.find('.devui-star-container')
+ expect(container.exists()).toBeTruthy()
+ })
+ })
+
+ describe('rate change', () => {
+ it('Rate can be changed', async () => {
+ const wrapper = mount({
+ components: {
+ 'd-rate': DRate,
+ },
+ template: `
+
+ `,
+ setup() {
+ const value = ref(0)
+
+ return {
+ value,
+ }
+ },
+ })
+ await nextTick()
+
+ const starEles = wrapper.findAll('.devui-star-align')
+
+ const container = wrapper.find('.devui-star-container')
+ const firstStarEle = starEles[0]
+ const thirdStarEle = starEles[2]
+ const fourthStarEle = starEles[3]
+
+ expect(starEles.length).toBe(5)
+
+ await fourthStarEle.trigger('mouseover')
+
+ expect(
+ fourthStarEle.find('.devui-star-color-active').attributes('style')
+ ).toBe('width: 100%;')
+
+ await container.trigger('mouseleave')
+ expect(
+ fourthStarEle.find('.devui-star-color-active').attributes('style')
+ ).toBe('width: 0px;')
+ expect(wrapper.find('.count').html()).toContain('0')
+
+ await firstStarEle.trigger('click')
+
+ expect(wrapper.find('.count').html()).toContain('1')
+
+ await thirdStarEle.trigger('click')
+ expect(wrapper.find('.count').html()).toContain('3')
+
+ await container.trigger('mouseleave')
+ expect(
+ fourthStarEle.find('.devui-star-color-active').attributes('style')
+ ).toBe('width: 0px;')
+ expect(wrapper.find('.count').html()).toContain('3')
+ })
+ })
+
+ describe('read only', () => {
+ const TestComponent = {
+ components: {
+ 'd-rate': DRate,
+ },
+ template: `
+
+ `,
+ setup() {
+ const value = ref(3)
+
+ return {
+ value,
+ }
+ },
+ }
+ const wrapper = mount(TestComponent)
+
+ it('Rate should have content', async () => {
+ expect(wrapper.find('.devui-star-container').exists()).toBeTruthy()
+ })
+
+ it('Rate should not be changed', async () => {
+ const starEles = wrapper.findAll('.devui-star-align')
+
+ const firstStarEle = starEles[0]
+ const thirdStarEle = starEles[2]
+ const fourthStarEle = starEles[3]
+
+ await firstStarEle.trigger('click')
+ expect(wrapper.find('.count').html()).toContain('3')
+
+ await thirdStarEle.trigger('click')
+ expect(wrapper.find('.count').html()).toContain('3')
+
+ await fourthStarEle.trigger('click')
+ expect(wrapper.find('.count').html()).toContain('3')
+ })
+ })
+})
diff --git a/devui/rate/src/rate.scss b/devui/rate/src/rate.scss
index 0c54f08b19885be73c44d902ef92f533130848a4..e8790c9393c9b9b554112fd58631b7a90b1cfc1d 100644
--- a/devui/rate/src/rate.scss
+++ b/devui/rate/src/rate.scss
@@ -60,6 +60,10 @@
color: $devui-dividing-line;
line-height: 1.5;
+ .icon {
+ color: $devui-dividing-line !important;
+ }
+
svg g {
fill: $devui-dividing-line;
}
diff --git a/devui/rate/src/rate.tsx b/devui/rate/src/rate.tsx
index b0b6a53ecd80020fa57fab3a4e1338d77f1046b1..7b8eeeb0d2f81ec745b41d8472bfeb2147206a79 100644
--- a/devui/rate/src/rate.tsx
+++ b/devui/rate/src/rate.tsx
@@ -1,80 +1,80 @@
-import { defineComponent, onMounted, reactive, ref } from 'vue';
-import { rateProps } from './use-rate';
-import './rate.scss';
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { rateProps } from './use-rate'
+import './rate.scss'
export default defineComponent({
name: 'DRate',
props: rateProps,
- emits: ['change', 'update:value'],
+ emits: ['change', 'update:modelValue'],
setup(props, ctx) {
- const totalLevelArray = reactive[]>([]);
- const chooseValue = ref(0);
+ const totalLevelArray = reactive[]>([])
+ const chooseValue = ref(0)
// 根据mouseMove,mouseLeave,select等操作,改变颜色与是否选中
const setChange = (start: number, end: number, width: string) => {
for (let i = start; i < end; i++) {
- totalLevelArray[i]['width'] = width;
+ totalLevelArray[i]['width'] = width
}
- };
+ }
// 初始化设置
const initRating = () => {
- if (!props.value) {
- return;
+ if (!props.modelValue) {
+ return
}
- chooseValue.value = props.value - 1;
- const halfStar = chooseValue.value % 1;
- const intCurrentLevel = Math.floor(chooseValue.value);
- setChange(0, intCurrentLevel + 1, '100%');
+ chooseValue.value = props.modelValue - 1
+ const halfStar = chooseValue.value % 1
+ const intCurrentLevel = Math.floor(chooseValue.value)
+ setChange(0, intCurrentLevel + 1, '100%')
if (halfStar > 0) {
- totalLevelArray[intCurrentLevel + 1]['width'] = halfStar * 100 + '%';
- setChange(intCurrentLevel + 2, props.count, '0');
+ totalLevelArray[intCurrentLevel + 1]['width'] = halfStar * 100 + '%'
+ setChange(intCurrentLevel + 2, props.count, '0')
} else {
- setChange(intCurrentLevel + 1, props.count, '0');
+ setChange(intCurrentLevel + 1, props.count, '0')
}
- };
+ }
onMounted(() => {
for (let i = 0; i < props.count; i++) {
- totalLevelArray.push({ width: '0' });
+ totalLevelArray.push({ width: '0' })
}
- initRating();
- });
+ initRating()
+ })
const hoverToggle = (_, index: number, reset = false) => {
if (props.read) {
- return;
+ return
}
if (reset) {
if (chooseValue.value >= 0) {
- setChange(0, chooseValue.value + 1, '100%');
- setChange(chooseValue.value + 1, props.count, '0');
+ setChange(0, chooseValue.value + 1, '100%')
+ setChange(chooseValue.value + 1, props.count, '0')
} else {
- setChange(0, props.count, '0');
+ setChange(0, props.count, '0')
}
} else {
- setChange(0, index + 1, '100%');
- setChange(index + 1, props.count, '0');
+ setChange(0, index + 1, '100%')
+ setChange(index + 1, props.count, '0')
}
- };
+ }
const selectValue = (index: number) => {
if (props.read) {
- return;
+ return
}
- setChange(0, index + 1, '100%');
- setChange(index + 1, props.count, '0');
- chooseValue.value = index;
- props.onChange && props.onChange(index + 1);
- props.onTouched && props.onTouched();
- ctx.emit('update:value', index + 1);
- };
+ setChange(0, index + 1, '100%')
+ setChange(index + 1, props.count, '0')
+ chooseValue.value = index
+ props.onChange && props.onChange(index + 1)
+ props.onTouched && props.onTouched()
+ ctx.emit('update:modelValue', index + 1)
+ }
return {
totalLevelArray,
chooseValue,
hoverToggle,
selectValue,
- };
+ }
},
render() {
const {
@@ -87,7 +87,7 @@ export default defineComponent({
color,
hoverToggle,
selectValue,
- } = this;
+ } = this
return (
hoverToggle(e, index)}
onClick={() => selectValue(index)}
>
-
- {character}
- {!icon && !character && (
+ {icon && !character && (
+
+
+
+ )}
+ {character && !icon && (
+ {character}
+ )}
+ {!icon && !character && (
+
- )}
-
-
- {character}
- {!icon && !character && (
+
+ )}
+ {icon && !character && (
+
+
+
+ )}
+ {character && !icon && (
+
+ {character}
+
+ )}
+ {!character && !icon && (
+
- )}
-
+
+ )}
))}
- );
+ )
},
-});
+})
diff --git a/devui/rate/src/use-rate.ts b/devui/rate/src/use-rate.ts
index 8adf7317a88b884c41a272af8b2a4d52281679ad..c62c7a1ca6f58dc2bfba1d554827b1e23065c035 100644
--- a/devui/rate/src/use-rate.ts
+++ b/devui/rate/src/use-rate.ts
@@ -1,7 +1,8 @@
-import { PropType } from 'vue';
+import { PropType } from 'vue'
+type RateStatusType = PropType<'success' | 'warning' | 'error'>
export const rateProps = {
- value: {
+ modelValue: {
type: Number,
},
read: {
@@ -13,7 +14,7 @@ export const rateProps = {
default: 5,
},
type: {
- type: String as PropType<'success' | 'warning' | 'error'>,
+ type: String as RateStatusType,
default: '',
},
color: {
@@ -36,4 +37,4 @@ export const rateProps = {
type: Function as PropType<() => void>,
default: undefined,
},
-};
+}
diff --git a/jest.config.js b/jest.config.js
index e81cdbd1ee287f79f30af5b35a9ace0ff2a71ee7..5fcd4828d69687c9380fc1d57a44e651ff84225e 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,19 +1,19 @@
module.exports = {
-
// Automatically clear mock calls and instances between every test
clearMocks: true,
// A map from regular expressions to paths to transformers
transform: {
'^.+\\.(ts|tsx|js|jsx)$': [
- 'babel-jest', {
+ 'babel-jest',
+ {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
- ['@babel/preset-typescript']
+ ['@babel/preset-typescript'],
],
- plugins: ['@vue/babel-plugin-jsx']
- }
- ]
+ plugins: ['@vue/babel-plugin-jsx'],
+ },
+ ],
},
// The glob patterns Jest uses to detect test files
@@ -32,5 +32,6 @@ module.exports = {
testPathIgnorePatterns: ['/node_modules/'],
// The test environment that will be used for testing
- testEnvironment: 'jest-environment-jsdom'
-};
+ testEnvironment: 'jest-environment-jsdom',
+ setupFiles: ['/jest.setup.js'],
+}
diff --git a/jest.setup.js b/jest.setup.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5a273459680efa81784f858753098bbc55d23a9
--- /dev/null
+++ b/jest.setup.js
@@ -0,0 +1,5 @@
+import { config } from '@vue/test-utils'
+import Icon from './devui/icon/src/icon'
+config.global.components = {
+ 'd-icon': Icon,
+}
diff --git a/sites/components/rate/index.md b/sites/components/rate/index.md
index 09937b05acb482e34a6ec00f6226226194e3930b..021bf9cb3ef8ec7bd820c0023b03ab2dfce4ec2d 100644
--- a/sites/components/rate/index.md
+++ b/sites/components/rate/index.md
@@ -7,106 +7,132 @@
### Demo
-
-
-```html
-
+### 只读模式
+
+:::demo
+
+```vue
+
+
+
+
```
-
+:::
-```html
-
+### 动态模式
+
+:::demo
+
+```vue
+
+
+
+
```
-
-
-```html
-
+:::
+
+### 动态模式-自定义
+
+:::demo
+
+```vue
+
+
+
+
```
-
- 使用type参数
-
+:::
+
+### 使用 type 参数
+
+:::demo
+
+```vue
+
-
+
-
+
-
+
-
-
-### 如何使用
-
-### 只读模式
-
-在 module 中引入:
-
-```ts
-import { DRate } from 'vue-devui'
+
+
```
-在页面中使用:
+:::
-```html
-
-```
+### API
-# Rate
-
-### d-rate 参数
-
-| 参数 | 类型 | 默认值 | 描述 |
-| :-------: | :-----------------------------: | :----: | :------------------------------------------------------- |
-| read | `boolean` | false | 可选,设置是否为只读模式,只读模式无法交互 |
-| count | `number` | 5 | 可选,设置总等级数 |
-| type | `'success'\|'warning'\|'error'` | -- | 可选,设置当前评分的类型,不同类型对应不同颜色 |
-| color | `string` | -- | 可选,星星颜色 |
-| icon | `string` | -- | 可选,评分图标的样式,只支持 devUI 图标库中所有图标 |
-| character | `string` | -- | 可选,评分图标的样式,icon 与 character 只能设置其中一个 |
-
-
+d-rate 参数
+
+| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo |
+| :-------: | :-----------------------------: | :----: | :------------------------------------------------------- | ----------------------------------- |
+| read | `boolean` | false | 可选,设置是否为只读模式,只读模式无法交互 | [只读模式](#只读模式) |
+| count | `number` | 5 | 可选,设置总等级数 | [只读模式](#只读模式) |
+| type | `'success'\|'warning'\|'error'` | -- | 可选,设置当前评分的类型,不同类型对应不同颜色 | [使用 type 参数](#使用-type-参数) |
+| color | `string` | -- | 可选,星星颜色 | [动态模式-自定义](#动态模式-自定义) |
+| icon | `string` | -- | 可选,评分图标的样式,只支持 devUI 图标库中所有图标 | [动态模式](#动态模式) |
+| character | `string` | -- | 可选,评分图标的样式,icon 与 character 只能设置其中一个 | [动态模式-自定义](#动态模式-自定义) |