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: ` +
+ +
当前有{{ value }}颗星
+
+ `, + 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: ` +
+ +
当前有{{ value }}颗星
+
+ `, + 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 + + ``` -在页面中使用: +::: -```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 只能设置其中一个 | [动态模式-自定义](#动态模式-自定义) |