diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-09-04 09:24:33 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-09-04 20:20:56 +0200 |
commit | 0928b5632fd08edb53614a125bc52b3f5bee2b7d (patch) | |
tree | 53114ad776c0b5aa117722b9d96550ae60aa04c1 /server/sonar-web/src/main/js/components/controls | |
parent | f6fd6fb056ca6c3de3637cfeafb53c30815ee12d (diff) | |
download | sonarqube-0928b5632fd08edb53614a125bc52b3f5bee2b7d.tar.gz sonarqube-0928b5632fd08edb53614a125bc52b3f5bee2b7d.zip |
SONAR-11216 fix hiding tooltips (#679)
Diffstat (limited to 'server/sonar-web/src/main/js/components/controls')
3 files changed, 34 insertions, 39 deletions
diff --git a/server/sonar-web/src/main/js/components/controls/Tooltip.tsx b/server/sonar-web/src/main/js/components/controls/Tooltip.tsx index 9e25efbdb5c..802be846f8b 100644 --- a/server/sonar-web/src/main/js/components/controls/Tooltip.tsx +++ b/server/sonar-web/src/main/js/components/controls/Tooltip.tsx @@ -67,8 +67,8 @@ export default function Tooltip(props: Props) { export class TooltipInner extends React.Component<Props, State> { throttledPositionTooltip: (() => void); - mouseEnterInterval?: number; - mouseLeaveInterval?: number; + mouseEnterTimeout?: number; + mouseLeaveTimeout?: number; tooltipNode?: HTMLElement | null; mounted = false; mouseIn = false; @@ -118,7 +118,7 @@ export class TooltipInner extends React.Component<Props, State> { componentWillUnmount() { this.mounted = false; this.removeEventListeners(); - this.clearIntervals(); + this.clearTimeouts(); } addEventListeners = () => { @@ -131,9 +131,9 @@ export class TooltipInner extends React.Component<Props, State> { window.removeEventListener('scroll', this.throttledPositionTooltip); }; - clearIntervals = () => { - window.clearInterval(this.mouseEnterInterval); - window.clearInterval(this.mouseLeaveInterval); + clearTimeouts = () => { + window.clearTimeout(this.mouseEnterTimeout); + window.clearTimeout(this.mouseLeaveTimeout); }; isVisible = () => { @@ -206,9 +206,12 @@ export class TooltipInner extends React.Component<Props, State> { }; handleMouseEnter = () => { - this.mouseEnterInterval = window.setTimeout(() => { + this.mouseEnterTimeout = window.setTimeout(() => { if (this.mounted) { - if (this.props.visible === undefined) { + // for some reason even after the `this.mouseEnterTimeout` is cleared, it still triggers + // to workaround this issue, check that its value is not `undefined` + // (if it's `undefined`, it means the timer has been reset) + if (this.props.visible === undefined && this.mouseEnterTimeout !== undefined) { this.setState({ visible: true }); } } @@ -220,13 +223,13 @@ export class TooltipInner extends React.Component<Props, State> { }; handleMouseLeave = () => { - if (this.mouseEnterInterval !== undefined) { - window.clearInterval(this.mouseEnterInterval); - this.mouseEnterInterval = undefined; + if (this.mouseEnterTimeout !== undefined) { + window.clearTimeout(this.mouseEnterTimeout); + this.mouseEnterTimeout = undefined; } if (!this.mouseIn) { - this.mouseLeaveInterval = window.setTimeout(() => { + this.mouseLeaveTimeout = window.setTimeout(() => { if (this.mounted) { if (this.props.visible === undefined && !this.mouseIn) { this.setState({ visible: false }); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/Tooltip-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/Tooltip-test.tsx index 139a4c7b1be..a6c2a759e88 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/Tooltip-test.tsx +++ b/server/sonar-web/src/main/js/components/controls/__tests__/Tooltip-test.tsx @@ -52,16 +52,33 @@ it('should open & close', () => { wrapper.find('#tooltip').simulate('mouseenter'); jest.runOnlyPendingTimers(); wrapper.update(); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('TooltipPortal').exists()).toBe(true); expect(onShow).toBeCalled(); wrapper.find('#tooltip').simulate('mouseleave'); jest.runOnlyPendingTimers(); wrapper.update(); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('TooltipPortal').exists()).toBe(false); expect(onHide).toBeCalled(); }); +it('should not open when mouse goes away quickly', () => { + const onShow = jest.fn(); + const onHide = jest.fn(); + const wrapper = shallow( + <TooltipInner onHide={onHide} onShow={onShow} overlay={<span id="overlay" />}> + <div id="tooltip" /> + </TooltipInner> + ); + + wrapper.find('#tooltip').simulate('mouseenter'); + wrapper.find('#tooltip').simulate('mouseleave'); + jest.runOnlyPendingTimers(); + wrapper.update(); + + expect(wrapper.find('TooltipPortal').exists()).toBe(false); +}); + it('should not render tooltip without overlay', () => { const wrapper = shallow( <Tooltip overlay={undefined}> diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Tooltip-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Tooltip-test.tsx.snap index 6c0f293b850..cec95565950 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Tooltip-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Tooltip-test.tsx.snap @@ -12,31 +12,6 @@ exports[`should not render empty tooltips 2`] = ` /> `; -exports[`should open & close 1`] = ` -<React.Fragment> - <div - id="tooltip" - onMouseEnter={[Function]} - onMouseLeave={[Function]} - /> - <TooltipPortal> - <ScreenPositionFixer - ready={false} - /> - </TooltipPortal> -</React.Fragment> -`; - -exports[`should open & close 2`] = ` -<React.Fragment> - <div - id="tooltip" - onMouseEnter={[Function]} - onMouseLeave={[Function]} - /> -</React.Fragment> -`; - exports[`should render 1`] = ` <React.Fragment> <div |