From 889b1be12511bebdf0467884ee65d2f9c2f04d0c Mon Sep 17 00:00:00 2001 From: xuchunxiao <522784020@qq.com> Date: Thu, 10 Jun 2021 11:23:43 +0800 Subject: [PATCH 01/10] Rate component accept onMouseEnter and onMouseLeave event --- src/Rate.tsx | 21 ++++- tests/simple.spec.js | 203 ++++++++++++------------------------------- 2 files changed, 75 insertions(+), 149 deletions(-) diff --git a/src/Rate.tsx b/src/Rate.tsx index 5048cc1..5dc753c 100644 --- a/src/Rate.tsx +++ b/src/Rate.tsx @@ -3,7 +3,8 @@ import findDOMNode from 'rc-util/lib/Dom/findDOMNode'; import classNames from 'classnames'; import KeyCode from 'rc-util/lib/KeyCode'; import { getOffsetLeft } from './util'; -import Star, { StarProps } from './Star'; +import type { StarProps } from './Star'; +import Star from './Star'; function noop() {} @@ -25,6 +26,8 @@ export interface RateProps { onFocus?: () => void; onBlur?: () => void; onKeyDown?: React.KeyboardEventHandler; + onMouseEnter?: React.MouseEventHandler; + onMouseLeave?: React.MouseEventHandler; autoFocus?: boolean; direction?: string; } @@ -135,7 +138,7 @@ class Rate extends React.Component { } }; - onKeyDown: React.KeyboardEventHandler = event => { + onKeyDown: React.KeyboardEventHandler = (event) => { const { keyCode } = event; const { count, allowHalf, onKeyDown, direction } = this.props; const reverse = direction === 'rtl'; @@ -253,6 +256,8 @@ class Rate extends React.Component { characterRender, tabIndex, direction, + onMouseEnter, + onMouseLeave, } = this.props; const { value, hoverValue, focused } = this.state; const stars = []; @@ -283,10 +288,20 @@ class Rate extends React.Component {
    { + if (onMouseLeave) { + onMouseLeave(e); + } + this.onMouseLeave(); + } + } tabIndex={disabled ? -1 : tabIndex} onFocus={disabled ? null : this.onFocus} onBlur={disabled ? null : this.onBlur} + onMouseEnter={onMouseEnter} onKeyDown={disabled ? null : this.onKeyDown} ref={this.saveRate} role="radiogroup" diff --git a/tests/simple.spec.js b/tests/simple.spec.js index 94bbf30..77b9cb3 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -36,87 +36,45 @@ describe('rate', () => { it('click works', () => { const handleChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(1) - .simulate('click'); + wrapper.find('li > div').at(1).simulate('click'); expect(handleChange).toBeCalledWith(2); }); it('click works in RTL', () => { const handleChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(1) - .simulate('click'); + wrapper.find('li > div').at(1).simulate('click'); expect(handleChange).toBeCalledWith(2); }); it('support mouseMove', () => { const wrapper = mount(); - wrapper - .find('li > div') - .at(1) - .simulate('mouseMove'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-full'), - ).toBe(true); + wrapper.find('li > div').at(1).simulate('mouseMove'); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-full')).toBe(true); }); it('support mouseMove in RTL', () => { const wrapper = mount(); - wrapper - .find('li > div') - .at(1) - .simulate('mouseMove'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-full'), - ).toBe(true); + wrapper.find('li > div').at(1).simulate('mouseMove'); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-full')).toBe(true); }); it('support focus and blur', () => { const wrapper = mount(); wrapper.simulate('focus'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(true); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(true); wrapper.simulate('blur'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(false); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(false); }); it('support focus and blur in RTL', () => { const wrapper = mount(); wrapper.simulate('focus'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(true); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(true); wrapper.simulate('blur'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(false); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(false); }); describe('support keyboard', () => { @@ -133,10 +91,7 @@ describe('rate', () => { it('enter', () => { const handleChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(2) - .simulate('keyDown', { keyCode: KeyCode.ENTER }); + wrapper.find('li > div').at(2).simulate('keyDown', { keyCode: KeyCode.ENTER }); expect(handleChange).toBeCalledWith(3); }); }); @@ -155,10 +110,7 @@ describe('rate', () => { it('enter', () => { const handleChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(2) - .simulate('keyDown', { keyCode: KeyCode.ENTER }); + wrapper.find('li > div').at(2).simulate('keyDown', { keyCode: KeyCode.ENTER }); expect(handleChange).toBeCalledWith(3); }); }); @@ -184,54 +136,26 @@ describe('rate', () => { it('click works', () => { const wrapper = mount(); - wrapper - .find('li > div') - .at(2) - .simulate('click'); - expect( - wrapper - .find('li') - .at(4) - .hasClass('rc-rate-star-full'), - ).toBe(false); + wrapper.find('li > div').at(2).simulate('click'); + expect(wrapper.find('li').at(4).hasClass('rc-rate-star-full')).toBe(false); }); it('support focus and blur', () => { const wrapper = mount(); wrapper.simulate('focus'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(true); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(true); wrapper.simulate('blur'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(false); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(false); }); it('support focus and blur in RTL', () => { const wrapper = mount(); wrapper.simulate('focus'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(true); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(true); wrapper.simulate('blur'); - expect( - wrapper - .find('li') - .at(1) - .hasClass('rc-rate-star-focused'), - ).toBe(false); + expect(wrapper.find('li').at(1).hasClass('rc-rate-star-focused')).toBe(false); }); it('support keyboard', () => { @@ -259,12 +183,9 @@ describe('rate', () => { it('hover Rate of allowHalf', () => { const onHoverChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(1) - .simulate('mouseMove', { - pageX: -1, - }); + wrapper.find('li > div').at(1).simulate('mouseMove', { + pageX: -1, + }); expect(onHoverChange).toHaveBeenCalledWith(1.5); }); @@ -273,12 +194,9 @@ describe('rate', () => { const wrapper = mount( , ); - wrapper - .find('li > div') - .at(1) - .simulate('mouseMove', { - pageX: 1, - }); + wrapper.find('li > div').at(1).simulate('mouseMove', { + pageX: 1, + }); expect(onHoverChange).toHaveBeenCalledWith(1.5); }); }); @@ -289,59 +207,28 @@ describe('rate', () => { const wrapper = mount( , ); - wrapper - .find('li > div') - .at(3) - .simulate('click'); - wrapper - .find('li > div') - .at(3) - .simulate('click'); + wrapper.find('li > div').at(3).simulate('click'); + wrapper.find('li > div').at(3).simulate('click'); expect(handleChange).toBeCalledWith(4); }); it('allowClear is true', () => { const handleChange = jest.fn(); const wrapper = mount(); - wrapper - .find('li > div') - .at(3) - .simulate('click'); + wrapper.find('li > div').at(3).simulate('click'); expect(handleChange).toBeCalledWith(0); }); it('cleaned star disable hover', () => { const wrapper = mount(); - wrapper - .find('li > div') - .at(3) - .simulate('click'); - wrapper - .find('li > div') - .at(3) - .simulate('mouseMove'); - expect( - wrapper - .find('li') - .at(3) - .hasClass('rc-rate-star-full'), - ).toBe(false); + wrapper.find('li > div').at(3).simulate('click'); + wrapper.find('li > div').at(3).simulate('mouseMove'); + expect(wrapper.find('li').at(3).hasClass('rc-rate-star-full')).toBe(false); }); it('cleaned star reset', () => { const wrapper = mount(); - wrapper - .find('li > div') - .at(3) - .simulate('click'); + wrapper.find('li > div').at(3).simulate('click'); wrapper.find('ul').simulate('mouseLeave'); - wrapper - .find('li > div') - .at(3) - .simulate('mouseMove'); - expect( - wrapper - .find('li') - .at(3) - .hasClass('rc-rate-star-full'), - ).toBe(true); + wrapper.find('li > div').at(3).simulate('mouseMove'); + expect(wrapper.find('li').at(3).hasClass('rc-rate-star-full')).toBe(true); }); }); @@ -400,5 +287,29 @@ describe('rate', () => { wrapper.simulate('keydown'); expect(onKeyDown).toHaveBeenCalled(); }); + + // https://github.com/ant-design/ant-design/issues/30940 + it('range picker should accept onMouseEnter and onMouseLeave event when Rate component is diabled', () => { + const handleMouseEnter = jest.fn(); + const handleMouseLeave = jest.fn(); + const wrapper = mount( + , + ); + wrapper.simulate('mouseenter'); + expect(handleMouseEnter).toHaveBeenCalled(); + wrapper.simulate('mouseleave'); + expect(handleMouseLeave).toHaveBeenCalled(); + }); + it('range picker should accept onMouseEnter and onMouseLeave event when Rate component is not diabled', () => { + const handleMouseEnter = jest.fn(); + const handleMouseLeave = jest.fn(); + const wrapper = mount( + , + ); + wrapper.simulate('mouseenter'); + expect(handleMouseEnter).toHaveBeenCalled(); + wrapper.simulate('mouseleave'); + expect(handleMouseLeave).toHaveBeenCalled(); + }); }); }); From 4dcc3fd3d4cdb8929bf755e32e6eae89bc387bc2 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 21:42:05 +0800 Subject: [PATCH 02/10] Update Rate.tsx --- src/Rate.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Rate.tsx b/src/Rate.tsx index f322eb9..064de1b 100644 --- a/src/Rate.tsx +++ b/src/Rate.tsx @@ -24,6 +24,7 @@ export interface RateProps onKeyDown?: React.KeyboardEventHandler; onMouseEnter?: React.MouseEventHandler; onMouseLeave?: React.MouseEventHandler; + id?: string; autoFocus?: boolean; direction?: string; } @@ -39,6 +40,7 @@ function Rate(props: RateProps, ref: React.Ref) { prefixCls = 'rc-rate', className, style, + id, // Value defaultValue, @@ -241,6 +243,7 @@ function Rate(props: RateProps, ref: React.Ref) { [`${prefixCls}-rtl`]: direction === 'rtl', })} style={style} + id={id} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeaveCallback} tabIndex={disabled ? -1 : tabIndex} From 1935dc70017b902242079a2a13edad0d9b05c745 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 21:48:07 +0800 Subject: [PATCH 03/10] Update Rate.tsx --- src/Rate.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Rate.tsx b/src/Rate.tsx index 064de1b..d2aeabd 100644 --- a/src/Rate.tsx +++ b/src/Rate.tsx @@ -67,8 +67,25 @@ function Rate(props: RateProps, ref: React.Ref) { onKeyDown, onMouseEnter, onMouseLeave, + + ...restProps, } = props; + const dataOrAriaAttributeProps = Object.keys(restProps).reduce( + (prev, key) => { + if ( + key.substr(0, 5) === 'data-' || + key.substr(0, 5) === 'aria-' || + key === 'role' + ) { + // eslint-disable-next-line no-param-reassign + prev[key] = this.props[key]; + } + return prev; + }, + {}, + ); + const [getStarRef, setStarRef] = useRefs(); const rateRef = React.useRef(null); @@ -252,6 +269,7 @@ function Rate(props: RateProps, ref: React.Ref) { onKeyDown={disabled ? null : onInternalKeyDown} ref={rateRef} role="radiogroup" + {...dataOrAriaAttributeProps} > {starNodes}
From 0ed8a10a0dfb333b21fd1992cf4fe8aaa13d3c73 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 21:58:40 +0800 Subject: [PATCH 04/10] Update Rate.tsx --- src/Rate.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Rate.tsx b/src/Rate.tsx index d2aeabd..34c38c8 100644 --- a/src/Rate.tsx +++ b/src/Rate.tsx @@ -68,7 +68,7 @@ function Rate(props: RateProps, ref: React.Ref) { onMouseEnter, onMouseLeave, - ...restProps, + ...restProps } = props; const dataOrAriaAttributeProps = Object.keys(restProps).reduce( @@ -158,13 +158,13 @@ function Rate(props: RateProps, ref: React.Ref) { onHoverChange?.(nextHoverValue); }; - const onMouseLeaveCallback = (event: React.MouseEvent) => { + const onMouseLeaveCallback = (event?: React.MouseEvent) => { if (!disabled) { setHoverValue(null); setCleanedValue(null); onHoverChange?.(undefined); } - if (e) { + if (event) { onMouseLeave?.(event); } }; From d7e65ddb73873d6a3e46a8a9d3f42021430240e2 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:16:32 +0800 Subject: [PATCH 05/10] Update simple.spec.js --- tests/simple.spec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/simple.spec.js b/tests/simple.spec.js index b9763b2..65865e0 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -302,6 +302,7 @@ describe('rate', () => { wrapper.simulate('mouseleave'); expect(handleMouseLeave).toHaveBeenCalled(); }); + it('range picker should accept onMouseEnter and onMouseLeave event when Rate component is not diabled', () => { const handleMouseEnter = jest.fn(); const handleMouseLeave = jest.fn(); @@ -314,4 +315,19 @@ describe('rate', () => { expect(handleMouseLeave).toHaveBeenCalled(); }); }); + + describe('html attributes', () => { + it('data-* and aria-* and role', () => { + const onKeyDown = jest.fn(); + const wrapper = mount(); + expect(wrapper.getDOMNode().getAttribute('data-number').toBe('1')); + expect(wrapper.getDOMNode().getAttribute('aria-label').toBe('label')); + expect(wrapper.getDOMNode().getAttribute('role').toBe('button')); + }); + + it('id', () => { + const wrapper = mount(); + expect(wrapper.getDOMNode().getAttribute(id).toBe('myrate')); + }); + }); }); From b591a175b5e47d8fa0b5b6b5792708b3cf222cbd Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:16:55 +0800 Subject: [PATCH 06/10] Update tests/simple.spec.js --- tests/simple.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/simple.spec.js b/tests/simple.spec.js index 65865e0..9471d39 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -318,7 +318,6 @@ describe('rate', () => { describe('html attributes', () => { it('data-* and aria-* and role', () => { - const onKeyDown = jest.fn(); const wrapper = mount(); expect(wrapper.getDOMNode().getAttribute('data-number').toBe('1')); expect(wrapper.getDOMNode().getAttribute('aria-label').toBe('label')); From e057cbf002e89ff48752ca9f1441ee79b87b3044 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:22:50 +0800 Subject: [PATCH 07/10] Update src/Rate.tsx --- src/Rate.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rate.tsx b/src/Rate.tsx index 34c38c8..b0a1143 100644 --- a/src/Rate.tsx +++ b/src/Rate.tsx @@ -79,7 +79,7 @@ function Rate(props: RateProps, ref: React.Ref) { key === 'role' ) { // eslint-disable-next-line no-param-reassign - prev[key] = this.props[key]; + prev[key] = restProps[key]; } return prev; }, From d409575d043011af8a81f0871df0f6414b65b08a Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:28:12 +0800 Subject: [PATCH 08/10] Update tests/simple.spec.js --- tests/simple.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/simple.spec.js b/tests/simple.spec.js index 9471d39..6e74bfb 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -326,7 +326,7 @@ describe('rate', () => { it('id', () => { const wrapper = mount(); - expect(wrapper.getDOMNode().getAttribute(id).toBe('myrate')); + expect(wrapper.getDOMNode().getAttribute('id').toBe('myrate')); }); }); }); From b518c20c9176edd313faefc65b9cbea822d22fe6 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:28:33 +0800 Subject: [PATCH 09/10] Update tests/simple.spec.js --- tests/simple.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/simple.spec.js b/tests/simple.spec.js index 6e74bfb..e8a9333 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -323,7 +323,6 @@ describe('rate', () => { expect(wrapper.getDOMNode().getAttribute('aria-label').toBe('label')); expect(wrapper.getDOMNode().getAttribute('role').toBe('button')); }); - it('id', () => { const wrapper = mount(); expect(wrapper.getDOMNode().getAttribute('id').toBe('myrate')); From f0cce7670201ea88dbfe376a408eabd4edb46418 Mon Sep 17 00:00:00 2001 From: afc163 Date: Sat, 27 May 2023 22:29:36 +0800 Subject: [PATCH 10/10] Apply suggestions from code review --- tests/simple.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/simple.spec.js b/tests/simple.spec.js index e8a9333..5601199 100644 --- a/tests/simple.spec.js +++ b/tests/simple.spec.js @@ -319,13 +319,13 @@ describe('rate', () => { describe('html attributes', () => { it('data-* and aria-* and role', () => { const wrapper = mount(); - expect(wrapper.getDOMNode().getAttribute('data-number').toBe('1')); - expect(wrapper.getDOMNode().getAttribute('aria-label').toBe('label')); - expect(wrapper.getDOMNode().getAttribute('role').toBe('button')); + expect(wrapper.getDOMNode().getAttribute('data-number')).toBe('1'); + expect(wrapper.getDOMNode().getAttribute('aria-label')).toBe('label'); + expect(wrapper.getDOMNode().getAttribute('role')).toBe('button'); }); it('id', () => { const wrapper = mount(); - expect(wrapper.getDOMNode().getAttribute('id').toBe('myrate')); + expect(wrapper.getDOMNode().getAttribute('id')).toBe('myrate'); }); }); });