aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/components/controls
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-09-04 09:24:33 +0200
committerSonarTech <sonartech@sonarsource.com>2018-09-04 20:20:56 +0200
commit0928b5632fd08edb53614a125bc52b3f5bee2b7d (patch)
tree53114ad776c0b5aa117722b9d96550ae60aa04c1 /server/sonar-web/src/main/js/components/controls
parentf6fd6fb056ca6c3de3637cfeafb53c30815ee12d (diff)
downloadsonarqube-0928b5632fd08edb53614a125bc52b3f5bee2b7d.tar.gz
sonarqube-0928b5632fd08edb53614a125bc52b3f5bee2b7d.zip
SONAR-11216 fix hiding tooltips (#679)
Diffstat (limited to 'server/sonar-web/src/main/js/components/controls')
-rw-r--r--server/sonar-web/src/main/js/components/controls/Tooltip.tsx27
-rw-r--r--server/sonar-web/src/main/js/components/controls/__tests__/Tooltip-test.tsx21
-rw-r--r--server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/Tooltip-test.tsx.snap25
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